myAutToExe and Ruby for the win!

As I’ve mentioned maybe once or twice before, I like myAutToExe a good deal. It’s great for tinkering around with AutoIt programs that have been “secured” by compiling to tokens. In some situations, being able to decompile these scripts is an absolute necessity to allow users to check for security problems in an application. In some situations, it’s just fun to see how somebody did something. (The legality of doing this is not something I’m going to even pretend to know, so don’t ask. When in doubt, DON’T DO IT.)

Obfuscation can become a major problem, however, especially with a recent technique I’ve run into. myAutToExe does deal with obfuscation to some degree, but not as deeply as I’d like. Consider the example illustrated below:

Global $000O0O0O0O0000OOO00 = False
Global $OO0O0O0O00O0OO00OO0 = False
Global $000O0O0O0OOOOOO000O = False
Global $00OOOO0O0O00OO00O0O = False
Global $0O0O0O0O00O0OOO000O = True
Global $000O0O0O000O0O0O000 = True
Global $000O0O0OOO0O0O0O0OO = True
Global $O00O0O0O000O0O0O0OO = True
Global $000000000000000000 = "Enter your username:"
Global $0000000000000O0O00 = "Enter your password:"
Global $0000000000000O0O0OOO = "Invalid login information.  Try again."
Global $00OO000000000O0O0OOO = "Sorry"
Global $0000000000000O0O0O00 = "Thank you for your login.  I have now stolen your account, hahaha!"
Global $00OO000000000O0O0O00 = "SUCKER!!"
Global $0O00000000000O0O0OOO = 0

Func S000OOO00O000OOOO00O($00OOOO0O0O00OO00O)
  $00OO000000000O0O0O00 = "Loser!!"
  $00OO000000000O0O0OOO = "Sorry"

  if ($00OOOO0O0O00OO00O = $OO0O0O0O00O0OO00OO0) Then
    MsgBox($0O00000000000O0O0OOO, $00OO000000000O0O0OOO, $0000000000000O0O0OOO)
    MsgBox($0O00000000000O0O0OOO, $00OO000000000O0O0O00, $0000000000000O0O0O00)


Okay, we clearly know that somewhere this code is stealing our account data, but we also know that the code is useful, generally speaking. Assuming this code were buried in a listing that’s a few thousand lines long, just trying to figure it out by hand would get tedious really fast.

Well, the ruby script I’ve written takes care of all that. When it finds a global string with this particular variable pattern, it tries to figure out the best way to represent it. It may remove the variable completely and just present a raw string, or if the string is long and used in a lot of places, just give the string a useful name. Observe:

Global $g_false7 = False
Global $g_false6 = False
Global $g_false5 = False
Global $g_false4 = False
Global $g_true3 = True
Global $g_true2 = True
Global $g_true1 = True
Global $g_true0 = True
Global $g_000013_ = "SUCKER!!"
Global $g_000014_ = 0
Func S000OOO00O000OOOO00O($v_000015_)
  $g_000013_ = "Loser!!"
  if ($v_000015_ = $g_false6) Then
    MsgBox($g_000014_, "Sorry", "Invalid login information.  Try again.")
    MsgBox($g_000014_, $g_000013_, "Thank you for your login.  I have now stolen your account, hahaha!")

We were able to name all true/false values to something very simple and in-line most of the strings. It’s now very clear which code path is dangerous, and should be examined further.

The code to do this is attached. Keep in mind that it is a work in progress and I’m very likely to forget to update it here, so email me if you’re interested in the thing. Future plans include renaming functions to somehow reflect their signature, and deal with local variables that are read-only, such as those assigned to a global and then used for comparison.

If possible, I’d like to one day build a true parser, but so far lex and yacc have proven to be far too confusing to one such as myself :(

fix_names.rb – this is the main script.

lib.rb – this is the supporting library.

Copy both ruby scripts to the same directory, and run them something like this:

ruby fix_names.rb <input_file> <output_file>

I hope this is useful!

8 Replies to “myAutToExe and Ruby for the win!”

  1. Also note that the “unknown” variables are names in a very set format: $g_xxxxxx_ for globals and $v_xxxxxx_ for locals. This is to help facilitate other scripting to do more interesting things with a guaranteed pattern.

  2. Yeah I also had this idea and finally released it in the latest myAutToExe build(104) -> I call that tool ‘RegEx Renamer’ – you can access it with myAutToExe with F11

    Let’s say you have an obfuscated source like this Global $OO0O0O0O00O0OO00OO0 = False Global $000O0O0O0OOOOOO000O = False Global $00OOOO0O0O00OO00O0O = False Global $0O0O0O0O00O0OOO000O = True

    you can rename the vars to some more friendly names by entering this: “\$[O0]{19}\b” -> “$gENABLE” ; Replaces $OO0O0O0O00O0OO00OO0 with with $gENABLE0001…

    Global $gENABLE0001 = False Global $gENABLE0002 = False Global $gENABLE0003 = False

  3. Great program!

    The only complaint that I have is that I’m trying to decompile a rather large script, and myAutToExe stops at 65535 bytes.

    Is there a way to get it to decompile a larger file, or am I simply looking in the wrong place for the output?

  4. Grendahl, the output in the myAutToExe log window is limited to 65k, but as I recall it creates a decompiled file no matter the size. It should end up putting the file in the same place as the original exe.

  5. Argh! I’m still hosting the old version 2.2 (see for the link) – but I have no idea how outdated that is at this point. It was the latest version two years ago, so it’s likely pretty bad. It will definitely not have the Regex renamer function mentioned by cw2k.

    The only good news I can think of is that it was an open-source app, so surely anybody with some time and energy could bring it up to date and repost it. I’ll keep my version up if it helps, but I’m not even sure if it supports the latest versions of AutoIt.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.