When talking about editing memory, we usually think about patching code. Patching code means changing the binary code in memory for, let’s say, when you want to prove a hypothesis while debugging and you don’t have access to the source code.

This is a very exciting subject, and WinDbg has the right tools to do the job. To actually change the memory, we are going to use the following commands:

 

a [address] – This command assembles instruction mnemonics and puts the resulting instruction codes into memory.

 

The following commands change the content from a specific memory location:

 

e{b|d|D|f|p|q|w} <Address> [Values
e{a|u|za|zu} <Address> <"String">
e <Address> [Values] 

According to WinDbg help file:

 

 

e

 

Enters data in the same format as the most recent e* command. (If the most recent e* command was ea, eza, eu, or ezu, the final parameter will be String and may not be omitted.)

ea

ASCII string (not NULL-terminated).

eb

Byte values.

ed

Double-word values (4 bytes).

eD

Double-precision floating-point numbers (8 bytes).

ef

Single-precision floating-point numbers (4 bytes).

ep

Pointer-sized values. This command is equivalent to ed or eq, depending on whether the target computer's processor architecture is 32-bit or 64-bit, respectively.

eq

Quad-word values (8 bytes).

eu

Unicode string (not NULL-terminated).

ew

Word values (2 bytes).

eza

NULL-terminated ASCII string.

ezu

NULL-terminated Unicode string.

 

To learn how to edit memory, let’s crack the application below. We will use the Debug version compiled as 32 bits. However, this is just to make things easier because you can use the 64 bits version or Release version. The techniques are the same!

 

CrackMe application:

 

// CrackMe.cpp : Defines the entry point for the console application.

//

 

#include "stdafx.h"

 

#include <iostream>

 

using namespace std;  // Necessary for cout/cin.

 

// Declares prototypes.

void AskPassword(void);

bool IsRightPassword(int);

void GiveAccess(void);

void DenyAccess(void);

 

const int PASSWORD = 357;

 

void AskPassword()

{

     // User can try to input the password for three times.

     for(int i = 0; i < 3; i++)

     {

           cout << "Tentative " << i + 1 << "/3" << endl;

           cout << "Type the numeric secret password:" << endl;

 

           int nPassword = 0;

 

           cin >> nPassword;

 

           if(IsRightPassword(nPassword))

           {

                GiveAccess();

                break; // User got the right password. Don't need to ask more.

           }

           else

           {

                DenyAccess();

           }

 

     }

}

 

void GiveAccess()

{

     cout << "You have access to the system." << endl;

}

 

void DenyAccess()

{

     cout << "Wrong password!" << endl;

}

 

inline bool IsRightPassword(int nPasswordToValidate)

{

     return PASSWORD == nPasswordToValidate;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

     AskPassword();

     return 0;

}

 

From now on let’s pretend we have never seen the source code before and we don’t have the right password. Let’s use symbols to make things easier, but keep in mind that in real world scenarios you may not have application symbols!

 

 

Note: The answers from the tasks below are not meant to be the only right ones. They are just some of many possible answers that can be used to show the commands for memory editing.

 

Task #1 – Let’s find out the right password.

 

Run the application from Windbg and break into the debugger when it asks for the password.

Let’s disassemble the main() function:

 

0:001> uf CrackMe!wmain

*** WARNING: Unable to verify checksum for CrackMe.exe

CrackMe!wmain [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 59]:

   59 013f1c30 55              push    ebp

   59 013f1c31 8bec            mov     ebp,esp

   59 013f1c33 81ecc0000000    sub     esp,0C0h

   59 013f1c39 53              push    ebx

   59 013f1c3a 56              push    esi

   59 013f1c3b 57              push    edi

   59 013f1c3c 8dbd40ffffff    lea     edi,[ebp-0C0h]

   59 013f1c42 b930000000      mov     ecx,30h

   59 013f1c47 b8cccccccc      mov     eax,0CCCCCCCCh

   59 013f1c4c f3ab            rep stos dword ptr es:[edi]

   60 013f1c4e e8cbf3ffff      call    CrackMe!ILT+25(?AskPasswordYAXXZ) (013f101e)

   61 013f1c53 33c0            xor     eax,eax

   62 013f1c55 5f              pop     edi

   62 013f1c56 5e              pop     esi

   62 013f1c57 5b              pop     ebx

   62 013f1c58 81c4c0000000    add     esp,0C0h

   62 013f1c5e 3bec            cmp     ebp,esp

   62 013f1c60 e84ef5ffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (013f11b3)

   62 013f1c65 8be5            mov     esp,ebp

   62 013f1c67 5d              pop     ebp

   62 013f1c68 c3              ret

 

AskPasswordYAXXZ looks interesting… let’s disassemble it:

 

0:001> uf 013f101e

CrackMe!AskPassword [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 19]:

   19 013f4190 55              push    ebp

   19 013f4191 8bec            mov     ebp,esp

   19 013f4193 81ecd8000000    sub     esp,0D8h

   19 013f4199 53              push    ebx

   19 013f419a 56              push    esi

   19 013f419b 57              push    edi

   19 013f419c 8dbd28ffffff    lea     edi,[ebp-0D8h]

   19 013f41a2 b936000000      mov     ecx,36h

   19 013f41a7 b8cccccccc      mov     eax,0CCCCCCCCh

   19 013f41ac f3ab            rep stos dword ptr es:[edi]

   21 013f41ae c745f800000000  mov     dword ptr [ebp-8],0

   21 013f41b5 eb09            jmp     CrackMe!AskPassword+0x30 (013f41c0)

 

CrackMe!AskPassword+0x27 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 21]:

   21 013f41b7 8b45f8          mov     eax,dword ptr [ebp-8]

   21 013f41ba 83c001          add     eax,1

   21 013f41bd 8945f8          mov     dword ptr [ebp-8],eax

 

CrackMe!AskPassword+0x30 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 21]:

   21 013f41c0 837df803        cmp     dword ptr [ebp-8],3

   21 013f41c4 0f8dc2000000    jge     CrackMe!AskPassword+0xfc (013f428c)

 

