✒hhro([email protected])


Overview

This challenge is about analyzing the compiled autoit binary. Though I knew it early and tried to figure out how to extract original script, I cannot succeed. I tried myExetoAut, autToExe and several other tools and methods, but none of them worked. So I guessed that challenge author applied some tricks to avoid it decompiled easily. After contest, my teammate told me that he heard password for decrypting inner-script always changes in every run-time. Maybe that's the cause why I couldn't decompile it.

At the time I failed to decompile it, there was two choices. One is find the way to fix the binary and decompile with tools. And the other is analysing binary itself without extracting the autoit script. I took the latter way, because both seem to have similar difficulty.

Analyze

First I searched string 'This is a third-partyblah-blah' to disable anti-debugging. Then I ran binary and referenced IAT to which function is proper to start debugging with. At last, I recoginzed GetClipboardData is used to grab the data from the process whose name is flag.txt. So I opened flag.txt with notepad and start debugging at that function.

if ( IsDebuggerPresent() )
  {
    MessageBoxA(0i64, "This is a third-party compiled AutoIt script.", Caption, 0x10u);
    return sub_14001C29C(lpFile);
  }

Next, I used xref feature of IDA for GetClipboardData and it's caller. From this try, I discovered one more interesting function sub_140012D30. It seems like function that hooks autoit-script keyword with function.

wchar_t **__fastcall sub_140012D30(_DWORD *a1, int a2)
{
  int v2; // eax

  v2 = dword_1400E661C;
  if ( !(dword_1400E661C & 1) )
  {
    v2 = dword_1400E661C | 1;
    dword_1400DDA48 = 1;
    qword_1400DDA58 = (__int64)L"ACOS";
    xmmword_1400DDA38 = (unsigned __int64)sub_140008620;
    dword_1400E661C |= 1u;
    qword_1400DDA80 = (__int64)L"ADLIBREGISTER";
    xmmword_1400DDA60 = (unsigned __int64)sub_140085C70;
    dword_1400DDA4C = 1;
    qword_1400DDAA8 = (__int64)L"ADLIBUNREGISTER";
    xmmword_1400DDA88 = (unsigned __int64)sub_140008664;
    byte_1400DDA50 = 0;
    qword_1400DDAD0 = (__int64)L"ASC";
    xmmword_1400DDAB0 = (unsigned __int64)sub_14008721C;
    dword_1400DDA70 = 1;
    qword_1400DDAF8 = (__int64)L"ASCW";
    xmmword_1400DDAD8 = (unsigned __int64)sub_140085CF8;
    dword_1400DDA74 = 1;
    qword_1400DDB20 = (__int64)L"ASIN";
    xmmword_1400DDB00 = (unsigned __int64)sub_140085D64;
    byte_1400DDA78 = 0;
...

}

I set breakpoints at every function that is hooked with STRING[.*] keyword. I guessed one of them would be used to process input string. Luckily some breakpoints are hit. Among them, sub_7FF7377EA2E4 hooked with STRINGMID is called with string argument several times. I googled about STRINGMID and noticed this function is used to substring the string(like SQL).

After then, **I inspected the argument string passed to STRINGMID function, and the result of it. Most interesting one was the length of the result string. It was 32, which is the length of md5 hexdigest. I got the feeling that it is md5sum of flag substring.

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d5db7541-ed57-461b-b62a-98c0f993d123/Untitled.png

So I parse the argument string whole, and check the length. It is 512, exactly 32x16. I input them all to md5 hash killer, and get the flag.

Flag is: p4{1_h0p3_y0u_d1dnt_vi0lat3_th3_@ut0it_lic3ns3!}