Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
442 views
in Technique[技术] by (71.8m points)

pascalscript - Disassembling strings from Inno Setup [Code]

When I compile a Inno Setup project, the [Code] section is also compiled (as Pascal executable or Pascal DLL)?

In other words, if someone unpacks a Inno Setup project, can he see the [Code] section as original source code (damn! :) ) or as compiled executable/DLL (difficult to disassemble)?

I would like to insert in the [Code] section some strings (password and keys) and I don't know if they would be easily recoverable also with little knowledge of reverse engineering.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The code is compiled into some kind of a binary representation (very roughly like .NET CIL or Java bytecode).

There's Inno Setup Unpacker (and others), which can extract the files from .exe generated by Inno Setup. It can extract the binary representation of the code to CompiledCode.bin (if you use -x -m flags).

Then you can use Inno Setup Decompiler project that is able to decompile/disassemble the CompiledCode.bin file into (pseudo) Pascal Script code. But as with a reverse engineering of .NET or Java, it won't give you exact code. The decompiled code possibly won't even compile (at least it was so the last time I tried), but it is good enough to see, what the code does. They seem to have a paid version now, which may be better than the free one I've tried some time ago. (The latest version of Inno Setup Decompiler can even directly extract code from .exe, but it was not updated to the latest version of Inno Setup [5.6.1] yet, so it did not work for me.)

(Inno Setup Decompiler site is gone, but it does not change anything about the fact that it is technically possible to decompile/disassemble the compiled code)


It is rather easy to see literal strings compiled in the code, even in the CompiledCode.bin.

For example these credentials:

Username := 'secretusername';
Password := 'mysupersecretpassword';

can be seen like this in the CompiledCode.bin file:

enter image description here

Of course, you can obfuscate the strings somehow (at least hex-encode them). But as you are hopefully aware, no matter what you do, once the (even compiled) code is on user's machine, there's really no way you can protect it absolutely.

A simple support code to store the string literal hex-encoded:

function CryptStringToBinary(
  sz: string; cch: LongWord; flags: LongWord; binary: AnsiString; 
  var size: LongWord; skip: LongWord; flagsused: LongWord): Integer;
  external 'CryptStringToBinaryW@crypt32.dll stdcall';

const
  CRYPT_STRING_HEX = $04;

function UnobfuscateString(S: string): string;
var
  Size: LongWord;
  Buffer: AnsiString;
  Len: Integer;
begin
  SetLength(Buffer, (Length(S) div 2) + 1);
  Len := Length(S);
  Size := Len div 2;
  if (CryptStringToBinary(S, Len, CRYPT_STRING_HEX, Buffer, Size, 0, 0) = 0) or
     (Size <> Length(S) div 2) then
  begin
    RaiseException('Error unobfuscating string');
  end;
  Result := Buffer;
end;

#define ObfuscateString(str S) 
  Local[0] = AddBackslash(GetEnv("TEMP")) + "ObfuscatedString.pas", 
  Local[1] = 
    "-ExecutionPolicy Bypass -Command """ + 
    "$bytes = [Text.Encoding]::ASCII.GetBytes('" + S + "'); " + 
    "$s = '''' + (($bytes | foreach { $_.ToString('X2') }) -join '') + ''''; " + 
    "Set-Content -Path '" + Local[0] + "' -Value $s;" + 
    """", 
  Exec("powershell.exe", Local[1], SourcePath, , SW_HIDE), 
  Local[2] = FileOpen(Local[0]), 
  Local[3] = FileRead(Local[2]), 
  FileClose(Local[2]), 
  DeleteFileNow(Local[0]), 
  "UnobfuscateString(" + Local[3] + ")"

(The code was tested on Unicode version of Inno Setup. Though, it can work with ASCII passwords only.)

With the help of the code above, you can write this (so you have the credentials easily editable in the source code):

Username := {#ObfuscateString("secretusername")};
Password := {#ObfuscateString("mysupersecretpassword")};

But the code will be compiled as:

Username := UnobfuscateString('736563726574757365726E616D65');
Password := UnobfuscateString('6D79737570657273656372657470617373776F7264');

You can verify that by adding this to the end of your .iss script and checking the generated Preprocessed.iss file.

#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")

So despite the credentials being readable in the source code, they won't be stored literally to the compiled code:

enter image description here

But again, this is only an obfuscation. Anyone with decent programming skills will be able to unobfuscate (decrypt) the credentials.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...