CrackMe!AskPassword+0x3a [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

   23 013f41ca 8bf4            mov     esi,esp

   23 013f41cc a110a33f01      mov     eax,dword ptr [CrackMe!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (013fa310)]

   23 013f41d1 50              push    eax

   23 013f41d2 683c783f01      push    offset CrackMe!`string' (013f783c)

   23 013f41d7 8b4df8          mov     ecx,dword ptr [ebp-8]

   23 013f41da 83c101          add     ecx,1

   23 013f41dd 8bfc            mov     edi,esp

   23 013f41df 51              push    ecx

   23 013f41e0 6814783f01      push    offset CrackMe!`string' (013f7814)

   23 013f41e5 8b150ca33f01    mov     edx,dword ptr [CrackMe!_imp_?coutstd (013fa30c)]

   23 013f41eb 52              push    edx

   23 013f41ec e872cfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (013f1163)

   23 013f41f1 83c408          add     esp,8

   23 013f41f4 8bc8            mov     ecx,eax

   23 013f41f6 ff1554a33f01    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01HZ (013fa354)]

   23 013f41fc 3bfc            cmp     edi,esp

   23 013f41fe e8b0cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (013f11b3)

   23 013f4203 50              push    eax

   23 013f4204 e85acfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (013f1163)

   23 013f4209 83c408          add     esp,8

   23 013f420c 8bc8            mov     ecx,eax

   23 013f420e ff1508a33f01    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (013fa308)]

   23 013f4214 3bf4            cmp     esi,esp

   23 013f4216 e898cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (013f11b3)

   24 013f421b 8bf4            mov     esi,esp

   24 013f421d a110a33f01      mov     eax,dword ptr [CrackMe!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (013fa310)]

   24 013f4222 50              push    eax

   24 013f4223 68187b3f01      push    offset CrackMe!`string' (013f7b18)

   24 013f4228 8b0d0ca33f01    mov     ecx,dword ptr [CrackMe!_imp_?coutstd (013fa30c)]

   24 013f422e 51              push    ecx

   24 013f422f e82fcfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (013f1163)

   24 013f4234 83c408          add     esp,8

   24 013f4237 8bc8            mov     ecx,eax

   24 013f4239 ff1508a33f01    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (013fa308)]

   24 013f423f 3bf4            cmp     esi,esp

   24 013f4241 e86dcfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (013f11b3)

   26 013f4246 c745ec00000000  mov     dword ptr [ebp-14h],0

   28 013f424d 8bf4            mov     esi,esp

   28 013f424f 8d45ec          lea     eax,[ebp-14h]

   28 013f4252 50              push    eax

   28 013f4253 8b0d04a33f01    mov     ecx,dword ptr [CrackMe!_imp_?cinstd (013fa304)]

   28 013f4259 ff1500a33f01    call    dword ptr [CrackMe!_imp_??5?$basic_istreamDU?$char_traitsDstdstdQAEAAV01AAHZ (013fa300)]

   28 013f425f 3bf4            cmp     esi,esp

   28 013f4261 e84dcfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (013f11b3)

   30 013f4266 8b45ec          mov     eax,dword ptr [ebp-14h]

   30 013f4269 50              push    eax

   30 013f426a e8eecfffff      call    CrackMe!ILT+600(?IsRightPasswordYA_NHZ) (013f125d)

   30 013f426f 83c404          add     esp,4

   30 013f4272 0fb6c8          movzx   ecx,al

   30 013f4275 85c9            test    ecx,ecx

   30 013f4277 7409            je      CrackMe!AskPassword+0xf2 (013f4282)

 

CrackMe!AskPassword+0xe9 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 32]:

   32 013f4279 e8e9cfffff      call    CrackMe!ILT+610(?GiveAccessYAXXZ) (013f1267)

   33 013f427e eb0c            jmp     CrackMe!AskPassword+0xfc (013f428c)

 

CrackMe!AskPassword+0xf2 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 37]:

   37 013f4282 e8dbcfffff      call    CrackMe!ILT+605(?DenyAccessYAXXZ) (013f1262)

   38 013f4287 e92bffffff      jmp     CrackMe!AskPassword+0x27 (013f41b7)

 

CrackMe!AskPassword+0xfc [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 41]:

   41 013f428c 52              push    edx

   41 013f428d 8bcd            mov     ecx,ebp

   41 013f428f 50              push    eax

   41 013f4290 8d15b4423f01    lea     edx,[CrackMe!AskPassword+0x124 (013f42b4)]

   41 013f4296 e819ceffff      call    CrackMe!ILT+175(_RTC_CheckStackVars (013f10b4)

   41 013f429b 58              pop     eax

   41 013f429c 5a              pop     edx

   41 013f429d 5f              pop     edi

   41 013f429e 5e              pop     esi

   41 013f429f 5b              pop     ebx

   41 013f42a0 81c4d8000000    add     esp,0D8h

   41 013f42a6 3bec            cmp     ebp,esp

   41 013f42a8 e806cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (013f11b3)

   41 013f42ad 8be5            mov     esp,ebp

   41 013f42af 5d              pop     ebp

   41 013f42b0 c3              ret

 

CrackMe!ILT+25(?AskPasswordYAXXZ):

013f101e e96d310000      jmp     CrackMe!AskPassword (013f4190)

 

After analyzing the code above we see two calls like:

 

coutstd

 

And just one call like:

 

cinstd

 

 

This clearly suggests cout and cin from C++ Standard Template Library.

If that is true we know that cin is used to receive information from the user.

Let’s put a breakpoint after the call function just after cin.

 

0:001> bp 013f425f

0:001> bl

 0 e 013f425f     0001 (0001)  0:**** CrackMe!AskPassword+0xcf

 

And continue the execution.

We type any number, like 543. Now let’s track our number and see when it is compared against the right password.

At this point the breakpoint is hit.

 

If you look at the disassembled code again, you will see where our password was stored:

 

   28 013f424f 8d45ec          lea     eax,[ebp-14h]

   28 013f4252 50              push    eax

   28 013f4253 8b0d04a33f01    mov     ecx,dword ptr [CrackMe!_imp_?cinstd (013fa304)]

   28 013f4259 ff1500a33f01    call    dword ptr [CrackMe!_imp_??5?$basic_istreamDU?$char_traitsDstdstdQAEAAV01AAHZ (013fa300)]

   28 013f425f 3bf4            cmp     esi,esp

   28 013f4261 e84dcfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (013f11b3)

   30 013f4266 8b45ec          mov     eax,dword ptr [ebp-14h]

   30 013f4269 50              push    eax

   30 013f426a e8eecfffff      call    CrackMe!ILT+600(?IsRightPasswordYA_NHZ) (013f125d)

 

Look at [ebp-14h]. It is a local variable used in cin and used again just before IsRightPassword is called.

If that is true we should get the password we typed:

 

0:000> dd [ebp-0x14]

001cf9dc  0000021f cccccccc cccccccc 00000000

001cf9ec  cccccccc 001cfac4 013f1c53 00000000

001cf9fc  00000000 7efde000 cccccccc cccccccc

001cfa0c  cccccccc cccccccc cccccccc cccccccc

001cfa1c  cccccccc cccccccc cccccccc cccccccc

001cfa2c  cccccccc cccccccc cccccccc cccccccc

001cfa3c  cccccccc cccccccc cccccccc cccccccc

001cfa4c  cccccccc cccccccc cccccccc cccccccc

 

0:000> ? 21f

Evaluate expression: 543 = 0000021f

 

Right! This is the password we just typed. Let’s follow it through the code execution.

 

It’s being used as argument here:

 

66 8b45ec          mov     eax,dword ptr [ebp-14h] ss:002b:001cf9dc=0000021f

013f4269 50              push    eax

013f426a e8eecfffff      call    CrackMe!ILT+600(?IsRightPasswordYA_NHZ) (013f125d)

013f426f 83c404          add     esp,4

 

 

Note: Use p to step over and t to step into.

 

After stepping into IsRightPassword() and disassemble it we have:

 

CrackMe!IsRightPassword:

013f16b0 55              push    ebp

013f16b1 8bec            mov     ebp,esp

013f16b3 81ecc0000000    sub     esp,0C0h

013f16b9 53              push    ebx

013f16ba 56              push    esi

013f16bb 57              push    edi

013f16bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

013f16c2 b930000000      mov     ecx,30h

013f16c7 b8cccccccc      mov     eax,0CCCCCCCCh

013f16cc f3ab            rep stos dword ptr es:[edi]

013f16ce 33c0            xor     eax,eax

013f16d0 817d0865010000  cmp     dword ptr [ebp+8],165h

013f16d7 0f94c0          sete    al

013f16da 5f              pop     edi

013f16db 5e              pop     esi

013f16dc 5b              pop     ebx

013f16dd 8be5            mov     esp,ebp

013f16df 5d              pop     ebp

013f16e0 c3              ret

 

The line at address number 013f16d0 is key. Why? It compares the first function parameter against a specific number.

The parameter happens to be our password, sent by argument as you can see from the disassembled listing. Now let’s see what 165h is in decimal.

Let’s put a breakpoint on address 013f16d0 and continue the execution to that point.

 

0:000> g

Breakpoint 1 hit

eax=00000000 ebx=7efde000 ecx=00000000 edx=6952daa4 esi=001cf90c edi=001cf900

eip=013f16d0 esp=001cf834 ebp=001cf900 iopl=0         nv up ei pl zr na pe nc

cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246

CrackMe!IsRightPassword+0x20:

013f16d0 817d0865010000  cmp     dword ptr [ebp+8],165h ss:002b:001cf908=0000021f

 

Next:

 

0:000> dd [ebp+0x8] L1

001cf908  0000021f

 

Our password, remember?

And:

 

0:000> ? 165

Evaluate expression: 357 = 00000165

 

So our password is being compared against 357. If we run the application again and use 357 we can prove that this is the right password.

Mission accomplished!

 

 

Task #2 – Let’s make the application use 0 as password.

 

OK, now we know the right password and we know where the user’s password is being tested against the application’s password. So we just need to change the right password to 0.

Pay attention to the fact that the same password could be used from different parts of the program, so ideally all parts should be changed.

 

Let’s restart the application and stop the execution when it asks for the password.

After that let’s disassemble CrackMe!IsRightPassword and get the address of the call just before the cmp call. Depending on the Windows version, the address should be different from last time:

 

0:001> uf CrackMe!IsRightPassword

*** WARNING: Unable to verify checksum for CrackMe.exe

CrackMe!IsRightPassword [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 54]:

   54 00d416b0 55              push    ebp

   54 00d416b1 8bec            mov     ebp,esp

   54 00d416b3 81ecc0000000    sub     esp,0C0h

   54 00d416b9 53              push    ebx

   54 00d416ba 56              push    esi

   54 00d416bb 57              push    edi

   54 00d416bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

   54 00d416c2 b930000000      mov     ecx,30h

   54 00d416c7 b8cccccccc      mov     eax,0CCCCCCCCh

   54 00d416cc f3ab            rep stos dword ptr es:[edi]

   55 00d416ce 33c0            xor     eax,eax

   55 00d416d0 817d0865010000  cmp     dword ptr [ebp+8],165h

   55 00d416d7 0f94c0          sete    al

   56 00d416da 5f              pop     edi

   56 00d416db 5e              pop     esi

   56 00d416dc 5b              pop     ebx

   56 00d416dd 8be5            mov     esp,ebp

   56 00d416df 5d              pop     ebp

   56 00d416e0 c3              ret

 

 

After hitting the breakpoint at 00d416ce we start the “surgery.”

 

0:000> a 00d416ce

00d416ce cmp dword ptr [ebp+8], 0

cmp dword ptr [ebp+8], 0

00d416d2

 

This is the new listing:

 

0:000>  uf CrackMe!IsRightPassword

CrackMe!IsRightPassword [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 54]:

   54 00d416b0 55              push    ebp

   54 00d416b1 8bec            mov     ebp,esp

   54 00d416b3 81ecc0000000    sub     esp,0C0h

   54 00d416b9 53              push    ebx

   54 00d416ba 56              push    esi

   54 00d416bb 57              push    edi

   54 00d416bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

   54 00d416c2 b930000000      mov     ecx,30h

   54 00d416c7 b8cccccccc      mov     eax,0CCCCCCCCh

   54 00d416cc f3ab            rep stos dword ptr es:[edi]

   55 00d416ce 837d0800        cmp     dword ptr [ebp+8],0

   55 00d416d2 086501          or      byte ptr [ebp+1],ah

   55 00d416d5 0000            add     byte ptr [eax],al

   55 00d416d7 0f94c0          sete    al

   56 00d416da 5f              pop     edi

   56 00d416db 5e              pop     esi

   56 00d416dc 5b              pop     ebx

   56 00d416dd 8be5            mov     esp,ebp

   56 00d416df 5d              pop     ebp

   56 00d416e0 c3              ret

 

Note that we messed up the function because the original code:

 

817d0865010000

 

Has more bytes than the new code has:

 

837d0800  

 

What do we need to do? Insert NOP instructions that do not do anything just to fill the remaining bytes. We do that using the NOP instruction. You can calculate the number of instructions or see the disassembly after entering each NOP until you see the right continuation according to the original listing.

In our case we use:

 

a 00d416d2

 

And enter NOP instructions then hit Enter after that.

You can also use the approach below that uses the code corresponding to the mnemonic:

 

eb 00d416d2 90 90 90

 

If you are using the Disassembly Window or if you use uf again, you will be able to see the modified version.

 

Ours is:

 

CrackMe!IsRightPassword:

003716b0 55              push    ebp

003716b1 8bec            mov     ebp,esp

003716b3 81ecc0000000    sub     esp,0C0h

003716b9 53              push    ebx

003716ba 56              push    esi

003716bb 57              push    edi

003716bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

003716c2 b930000000      mov     ecx,30h

003716c7 b8cccccccc      mov     eax,0CCCCCCCCh

003716cc f3ab            rep stos dword ptr es:[edi]

003716ce 33c0            xor     eax,eax

003716d0 837d0800        cmp     dword ptr [ebp+8],0

003716d4 90              nop

003716d5 90              nop

003716d6 90              nop

003716d7 0f94c0          sete    al

003716da 5f              pop     edi

003716db 5e              pop     esi

003716dc 5b              pop     ebx

003716dd 8be5            mov     esp,ebp

003716df 5d              pop     ebp

003716e0 c3              ret

 

The original password is 0. Let’s change the user’s password to 0, too:

 

0:000> dd [ebp+8] L1

002bfaf0  00000003

 

In our case we used 3.

Let’s change our password to 0, too:

 

0:000> ed 002bfaf0  0

 

You can see it was changed:

 

0:000> dd [ebp+8] L1

002bfaf0  00000000

 

At this point you should get the message:

 

“You have access to the system.”

 

This happens because the application is comparing the user’s password, which is 0 (we changed it), against the original password, which is also 0 (we changed it too).

Using debuggers like OllyDbg or hexadecimal editors, you can go one step further and save another version of the binary, the patched version. That means the application will consider the number 0 as the correct password whenever you run it! But be warned, it is considered a crime to do that.

 

 

Task #3 – Let’s remove the test that validates the password.

 

After running the application again, we break into the debugger when it asks for the password.

 

0:000> uf CrackMe!wmain

CrackMe!wmain [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 59]:

   59 00ec1c30 55              push    ebp

   59 00ec1c31 8bec            mov     ebp,esp

   59 00ec1c33 81ecc0000000    sub     esp,0C0h

   59 00ec1c39 53              push    ebx

   59 00ec1c3a 56              push    esi

   59 00ec1c3b 57              push    edi

   59 00ec1c3c 8dbd40ffffff    lea     edi,[ebp-0C0h]

   59 00ec1c42 b930000000      mov     ecx,30h

   59 00ec1c47 b8cccccccc      mov     eax,0CCCCCCCCh

   59 00ec1c4c f3ab            rep stos dword ptr es:[edi]

   60 00ec1c4e e8cbf3ffff      call    CrackMe!ILT+25(?AskPasswordYAXXZ) (00ec101e)

   61 00ec1c53 33c0            xor     eax,eax

   62 00ec1c55 5f              pop     edi

   62 00ec1c56 5e              pop     esi

   62 00ec1c57 5b              pop     ebx

   62 00ec1c58 81c4c0000000    add     esp,0C0h

   62 00ec1c5e 3bec            cmp     ebp,esp

   62 00ec1c60 e84ef5ffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (00ec11b3)

   62 00ec1c65 8be5            mov     esp,ebp

   62 00ec1c67 5d              pop     ebp

   62 00ec1c68 c3              ret

 

0:000> uf 00ec101e

CrackMe!AskPassword [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 19]:

   19 00ec4190 55              push    ebp

   19 00ec4191 8bec            mov     ebp,esp

   19 00ec4193 81ecd8000000    sub     esp,0D8h

   19 00ec4199 53              push    ebx

   19 00ec419a 56              push    esi

   19 00ec419b 57              push    edi

   19 00ec419c 8dbd28ffffff    lea     edi,[ebp-0D8h]

   19 00ec41a2 b936000000      mov     ecx,36h

   19 00ec41a7 b8cccccccc      mov     eax,0CCCCCCCCh

   19 00ec41ac f3ab            rep stos dword ptr es:[edi]

   21 00ec41ae c745f800000000  mov     dword ptr [ebp-8],0

   21 00ec41b5 eb09            jmp     CrackMe!AskPassword+0x30 (00ec41c0)

 

CrackMe!AskPassword+0x27 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 21]:

   21 00ec41b7 8b45f8          mov     eax,dword ptr [ebp-8]

   21 00ec41ba 83c001          add     eax,1

   21 00ec41bd 8945f8          mov     dword ptr [ebp-8],eax

 

CrackMe!AskPassword+0x30 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 21]:

   21 00ec41c0 837df803        cmp     dword ptr [ebp-8],3

   21 00ec41c4 0f8dc2000000    jge     CrackMe!AskPassword+0xfc (00ec428c)

 

CrackMe!AskPassword+0x3a [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

   23 00ec41ca 8bf4            mov     esi,esp

   23 00ec41cc a110a3ec00      mov     eax,dword ptr [CrackMe!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00eca310)]

   23 00ec41d1 50              push    eax

   23 00ec41d2 683c78ec00      push    offset CrackMe!`string' (00ec783c)

   23 00ec41d7 8b4df8          mov     ecx,dword ptr [ebp-8]

   23 00ec41da 83c101          add     ecx,1

   23 00ec41dd 8bfc            mov     edi,esp

   23 00ec41df 51              push    ecx

   23 00ec41e0 681478ec00      push    offset CrackMe!`string' (00ec7814)

   23 00ec41e5 8b150ca3ec00    mov     edx,dword ptr [CrackMe!_imp_?coutstd (00eca30c)]

   23 00ec41eb 52              push    edx

   23 00ec41ec e872cfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00ec1163)

   23 00ec41f1 83c408          add     esp,8

   23 00ec41f4 8bc8            mov     ecx,eax

   23 00ec41f6 ff1554a3ec00    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01HZ (00eca354)]

   23 00ec41fc 3bfc            cmp     edi,esp

   23 00ec41fe e8b0cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (00ec11b3)

   23 00ec4203 50              push    eax

   23 00ec4204 e85acfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00ec1163)

   23 00ec4209 83c408          add     esp,8

   23 00ec420c 8bc8            mov     ecx,eax

   23 00ec420e ff1508a3ec00    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (00eca308)]

   23 00ec4214 3bf4            cmp     esi,esp

   23 00ec4216 e898cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (00ec11b3)

   24 00ec421b 8bf4            mov     esi,esp

   24 00ec421d a110a3ec00      mov     eax,dword ptr [CrackMe!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00eca310)]

   24 00ec4222 50              push    eax

   24 00ec4223 68187bec00      push    offset CrackMe!`string' (00ec7b18)

   24 00ec4228 8b0d0ca3ec00    mov     ecx,dword ptr [CrackMe!_imp_?coutstd (00eca30c)]

   24 00ec422e 51              push    ecx

   24 00ec422f e82fcfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00ec1163)

   24 00ec4234 83c408          add     esp,8

   24 00ec4237 8bc8            mov     ecx,eax

   24 00ec4239 ff1508a3ec00    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (00eca308)]

   24 00ec423f 3bf4            cmp     esi,esp

   24 00ec4241 e86dcfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (00ec11b3)

   26 00ec4246 c745ec00000000  mov     dword ptr [ebp-14h],0

   28 00ec424d 8bf4            mov     esi,esp

   28 00ec424f 8d45ec          lea     eax,[ebp-14h]

   28 00ec4252 50              push    eax

   28 00ec4253 8b0d04a3ec00    mov     ecx,dword ptr [CrackMe!_imp_?cinstd (00eca304)]

   28 00ec4259 ff1500a3ec00    call    dword ptr [CrackMe!_imp_??5?$basic_istreamDU?$char_traitsDstdstdQAEAAV01AAHZ (00eca300)]

   28 00ec425f 3bf4            cmp     esi,esp

   28 00ec4261 e84dcfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (00ec11b3)

   30 00ec4266 8b45ec          mov     eax,dword ptr [ebp-14h]

   30 00ec4269 50              push    eax

   30 00ec426a e8eecfffff      call    CrackMe!ILT+600(?IsRightPasswordYA_NHZ) (00ec125d)

   30 00ec426f 83c404          add     esp,4

   30 00ec4272 0fb6c8          movzx   ecx,al

   30 00ec4275 85c9            test    ecx,ecx

   30 00ec4277 7409            je      CrackMe!AskPassword+0xf2 (00ec4282)

 

