Removing ASProtect 1.22 - 1.23 Beta 21 and hacking Lemonade Tycoon v1.1.6


Removing ASProtect 1.22 - 1.23 Beta 21 and hacking Lemonade Tycoon v1.1.6
Author: ProTeuS [[email protected]]

Target: Lemonade Tycoon v1.1.6 (2100kb)
What else is needed:
1. OllyDbg + OllyDump plugin
2. ImpRec 1.6 Final
3. IDA
4. Hiew or any other hexadecimal editor
4. Beck's beer, 0.5;)

Victim

Our target is one uncomplicated toy. But the most important is that it is spoiled with "ASProtect 1.22 - 1.23 Beta 21", which PEID has kindly told us about:


The victim is still unreachable for the brutal intrigues of the disassembler;)



Search OEP

We will not use autocompackers like AsprStripperXP and therefore we will run OllyDbg and open the executable file of the program in the debugger.


Entry Point

To successfully find the original entry point of the victim, we must include memory access voilation, access violation. We go into the debugging option (by pressing Alt + O) and set the checkboxes as in the picture below:


Enabling Exception Handling

Return to the "CPU" window OllyDbg and begin to pass exceptions (by pressing Shift + F9). After 27 times (if you press Shift + F9 one more time, our program will run OEP and start), we will appear at .D405CC


The "CPU" window after processing 27 exceptions

Next, you need to put a breakpoint on the command RETN (.D40609) and order the olk to "get" to it by pressing Shift + F9 again. The final step in the OEP search will be to install a crack on Asprom access to the code section of the protected application. To do this, press Alt + M (to bring up the "Memory Map" window) and press F2 on the second section of the specified process. In our case, this is Lemonade codesection at 00401000.


A crack to access the code section

Last time press on Shift + F9 and EVERYTHING !!! We are at OEP. In order to believe it all, you can press Ctrl + A and olka will analyze the code and the disassembler listing instead of incomprehensible single-byte expressions will find the "human" form =)


And here is OEP!



We make a dump


Select the Plugins-OllyDump-Dump debugged process from the main menu and click "Dump" in the pop-up window (before removing the "Rebuild import" flag so that OllyDump does not attempt to restore the import of the dump itself).


We make a dump using the plugin OllyDump

About addresses of an entry point and sections it is possible not to worry, as OllyDump itself calculates them.

Import recovery


Simply so a dump (I named a file dumped.exe) will not be launched - it needs to restore the table of the imported functions. To do this, run ImpRec and select our explored Lemonade.exe process in it (it will still "stand" on OEP, because Olly we have not closed with it yet). In the "OEP" field, enter the address of our OEP (which is 4FB6B) and click on "IAT AutoSearch" - "Get Imports" - "Show Invalid". We get a couple of hundred undefined functions. To restore them, we will try to trace in 2 stages. In the first one, right-click on one of the highlighted undefined functions and select "Trace Level1 (Disasm)" in me. In the second step, we click on "Show invalid" again, and then restore the functions with Plugin Tracers plug-in - Asprotect 1.22.


Imprec restores import ...

After the manipulations in the log window will appear such an inscription


Import successfully restored ...

This indicates that the import is restored and you can modify our dump (dumped.exe) by clicking on the "Fix Dump"


Dump successfully modified ...

So, we got a fully working unpacked file (dumped_.exe)!


PEID confirms that aspr is successfully removed

Let's start analyzing it ...

Debugging and hacking the victim with a patch


Download the unpacked prog in the debugger. Since to enter the registration data it uses standard input windows,

The login screen

And a standard error window, it was decided in the old fashion to set breakpoints on calls to the MessageBoxA functions (output error messages) or GetDlgItemTextA (reading the input text).


Installing the bugs on the call to the MessageBoxA functions

Clicking on the "Enter License Information" button resulted in such a piece of code in the olk:


Interrupted on the output error length of the regcode (it should be equal to 20)

