I have the following code:

00401163   > 8D15 49634000  LEA EDX,DWORD PTR DS:[406349]            ; see below, 0x406349 is pointing to entered username
00401169   . 52             PUSH EDX                                 ; /String => "myusername"
0040116A   . E8 8D020000    CALL <JMP.&kernel32.lstrlenA>            ; \lstrlenA
0040116F   . 8BE8           MOV EBP,EAX
00401171   . B9 05000000    MOV ECX,5
00401176   . 33F6           XOR ESI,ESI                              ; ESI = 0
00401178   . 33C0           XOR EAX,EAX
0040117A   > 8A0C16         MOV CL,BYTE PTR DS:[ESI+EDX]             ; Why is it pointing to 'y' (2nd letter of username) at 1st run in the loop?
0040117D   . 8AD9           MOV BL,CL
0040117F   . 3298 28634000  XOR BL,BYTE PTR DS:[EAX+406328]
00401185   . 40             INC EAX
00401186   . 83F8 05        CMP EAX,5
00401189   . 881C32         MOV BYTE PTR DS:[EDX+ESI],BL
0040118C   . 8888 27634000  MOV BYTE PTR DS:[EAX+406327],CL
00401192   . 75 02          JNZ SHORT crackme.00401196
00401194   . 33C0           XOR EAX,EAX
00401196   > 46             INC ESI
00401197   . 3BF5           CMP ESI,EBP
00401199   .^72 DF          JB SHORT crackme.0040117A

As you can see, 0x406349 contains the username:

00406349  6D 79 75 73 65 72 6E 61 6D 65 00 00 00 00 00 00  myusername......

There is a loop that will go thru the letters of the entered username. I don't understand why the first run in the loop (at 0x40117A) contains the 2nd letter of the username instead of the 1st one because the index (ESI) is 0.

Can you please help me understand?

  • Check your EDX register content at 0x40116F. This will probably confirm that EDX gets changed by lstrlenA. It probably didn't get changed by the lstrlenA of the version of Windows that was current when the crackme was written, but does get changed with your version; the bug probably didn't ever bite the author of the crackme, but bites you now. – Guntram Blohm Jul 13 '15 at 13:24

as hanno binder replied edx is not preserved by the function call lstrlena

you can easily deduce such things by instrumenting the code prior to and post the operation where your assumptions dont pan out to actual behaviour

a sample test code could look like this (in x64 you may need a seperate file for inline asm but since you say edx and not rdx inline asm inside a cpp file is fine)

#include <stdio.h>
#include <windows.h>
// the vars are global so they are initialised to zero
int preeax,preebx,preecx,preedx,posteax,postebx,postecx,postedx;
void main (void) {
  printf("does lstrlena change edx ? lets check\n");
__asm {
  mov preeax,eax
  mov preebx,ebx
  mov preecx,ecx
  mov preedx,edx  
lstrlenA("does this change edx\n");
__asm {
  mov posteax,eax
  mov postebx,ebx
  mov postecx,ecx
  mov postedx,edx  
"preeax = %08x\tposteax = %08x\npreebx = %08x\tpostebx = %08x\n"
"preecx = %08x\tpostecx = %08x\npreedx = %08x\tpostedx = %08x\n",

on compiling and running it

does lstrlena change edx ? lets check
preeax = 00000026       posteax = 00000015
preebx = 7ffd8000       postebx = 7ffd8000
preecx = 00401120       postecx = 7c80be86

preedx = 004166a0 postedx = 004121b9

and as guntram commented to confirm you could disassemble lstrlena and grep for edx

cdb -c "uf kernel32!lstrlena;q" cdb | grep edx
eax=00191eb4 ebx=7ffdb000 ecx=00000007 edx=00000080 esi=00191f48 edi=00191eb4
7c80be71 8d5001          lea     edx,[eax+1] <-------------
7c80be7b 2bc2            sub     eax,edx

guess what eax points to :) or here is the spoiler you still need to understand x86 stack

cdb -c "uf kernel32!lstrlena;q" cdb | grep eax
eax=00191eb4 ebx=7ffd7000 ecx=00000007 edx=00000080 esi=00191f48 edi=00191eb4
7c80be62 8b4508 mov eax,dword ptr [ebp+8]
7c80be65 85c0 test eax,eax

  • Now the interesting part of this is: why is your postedx so completely different from preedx, when it's only preedx+1 in the OP's example? (Probable answer: edx equals the input string + 1 after lstrlenA, and in the OP's example, it's the input string before the call; in your example, it's some random value). – Guntram Blohm Jul 13 '15 at 13:21
  • You guys are correct. EDX is modified by lstrlenA. Thank you all for your quick and very valuable feedback. – Sebastien Damaye Jul 13 '15 at 15:32

EDX may have been altered by the function call, see stdcall:

Registers EAX, ECX, and EDX are designated for use within the function

Use another register, or push+pop EDX before/after the call to lstrlenA.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.