CrackMe!AskPassword+0xe9 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 32]:

   32 00ec4279 e8e9cfffff      call    CrackMe!ILT+610(?GiveAccessYAXXZ) (00ec1267)

   33 00ec427e eb0c            jmp     CrackMe!AskPassword+0xfc (00ec428c)

 

CrackMe!AskPassword+0xf2 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 37]:

   37 00ec4282 e8dbcfffff      call    CrackMe!ILT+605(?DenyAccessYAXXZ) (00ec1262)

   38 00ec4287 e92bffffff      jmp     CrackMe!AskPassword+0x27 (00ec41b7)

 

CrackMe!AskPassword+0xfc [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 41]:

   41 00ec428c 52              push    edx

   41 00ec428d 8bcd            mov     ecx,ebp

   41 00ec428f 50              push    eax

   41 00ec4290 8d15b442ec00    lea     edx,[CrackMe!AskPassword+0x124 (00ec42b4)]

   41 00ec4296 e819ceffff      call    CrackMe!ILT+175(_RTC_CheckStackVars (00ec10b4)

   41 00ec429b 58              pop     eax

   41 00ec429c 5a              pop     edx

   41 00ec429d 5f              pop     edi

   41 00ec429e 5e              pop     esi

   41 00ec429f 5b              pop     ebx

   41 00ec42a0 81c4d8000000    add     esp,0D8h

   41 00ec42a6 3bec            cmp     ebp,esp

   41 00ec42a8 e806cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (00ec11b3)

   41 00ec42ad 8be5            mov     esp,ebp

   41 00ec42af 5d              pop     ebp

   41 00ec42b0 c3              ret

 

CrackMe!ILT+25(?AskPasswordYAXXZ):

00ec101e e96d310000      jmp     CrackMe!AskPassword (00ec4190)

 

 

 

From above: [ebp-14] holds the user password and is sent as argument to IsRightPassword().

 

 

0:000> uf 00ec125d

CrackMe!IsRightPassword [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 54]:

   54 00ec16b0 55              push    ebp

   54 00ec16b1 8bec            mov     ebp,esp

   54 00ec16b3 81ecc0000000    sub     esp,0C0h

   54 00ec16b9 53              push    ebx

   54 00ec16ba 56              push    esi

   54 00ec16bb 57              push    edi

   54 00ec16bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

   54 00ec16c2 b930000000      mov     ecx,30h

   54 00ec16c7 b8cccccccc      mov     eax,0CCCCCCCCh

   54 00ec16cc f3ab            rep stos dword ptr es:[edi]

   55 00ec16ce 33c0            xor     eax,eax

   55 00ec16d0 817d0865010000  cmp     dword ptr [ebp+8],165h

   55 00ec16d7 0f94c0          sete    al

   56 00ec16da 5f              pop     edi

   56 00ec16db 5e              pop     esi

   56 00ec16dc 5b              pop     ebx

   56 00ec16dd 8be5            mov     esp,ebp

   56 00ec16df 5d              pop     ebp

   56 00ec16e0 c3              ret

 

CrackMe!ILT+600(?IsRightPasswordYA_NHZ):

00ec125d e94e040000      jmp     CrackMe!IsRightPassword (00ec16b0)

 

Next step is to replace this:

 

   55 00ec16ce 33c0            xor     eax,eax

   55 00ec16d0 817d0865010000  cmp     dword ptr [ebp+8],165h

 

For this:

 

55 00ec16ce mov eax, 1

                   nop

                   nop

                  

After the changes:

 

CrackMe!IsRightPassword:

00ec16b0 55              push    ebp

00ec16b1 8bec            mov     ebp,esp

00ec16b3 81ecc0000000    sub     esp,0C0h

00ec16b9 53              push    ebx

00ec16ba 56              push    esi

00ec16bb 57              push    edi

00ec16bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

00ec16c2 b930000000      mov     ecx,30h

00ec16c7 b8cccccccc      mov     eax,0CCCCCCCCh

00ec16cc f3ab            rep stos dword ptr es:[edi]

00ec16ce b801000000      mov     eax,1

00ec16d3 650100          add     dword ptr gs:[eax],eax

00ec16d6 000f            add     byte ptr [edi],cl

00ec16d8 94              xchg    eax,esp

00ec16d9 c05f5e5b        rcr     byte ptr [edi+5Eh],5Bh

00ec16dd 8be5            mov     esp,ebp

00ec16df 5d              pop     ebp

00ec16e0 c3              ret

 

However, notice that we changed all other instructions because our instruction used more bytes than the original instruction.

Let’s fix that using NOPs.

 

0:000> eb 00ec16d3 90 90 90 90 90 90 90

 

Another approach is to use:

 

a 00ec16d3

 

And type 7 NOP pressing Enter after each one.

The first approach has one key benefit: it can be used from scripts or breakpoints. It’s also faster.

 

Final code:

 

CrackMe!IsRightPassword:

00ec16b0 55              push    ebp

00ec16b1 8bec            mov     ebp,esp

00ec16b3 81ecc0000000    sub     esp,0C0h

00ec16b9 53              push    ebx

00ec16ba 56              push    esi

00ec16bb 57              push    edi

00ec16bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

00ec16c2 b930000000      mov     ecx,30h

00ec16c7 b8cccccccc      mov     eax,0CCCCCCCCh

00ec16cc f3ab            rep stos dword ptr es:[edi]

00ec16ce b801000000      mov     eax,1

00ec16d3 90              nop

00ec16d4 90              nop

00ec16d5 90              nop

00ec16d6 90              nop

00ec16d7 90              nop

00ec16d8 90              nop

00ec16d9 90              nop

00ec16da 5f              pop     edi

00ec16db 5e              pop     esi

00ec16dc 5b              pop     ebx

00ec16dd 8be5            mov     esp,ebp

00ec16df 5d              pop     ebp

00ec16e0 c3              ret

 

So now the IsRightPassword() function is always return 1 (TRUE).

Use g to continue the execution and from the console window enter any number you want as password.

 

 

Task #4 – Let’s make the application call the function that is called when typing the right password even when typing the wrong password.

 

After running the application and breaking it into the debugger when asking for the password, we start what we call the “pre-surgery” phase.

 

0:000> kL 1000

ChildEBP RetAddr 

0046f1ec 75f66f99 kernel32!ReadConsoleInternal+0x15

0046f274 75eeefc6 kernel32!ReadConsoleA+0x40

0046f2bc 67416c3c kernel32!ReadFileImplementation+0x75

0046f350 67416589 MSVCR90D!_read_nolock+0x62c

0046f3a0 673a4453 MSVCR90D!_read+0x219

0046f3c8 673a2748 MSVCR90D!_filbuf+0x113

0046f420 6ce5c8e0 MSVCR90D!fgetc+0x208

0046f430 6ce5c567 MSVCP90D!std::_Fgetc<char>+0x10

0046f518 6ce5c460 MSVCP90D!std::basic_filebuf<char,std::char_traits<char> >::uflow+0xb7

0046f530 6ce58c9a MSVCP90D!std::basic_filebuf<char,std::char_traits<char> >::underflow+0x50

0046f540 6ce59104 MSVCP90D!std::basic_streambuf<char,std::char_traits<char> >::sgetc+0x3a

0046f59c 6ce58c3a MSVCP90D!std::basic_istream<char,std::char_traits<char> >::_Ipfx+0x104

0046f5bc 6ce7eee6 MSVCP90D!std::basic_istream<char,std::char_traits<char> >::sentry::sentry+0x4a

0046f634 0002425f MSVCP90D!std::basic_istream<char,std::char_traits<char> >::operator>>+0x46

0046f724 00021c53 CrackMe!AskPassword+0xcf

0046f7f8 00022598 CrackMe!wmain+0x23

0046f848 000223df CrackMe!__tmainCRTStartup+0x1a8

0046f850 75ec3f39 CrackMe!wmainCRTStartup+0xf

0046f85c 77710409 kernel32!BaseThreadInitThunk+0xe

0046f89c 777103dc ntdll!__RtlUserThreadStart+0x70

0046f8b4 00000000 ntdll!_RtlUserThreadStart+0x1b

 

 

AskPassword() is called from main() and looks suspicious. Let’s investigate:

 

0:000> uf CrackMe!AskPassword

CrackMe!AskPassword [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 19]:

   19 00024190 55              push    ebp

   19 00024191 8bec            mov     ebp,esp

   19 00024193 81ecd8000000    sub     esp,0D8h

   19 00024199 53              push    ebx

   19 0002419a 56              push    esi

   19 0002419b 57              push    edi

   19 0002419c 8dbd28ffffff    lea     edi,[ebp-0D8h]

   19 000241a2 b936000000      mov     ecx,36h

   19 000241a7 b8cccccccc      mov     eax,0CCCCCCCCh

   19 000241ac f3ab            rep stos dword ptr es:[edi]

   21 000241ae c745f800000000  mov     dword ptr [ebp-8],0

   21 000241b5 eb09            jmp     CrackMe!AskPassword+0x30 (000241c0)

 

CrackMe!AskPassword+0x27 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 21]:

   21 000241b7 8b45f8          mov     eax,dword ptr [ebp-8]

   21 000241ba 83c001          add     eax,1

   21 000241bd 8945f8          mov     dword ptr [ebp-8],eax

 