What was my surprise when I traced the sections checking the length of the entered registration data (.0042563A), a bunch of string and arithmetic conversions with them (.00425692) and writing the questionable keys to the registry, I did not find their subsequent reading either by installing the bryaks on the appropriate api, Nor with the help of RegMon (of course, everything was tested after the program was reloaded)! It turned out that the reason for this was the following section of the code:

  Seg000: 00425D99 call esi ;
  DialogBoxParamA ;
  Create a modal dialog box from a
 
  Seg000: 00425D99 ;
  Dialog box template resource
 
  Seg000: 00425D9B mov edi , eax seg000: 00425D9D
 
  Seg000: 00425D9D loc_425D9D:;
  CODE XREF: sub_425C59 + 12Dj
 
  Seg000: 00425D9D cmp edi , 3EBh seg000: 00425DA3 jnz short loc_425DAA ;  Jmp if no data were entered
 Seg000: 00425DA5 call sub_425228 ;  CreateProcessA
 Seg000: 00425DAA
 
  Seg000: 00425DAA loc_425DAA:;
  CODE XREF: sub_425C59 + 14Aj
 
  Seg000: 00425DAA mov eax , edi seg000: 00425DAC
 
  Seg000: 00425DAC loc_425DAC:;
  CODE XREF: sub_425C59 + 178j
 
  Seg000: 00425DAC pop edi seg000: 00425DAD pop esi seg000: 00425DAE pop ebx seg000: 00425DAF leave
 
  Seg000: 00425DB0 retn
 

Ie, after entering reg.data, the main application window was simply deactivated and the application was closed. But the most interesting is that before that (.00425DA5) there was a call to a function that created a new process-a copy of the process that was just started by us-the victim (ala CopeMemII armas, although in the process of hacking this feint, in my opinion, did not add any complexity, except Unusualness). Here is a piece of the procedure code sub_425228, which it confirms.

  Seg000: 00425278 lea eax , [ebp + ProcessInformation ]
 
  Seg000: 0042527B mov [ebp + StartupInfo.cb ] , 44h seg000: 00425282 mov [ebp + StartupInfo.dwFlags ] , 40h seg000: 00425289 push eax ;  LpProcessInformation
 Seg000: 0042528A lea eax , [ebp + StartupInfo ]
 
  Seg000: 0042528D push eax ;  LpStartupInfo
 Seg000: 0042528E push esi ;  LpCurrentDirectory
 Seg000: 0042528F push esi ;  LpEnvironment
 Seg000: 00425290 push esi ;  DwCreationFlags
 Seg000: 00425291 push esi ;  BInheritHandles
 Seg000: 00425292 push esi ;  LpThreadAttributes
 Seg000: 00425293 push esi ;  LpProcessAttributes
 Seg000: 00425294 lea eax , [ebp + ApplicationName ] seg000: 0042529A push esi ;  LpCommandLine
 Seg000: 0042529B push eax ;  LpApplicationName
 Seg000: 0042529C call ds: CreateProcessA seg000: 004252A2 pop esi seg000: 004252A3 leave
 
  Seg000: 004252A4 retn
 
  Seg000: 004252A4 sub_425228 endp
 Seg000: 004252A4
 

By flipping the code a bit higher, I understood why the registers recorded in the registry were not read at startup. It turned out that when creating the process, a unique mutex was created that "let know" to the parent process whether the child process was started as a "launch toy" or as "to verify the correctness of the data." Since the checks after entering the name-code were already in the pre-process, and in OllyDbg they could not be caught (at the time of connection to the newly created process all the checks were already passed, and there was no possibility of using a decent ring0-mode debugger), then I decided to go On some trick: modify the binaries of the file being examined in such a way that the first of the lines of its executable functions (for example, WinMain) was a loop (EBFE opcode). So the process created was looped and I would be able to connect to it on time and restore the original 2 bytes of code quietly to search for the necessary areas. But, unfortunately, trying to implement the described method was spent half an hour, and the child process was not obsessed with anything! Not wanting to spend any more time finding the cause (which apparently consisted of duplicating Main functions in the victim), I decided to go with a more "traditional" method and put the parsers in the parent process to call TerminateProcess and ExitProcess;)


Put brushes on the calls to the application shutdown functions

We launch our file, enter the required reg data (I entered the name: ProTeuS and the code: 1234567890abcdeABCDE) and without problems get the desired point (.44A841)


Detect call point for the application's shutdown function

