1. (Part 2 of .NET native exe insights)Serial fishing and patching .NET exes with Ollydb

    (Part 2 of .NET native exe insights)Serial fishing and patching .NET exes with Ollydbg.

    Last blog post I pointed out how native exes, when used improperly, do nothing to deter reverse engineer of
    completely decompiling your product, and doing with it as they please (cracking). Now, I would like to assume
    that the developer bothered reading my blog post, and actually bothered wiping the IL from his native exe. While
    I do admit that this is a "final" solution to decompilation, as I mentioned before it is faaaar from a "final"
    solution to crackers. Hackers have been going at native code for years, so with a bit of brainpower and Olly, a
    native .NET exe should pose no challenge to them.

    In this post I will observe a simple keygenme, and I will show you how I was able to
    a) patch it
    b) fish a serial for it...

    in less that 5 minutes with Olly.

    Here is the link to the keygenme we will be dealing with(same as in last blog post):

    Download it, extract it anywhere, and Ngen it

    >ngen unpackme.exe.

    Then, take unpackme.exe, and load it into Olly. Check all exceptions, and run the Unpackme. It will pop up with
    a little dialogue asking for a name and serial. Click the "Check" button, and observe the error message:

    "Invalid serial. Pls don't hack me :'("

    Hardy harr.

    Well, now lets think for a second. This is a string that is needed for the unpackme to run. Therefore, it can
    probably be found the native image of the unpackme. We also know that all strings in a .NET exe are stored in
    the metadata. As I pointed out in the last tutorial, the metadata of a .NET exe is in the .IL section of the
    native exe. So, we know that somewhere in the .IL section of our native exe, we will find a string saying:
    "Invalid serial. Pls don't hack me :'("

    Furthermore, if you paid close attention to the .NET file format, you know that all strings in .NET are stored as
    unicode. So, somewhere in the .IL section of our native .NET exe there will be a UNICODE string that says:
    "Invalid serial. Pls don't hack me :'(".

    Now, suppose that we locate this string. What do we do with it? Quite simple: We put a hardware breakpoint upon
    it. Once it is accessed, we know that the routine it was accessed from is part of the serial checking routine.

    Alright, now in Olly, with the unpackme running in the background, press ALT+M to open a list of all modules.
    Scroll down a bit until you find the native image of unpackme.exe ( You should see this:

    30000000    00001000 (  Unpack_1 3             PE header     Imag   R         RWE
    30002000    00004000 (  Unpack_1 3  .text      code          Imag   R E       RWE
    30006000    00001000 (  Unpack_1 3  .extrel    code          Imag   R E       RWE
    30008000    00005000 (  Unpack_1 3  .data      code,data     Imag   RW        RWE
    3000E000    00001000 (  Unpack_1 3  .xdata                   Imag   RWE       RWE
    30010000    00001000 (  Unpack_1 3  .dbgmap                  Imag   R         RWE
    30012000    00004000 (  Unpack_1 3  .il                      Imag   R         RWE
    30016000    00001000 (  Unpack_1 3  .rsrc      resources     Imag   R         RWE
    30018000    00001000 (  Unpack_1 3  .reloc     relocations   Imag   R         RWE
    Now, we are interested in the .IL section of this native exe, because that is where the string we are trying to
    breakpoint is. In the dump window of Ollydbg, press CTRL+G, type 30012000, and press enter. This will move the
    Ollydbg hex dump window to the beginning of the .IL section. Then, still in the dump window, press
    CTRL+B (binary search), and under unicode type in:
    "Invalid serial.". Then press enter to let Olly search. It should end up here:

    300142FD   49 00 6E 00 76 00 61 00  I.n.v.a.
    30014305   6C 00 69 00 64 00 20 00  l.i.d. .
    3001430D   53 00 65 00 72 00 69 00  S.e.r.i.
    30014315   61 00 6C 00 2E 00 20 00  a.l... .
    3001431D   50 00 6C 00 73 00 20 00  P.l.s. .
    30014325   64 00 6F 00 6E 00 27 00  d.o.n.'.
    3001432D   74 00 20 00 68 00 61 00  t. .h.a.
    30014335   63 00 6B 00 20 00 6D 00  c.k. .m.
    3001433D   65 00 20 00 3A 00 27 00  e. .:.'.
    30014345   28 00 01 81 7B 54 00 68  (.{T.h
    3001434D   00 65 00 20 00 70 00 6F  .e. .p.o
    30014355   00 69 00 6E 00 74 00 20  .i.n.t.
    3001435D   00 6F 00 66 00 20 00 74  .o.f. .t
    30014365   00 68 00 69 00 73 00 20  .h.i.s.
    3001436D   00 55 00 6E 00 70 00 61  .U.n.p.a
    30014375   00 63 00 6B 00 6D 00 65  .c.k.m.e
    3001437D   00 20 00 69 00 73 00 20  . .i.s.
    30014385   00 66 00 6F 00 72 00 20  .f.o.r.
    Cool! This is the badboy string we are interested in. Write down the address, restart the target in Olly, and
    press F9 to run Olly once again. Do not click on the check button yet. First, go to the address we wrote down
    (300142FD) select the first 4 bytes,
    Right click -> breakpoint -> hardware, on access -> byte

    Now, go back to the unpackme, and click on the "Check" button. Olly should break with a hardware DWORD on access
    at a place that looks like this:

    7814507A    F3:A5              REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
    7814507C    FF2495 94511478    JMP DWORD PTR DS:[EDX*4+78145194]
    78145083    90                 NOP
    Alright now, go to
    Debug -> hardware breakpoints

    in Olly, and delete your hardware breakpoint that you set upon this string.

    Now, its time to trace a bit with F8 until we get to the .text section of Unpackme.exe. Just hold F8 until
    you end up here:

    300041D0    57                 PUSH EDI
    300041D1    56                 PUSH ESI
    300041D2    53                 PUSH EBX
    300041D3    55                 PUSH EBP
    300041D4    83EC 10            SUB ESP,10
    300041D7    891424             MOV DWORD PTR SS:[ESP],EDX
    300041DA    8BF1               MOV ESI,ECX
    300041DC    8B05 0CE00030      MOV EAX,DWORD PTR DS:[3000E00C]                 ; Unpack_1.300081B4
    300041E2    8338 00            CMP DWORD PTR DS:[EAX],0
    300041E5    74 05              JE SHORT Unpack_1.300041EC
    300041E7    E8 12E1084A        CALL mscorwks.7A0922FE
    After you've debugged .NET exe's a bit in Olly you will recognize this as the beginning of a method, just like

    usually marks the beginning of a routine in VC++...

    Anyways, since this routine has accessed the "Invalid serial" string, we can assume that this routine is the
    serial check routine. Start tracing at it with F8. A messagebox telling you you entered the wrong serial will
    pop up after you trace over this call:

    300042A6    8B05 18BF0030      MOV EAX,DWORD PTR DS:[3000BF18]
    300042AC    8B08               MOV ECX,DWORD PTR DS:[EAX]
    300042AE    FF15 C0BF0030      CALL DWORD PTR DS:[3000BFC0]                    ; System_W.7B26EC88
    300042B4    90                 NOP
    Interesting... look around in Olly and try to get a feel for what is happening. Even a noob should be able to
    understand what is happening here:

    30004270    8BF8               MOV EDI,EAX
    30004272    6A 00              PUSH 0
    30004274    8BD3               MOV EDX,EBX
    30004276    8BCF               MOV ECX,EDI
    30004278    FF15 BCBF0030      CALL DWORD PTR DS:[3000BFBC]                    ; Compare strings (Microsoft.VisualBasic.dll)
    3000427E    8BF8               MOV EDI,EAX
    30004280    85FF               TEST EDI,EDI
    30004282    0F94C0             SETE AL
    30004285    0FB6C0             MOVZX EAX,AL
    30004288    894424 04          MOV DWORD PTR SS:[ESP+4],EAX
    3000428C    837C24 04 00       CMP DWORD PTR SS:[ESP+4],0			; were they the same?
    30004291    74 12              JE SHORT Unpack_1.300042A5			; if not, JMP
    30004293    8B05 14BF0030      MOV EAX,DWORD PTR DS:[3000BF14]
    30004299    8B08               MOV ECX,DWORD PTR DS:[EAX]
    3000429B    FF15 C0BF0030      CALL DWORD PTR DS:[3000BFC0]                    ; good boy message. 
    300042A1    90                 NOP
    300042A2    90                 NOP
    300042A3    EB 10              JMP SHORT Unpack_1.300042B5
    300042A5    90                 NOP
    300042A6    8B05 18BF0030      MOV EAX,DWORD PTR DS:[3000BF18]
    300042AC    8B08               MOV ECX,DWORD PTR DS:[EAX]
    300042AE    FF15 C0BF0030      CALL DWORD PTR DS:[3000BFC0]                    ; bad boy message.
    300042B4    90                 NOP
    300042B5    90                 NOP
    300042B6    90                 NOP
    300042B7    90                 NOP
    300042B8    83C4 10            ADD ESP,10
    300042BB    5D                 POP EBP
    300042BC    5B                 POP EBX
    300042BD    5E                 POP ESI
    300042BE    5F                 POP EDI
    300042BF    C2 0400            RETN 4
    Simple, eh? Just for kicks, nop the JE at 30004291 and press F9 to run the unpackme. Click on the "Check" button and watch ...

    Updated March 24th, 2008 at 02:00 by rendari