CrackMe!AskPassword+0x30 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 21]:

   21 000241c0 837df803        cmp     dword ptr [ebp-8],3

   21 000241c4 0f8dc2000000    jge     CrackMe!AskPassword+0xfc (0002428c)

 

CrackMe!AskPassword+0x3a [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

   23 000241ca 8bf4            mov     esi,esp

   23 000241cc a110a30200      mov     eax,dword ptr [CrackMe!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (0002a310)]

   23 000241d1 50              push    eax

   23 000241d2 683c780200      push    offset CrackMe!`string' (0002783c)

   23 000241d7 8b4df8          mov     ecx,dword ptr [ebp-8]

   23 000241da 83c101          add     ecx,1

   23 000241dd 8bfc            mov     edi,esp

   23 000241df 51              push    ecx

   23 000241e0 6814780200      push    offset CrackMe!`string' (00027814)

   23 000241e5 8b150ca30200    mov     edx,dword ptr [CrackMe!_imp_?coutstd (0002a30c)]

   23 000241eb 52              push    edx

   23 000241ec e872cfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00021163)

   23 000241f1 83c408          add     esp,8

   23 000241f4 8bc8            mov     ecx,eax

   23 000241f6 ff1554a30200    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01HZ (0002a354)]

   23 000241fc 3bfc            cmp     edi,esp

   23 000241fe e8b0cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

   23 00024203 50              push    eax

   23 00024204 e85acfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00021163)

   23 00024209 83c408          add     esp,8

   23 0002420c 8bc8            mov     ecx,eax

   23 0002420e ff1508a30200    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (0002a308)]

   23 00024214 3bf4            cmp     esi,esp

   23 00024216 e898cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

   24 0002421b 8bf4            mov     esi,esp

   24 0002421d a110a30200      mov     eax,dword ptr [CrackMe!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (0002a310)]

   24 00024222 50              push    eax

   24 00024223 68187b0200      push    offset CrackMe!`string' (00027b18)

   24 00024228 8b0d0ca30200    mov     ecx,dword ptr [CrackMe!_imp_?coutstd (0002a30c)]

   24 0002422e 51              push    ecx

   24 0002422f e82fcfffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00021163)

   24 00024234 83c408          add     esp,8

   24 00024237 8bc8            mov     ecx,eax

   24 00024239 ff1508a30200    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (0002a308)]

   24 0002423f 3bf4            cmp     esi,esp

   24 00024241 e86dcfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

   26 00024246 c745ec00000000  mov     dword ptr [ebp-14h],0

   28 0002424d 8bf4            mov     esi,esp

   28 0002424f 8d45ec          lea     eax,[ebp-14h]

   28 00024252 50              push    eax

   28 00024253 8b0d04a30200    mov     ecx,dword ptr [CrackMe!_imp_?cinstd (0002a304)]

   28 00024259 ff1500a30200    call    dword ptr [CrackMe!_imp_??5?$basic_istreamDU?$char_traitsDstdstdQAEAAV01AAHZ (0002a300)]

   28 0002425f 3bf4            cmp     esi,esp

   28 00024261 e84dcfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

   30 00024266 8b45ec          mov     eax,dword ptr [ebp-14h]

   30 00024269 50              push    eax

   30 0002426a e8eecfffff      call    CrackMe!ILT+600(?IsRightPasswordYA_NHZ) (0002125d)

   30 0002426f 83c404          add     esp,4

   30 00024272 0fb6c8          movzx   ecx,al

   30 00024275 85c9            test    ecx,ecx

   30 00024277 7409            je      CrackMe!AskPassword+0xf2 (00024282)

 

CrackMe!AskPassword+0xe9 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 32]:

   32 00024279 e8e9cfffff      call    CrackMe!ILT+610(?GiveAccessYAXXZ) (00021267)

   33 0002427e eb0c            jmp     CrackMe!AskPassword+0xfc (0002428c)

 

CrackMe!AskPassword+0xf2 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 37]:

   37 00024282 e8dbcfffff      call    CrackMe!ILT+605(?DenyAccessYAXXZ) (00021262)

   38 00024287 e92bffffff      jmp     CrackMe!AskPassword+0x27 (000241b7)

 

CrackMe!AskPassword+0xfc [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 41]:

   41 0002428c 52              push    edx

   41 0002428d 8bcd            mov     ecx,ebp

   41 0002428f 50              push    eax

   41 00024290 8d15b4420200    lea     edx,[CrackMe!AskPassword+0x124 (000242b4)]

   41 00024296 e819ceffff      call    CrackMe!ILT+175(_RTC_CheckStackVars (000210b4)

   41 0002429b 58              pop     eax

   41 0002429c 5a              pop     edx

   41 0002429d 5f              pop     edi

   41 0002429e 5e              pop     esi

   41 0002429f 5b              pop     ebx

   41 000242a0 81c4d8000000    add     esp,0D8h

   41 000242a6 3bec            cmp     ebp,esp

   41 000242a8 e806cfffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

   41 000242ad 8be5            mov     esp,ebp

   41 000242af 5d              pop     ebp

   41 000242b0 c3              ret

 

 

At this point it is necessary to analyze what we call “dead listing” in order to get a better understanding of the function and make sure this may be the right function.

In bold above you can see what looks like the routine that checks the password. Remember, we are pretending we don’t know the source code, so to prove the point you should insert breakpoints, debug the application, and see if the DenyAccessYAXXZ above is called when you enter any invalid password.

 

Ok, so after running the application using breakpoints we prove the point.

However, we don’t know what happens when we enter the right password, but we suppose it is going to call GiveAccessYAXXZ. To prove the point let’s analyze this function.

 

0:000> uf 00021267

CrackMe!GiveAccess [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 44]:

   44 000215b0 55              push    ebp

   44 000215b1 8bec            mov     ebp,esp

   44 000215b3 81ecc0000000    sub     esp,0C0h

   44 000215b9 53              push    ebx

   44 000215ba 56              push    esi

   44 000215bb 57              push    edi

   44 000215bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

   44 000215c2 b930000000      mov     ecx,30h

   44 000215c7 b8cccccccc      mov     eax,0CCCCCCCCh

   44 000215cc f3ab            rep stos dword ptr es:[edi]

   45 000215ce 8bf4            mov     esi,esp

   45 000215d0 a110a30200      mov     eax,dword ptr [CrackMe!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (0002a310)]

   45 000215d5 50              push    eax

   45 000215d6 6840780200      push    offset CrackMe!`string' (00027840)

   45 000215db 8b0d0ca30200    mov     ecx,dword ptr [CrackMe!_imp_?coutstd (0002a30c)]

   45 000215e1 51              push    ecx

   45 000215e2 e87cfbffff      call    CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00021163)

   45 000215e7 83c408          add     esp,8

   45 000215ea 8bc8            mov     ecx,eax

   45 000215ec ff1508a30200    call    dword ptr [CrackMe!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (0002a308)]

   45 000215f2 3bf4            cmp     esi,esp

   45 000215f4 e8bafbffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

   46 000215f9 5f              pop     edi

   46 000215fa 5e              pop     esi

   46 000215fb 5b              pop     ebx

   46 000215fc 81c4c0000000    add     esp,0C0h

   46 00021602 3bec            cmp     ebp,esp

   46 00021604 e8aafbffff      call    CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

   46 00021609 8be5            mov     esp,ebp

   46 0002160b 5d              pop     ebp

   46 0002160c c3              ret

 