Rising several levels up the structure of the disassembled listing in IDA we see the following code:

  Seg000: 004247A0
 
  Seg000: 004247A0 ;
  --------------- SUBROUTINE ---------------------------------- -----
 
  Seg000: 004247A0
 
  Seg000: 004247A0 ;
  Attributes: bp-based frame
 
  Seg000: 004247A0
 
  Seg000: 004247A0 sub_4247A0 proc near ;
  CODE XREF: sub_437940 + 26p
 
  Seg000: 004247A0 ;
  Sub_437940 + 3Bp
 
  Seg000: 004247A0
 
  Seg000: 004247A0 var_200 = dword ptr -200h
 
  Seg000: 004247A0
 
  Seg000: 004247A0 push ebp seg000: 004247A1 mov ebp , esp seg000: 004247A3 sub esp , 200h seg000: 004247A9 push esi seg000: 004247AA push dsi seg000: 004247AB call sub_437940 seg000: 004247B0 mov dword ptr [eax + 20h ] , offset aLemonade ;
  "Lemonade"
 
  Seg000: 004247B7 call sub_437940 seg000: 004247BC mov dword ptr [eax + 24h ] , offset aLemonadeTycoon ;
  "Lemonade Tycoon"
 
  Seg000: 004247C3 call sub_437940 seg000: 004247C8 mov dword ptr [eax + 28h ] , offset a1_1_5 ;
  "1.1.5"
 
  Seg000: 004247CF call sub_437940 seg000: 004247D4 mov dword ptr [eax + 28h ] , offset a1_1_6 ;
  "1.1.6"
 
  Seg000: 004247DB call sub_437940 seg000: 004247E0 mov dword ptr [eax + 1Ch ] , offset aB6081ca706b415 ;
  "{B6081CA-706B-415E-AE52-910C4FB06016}"
 
  Seg000: 004247E7 call sub_437940 seg000: 004247EC mov dword ptr [eax + 10h ] , offset a1_0 ;
  "1.0"
 
  Seg000: 004247F3 call sub_437940 seg000: 004247F8 mov dword ptr [eax + 14h ] , offset a72733b3Ac0f4d4 ;
  "{72733B3-AC0F-4D43-BED1-25EE1194A7BA}"
 
  Seg000: 004247FF call sub_437940 seg000: 00424804 mov dword ptr [eax + 18h ] , offset a48033dc6A54144 ;
  "{48033DC6-A541-4454-A9CE-3186C3365B75}"
 
  Seg000: 0042480B call sub_437940 seg000: 00424810 mov dword ptr [eax + 88h ] , 96h seg000: 0042481A call sub_437940 seg000: 0042481F xor edi , edi seg000: 00424821 push 68h seg000: 00424823 mov [eax + 34h ] , edi seg000: 00424826 pop esi seg000 : 00424827
 
  Seg000: 00424827 loc_424827:;
  CODE XREF: sub_4247A0 + 98j
 
  Seg000: 00424827 call sub_437940 seg000: 0042482C mov [eax + esi] , edi seg000: 0042482F add esi , 4 seg000: 00424832 cmp esi , 84h seg000: 00424838 jl short loc_424827 seg000: 0042483A call sub_4263DD ;  Check function
 Seg000: 0042483F test eax , eax seg000: 00424841 jz short loc_42484A seg000: 00424843 push 1 ;  Int
 Seg000: 00424845 call _exit seg000: 0042484A ;
  -------------------------------------------------- -------------------------
 
  Seg000: 0042484A
 
  Seg000: 0042484A loc_42484A:;
  CODE XREF: sub_4247A0 + A1j
 
  Seg000: 0042484A call sub_4264BC ;  Eax = ds: dword_57F99C
 Seg000: 0042484F test eax , eax seg000: 00424851 jz short loc_42489B ;  JMP if eax = 1 (in the other process)
 Seg000: 00424853 mov esi , ds: GetModuleHandleA seg000: 00424859 lea eax , [ebp + var_200 ] seg000: 0042485F push eax ;  Char *
 Seg000: 00424860 push edi ;  LpModuleName
 Seg000: 00424861 call esi ;
  GetModuleHandleA
 
  Seg000: 00424863 push eax ;  HInstance
 Seg000: 00424864 call sub_426404 seg000: 00424869 pop ecx seg000: 0042486A lea eax , [ebp + var_200 ] seg000: 00424870 pop ecx seg000: 00424871 mov ds: dword_57F988 , edi seg000: 00424877 push eax ;  Int
 Seg000: 00424878 push edi ;  LpModuleName
 Seg000: 00424879 call esi ;
  GetModuleHandleA
 
  Seg000: 0042487B push eax ;  HInstance
 Seg000: 0042487C call sub_425C59 ;  ReadParametrs
 Seg000: 00424881 pop ecx seg000: 00424882 cmp eax , 3EBh seg000: 00424887 pop ecx seg000: 00424888 jnz short loc_424891 seg000: 0042488A push 1 ;  Int
 Seg000: 0042488C call _exit ;  Close the application after entering the data.
 Seg000: 00424891 ;
  -------------------------------------------------- -------------------------
 
  Seg000: 00424891
 
  Seg000: 00424891 loc_424891:;
  CODE XREF: sub_4247A0 + E8j
 
  Seg000: 00424891 mov ds: dword_57F988 , 1 seg000: 0042489B
 
  Seg000: 0042489B loc_42489B:;
  CODE XREF: sub_4247A0 + B1j
 
  Seg000: 0042489B pop edi seg000: 0042489C pop esi seg000: 0042489D leave ;  Jump to .4365C9
 Seg000: 0042489E retn
 
  Seg000: 0042489E sub_4247A0 endp
 Seg000: 0042489E
 

