Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 232
ezio Avatar asked Mar 09 '18 13:03

ezio


1 Answers

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 '[email protected] 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.

like image 144
Martin Prikryl Avatar answered Nov 03 '22 17:11

Martin Prikryl