CrackMe!ILT+610(?GiveAccessYAXXZ):

00021267 e944030000      jmp     CrackMe!GiveAccess (000215b0)

 

 

After reviewing the code we located one string. Let’s examine that:

 

0:000> db 00027840

00027840  59 6f 75 20 68 61 76 65-20 61 63 63 65 73 73 20  You have access

00027850  74 6f 20 74 68 65 20 73-79 73 74 65 6d 2e 00 00  to the system...

00027860  66 00 3a 00 5c 00 64 00-64 00 5c 00 76 00 63 00  f.:.\.d.d.\.v.c.

00027870  74 00 6f 00 6f 00 6c 00-73 00 5c 00 63 00 72 00  t.o.o.l.s.\.c.r.

00027880  74 00 5f 00 62 00 6c 00-64 00 5c 00 73 00 65 00  t._.b.l.d.\.s.e.

00027890  6c 00 66 00 5f 00 78 00-38 00 36 00 5c 00 63 00  l.f._.x.8.6.\.c.

000278a0  72 00 74 00 5c 00 73 00-72 00 63 00 5c 00 63 00  r.t.\.s.r.c.\.c.

000278b0  72 00 74 00 65 00 78 00-65 00 2e 00 63 00 00 00  r.t.e.x.e...c...

 