It's easy to guess that 0042483A call sub_4263DD is nothing more than a call to the check function, which affects the scan at .0042484F. It is from its test results that it depends on whether the ExitProcess function is called, or whether the normal order of operation will be restored in case of entering the user's registration and launching the toy.
Looking at the called function 0042484A call sub_4264BC, we see that the register eax is entered 1, the contents of the memory location at address 57F99C.
  Seg000: 004264BC
 
  Seg000: 004264BC ;
  --------------- SUBROUTINE ---------------------------------- -----
 
  Seg000: 004264BC
 
  Seg000: 004264BC
 
  Seg000: 004264BC sub_4264BC proc near ;
  CODE XREF: sub_413B78 + 5Cp
 
  Seg000: 004264BC ;
  Sub_4157E8 + 531p ...
 
  Seg000: 004264BC mov eax , ds: dword_57F99C seg000: 004264C1 retn
 
  Seg000: 004264C1 sub_4264BC endp
 Seg000: 004264C1
 

It is logical to assume that before this, during the check in this same cell, a record is made in the case of entering the wrong data. And if the cell contains 0, then the program will constantly skip the verification phase for registration and immediately start the game. To find the place of verification, restart the victim and set the breakpoint to write to the specified memory location:

Bryak to write to the memory cell, the filthy registration status

Click on F9 and before us there is such a piece of code:

  Seg000: 00426296
 
  seg000: 00426296 push ebp seg000: 00426297 mov ebp, esp seg000: 00426299 sub esp, 530h seg000: 0042629F push esi seg000: 004262A0 xor esi, esi seg000: 004262A2 cmp ds: dword_57F9A0, esi seg000: 004262A8 jnz loc_4263DA seg000: 004262AE lea eax , [ Ebp + KeyName ] seg000: 004262B4 push offset a1831 ;
  "183-1"
 
  Seg000: 004262B9 push eax seg000: 004262BA mov ds: dword_57F99C , 1 ;  Writes 1 to the memory in the case of incorrect data entry
 Seg000: 004262C4 call ds: lstrcpy

Address .004262A2 see an interesting team compared the cell 57F9A0 to 0. This is the place to check the countdown 60 seconds since the start of the game (click on .4262A2, click the right mouse button, select "Find References to - Address constant" and see the address. appropriate code 00426046 MOV DWORD PTR DS:. [57F9A0 ], 1 It is executed only if you are registred user, and "lets you know" game that does not need to be interrupted after a minute runtime). If the content of the cell 57F9A0 is 0, the game will crash even after the registration status variable has been patched! So, to complete a security breach is necessary to change the result of checking at 004262A2, that at least one of the operands, and amounted to 1, instead of comparing the content 57F9A0 to 0 (address .4261D6) cells burn to 1. To not use a massive operation with the modification of memory cells can be simply Enter 1 in the esi register. To do this, you can replace the command xor esi, esi at 004262A0 with inc esi and nop (opcodes 46 90). Instead of CMP DWORD PTR DS: [57F9A0], 0 should be written INC DWORD PTR DS: [57F9A0], because by default the program will store the unregistered 0 there and we thus optimizing the code introduce into the contents of the memory cell 1. At the request of the next conditional branch JNE Cracked.00426292 can be replaced by an unconditional JMP cracked.00426292. This is done in any hex editor. I chose the Hiew. Patching To open it dumped_.exe file 2 times we press Enter, then the F5, enter .4262A0, click the F3, enter 46 90. The same is done for the other teams, which can oppkody will see on the screenshot below. Save the changes F9.


Patches a binary game in hex editor Hiew

Now the program is fully operational. Running the game takes place immediately, without outputting any naga and interrupts in the middle of the game process.

Files to article:

Target: Lemonade Tycoon v1.1.6 (2100kb)
Dump with restored import: dumped_.rar

Gl hf 2 all
05.01.2006