Excellent! This is the right function. The string is an ANSI string, not Unicode. A Unicode string should have two bytes for each character.

Here is another way to see that:

 

0:000> da 00027840

00027840  "You have access to the system."

 

 

Let’s see the two calls, for right and wrong passwords:

 

0:000> uf /c CrackMe!AskPassword

CrackMe!AskPassword (00024190) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 19]

  CrackMe!AskPassword+0x5c (000241ec) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

    call to CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00021163)

  CrackMe!AskPassword+0x66 (000241f6) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

    call to MSVCP90D!std::basic_ostream<char,std::char_traits<char> >::operator<< (6ce7a520) 

  CrackMe!AskPassword+0x6e (000241fe) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

    call to CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

  CrackMe!AskPassword+0x74 (00024204) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

    call to CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00021163)

  CrackMe!AskPassword+0x7e (0002420e) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

    call to MSVCP90D!std::basic_ostream<char,std::char_traits<char> >::operator<< (6ce79f60) 

  CrackMe!AskPassword+0x86 (00024216) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 23]:

    call to CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

  CrackMe!AskPassword+0x9f (0002422f) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 24]:

    call to CrackMe!ILT+350(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (00021163)

  CrackMe!AskPassword+0xa9 (00024239) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 24]:

    call to MSVCP90D!std::basic_ostream<char,std::char_traits<char> >::operator<< (6ce79f60)

  CrackMe!AskPassword+0xb1 (00024241) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 24]:

    call to CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

  CrackMe!AskPassword+0xc9 (00024259) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 28]:

    call to MSVCP90D!std::basic_istream<char,std::char_traits<char> >::operator>> (6ce7eea0)

  CrackMe!AskPassword+0xd1 (00024261) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 28]:

    call to CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

  CrackMe!AskPassword+0xda (0002426a) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 30]:

    call to CrackMe!ILT+600(?IsRightPasswordYA_NHZ) (0002125d)

  CrackMe!AskPassword+0xe9 (00024279) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 32]:

    call to CrackMe!ILT+610(?GiveAccessYAXXZ) (00021267)

  CrackMe!AskPassword+0xf2 (00024282) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 37]:

    call to CrackMe!ILT+605(?DenyAccessYAXXZ) (00021262)

  CrackMe!AskPassword+0x106 (00024296) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 41]:

    call to CrackMe!ILT+175(_RTC_CheckStackVars (000210b4)

  CrackMe!AskPassword+0x118 (000242a8) [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 41]:

    call to CrackMe!ILT+430(__RTC_CheckEsp) (000211b3)

 

 

Hopefully the number of bytes is the same:

 

CrackMe!AskPassword+0xe9 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 32]:

   32 00024279 e8e9cfffff      call    CrackMe!ILT+610(?GiveAccessYAXXZ) (00021267)

   33 0002427e eb0c            jmp     CrackMe!AskPassword+0xfc (0002428c)

 

CrackMe!AskPassword+0xf2 [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 37]:

   37 00024282 e8dbcfffff      call    CrackMe!ILT+605(?DenyAccessYAXXZ) (00021262)

 

 

We are ready to start the “surgery”:

 

0:000> u 00021267

CrackMe!ILT+610(?GiveAccessYAXXZ):

00021267 e944030000      jmp     CrackMe!GiveAccess (000215b0)

 

See the indirection? We need 000215b0.

 

0:000> u 000215b0

CrackMe!GiveAccess [c:\development\my tools\book\crackme\crackme\crackme.cpp @ 44]:

000215b0 55              push    ebp

000215b1 8bec            mov     ebp,esp

000215b3 81ecc0000000    sub     esp,0C0h

000215b9 53              push    ebx

000215ba 56              push    esi

000215bb 57              push    edi

000215bc 8dbd40ffffff    lea     edi,[ebp-0C0h]

000215c2 b930000000      mov     ecx,30h

 

0:000> a 00024282

00024282 call CrackMe!GiveAccess

call CrackMe!GiveAccess

00024287

 

New listing:

 

00024277 7409            je      CrackMe!AskPassword+0xf2 (00024282)

00024279 e8e9cfffff      call    CrackMe!ILT+610(?GiveAccessYAXXZ) (00021267)

0002427e eb0c            jmp     CrackMe!AskPassword+0xfc (0002428c)

00024280 eb05            jmp     CrackMe!AskPassword+0xf7 (00024287)

00024282 e829d3ffff      call    CrackMe!GiveAccess (000215b0)

00024287 e92bffffff      jmp     CrackMe!AskPassword+0x27 (000241b7)

0002428c 52              push    edx

0002428d 8bcd            mov     ecx,ebp

0002428f 50              push    eax

 

 

Now if you type “g” and continue the execution entering any invalid password the application is going to show the message that says you have access to the system.

However, the application is going to ask you the password again because you typed the wrong password. In other words, after changing the application according to the instructions above, it will call the function that is supposed to be called only if you type the right password! ;-)

 

Here is a fun demonstration for Windows XP on 32 bits: http://blogs.msdn.com/debuggingtoolbox/archive/2007/03/28/windbg-script-playing-with-minesweeper.aspx

 

Another related blog article:

http://blogs.msdn.com/debuggingtoolbox/archive/2007/04/27/windbg-script-tracing-messagebox-calls.aspx

 

For more WinDbg commands check the Special Commands section in this blog.