|
继续分析 * Referenced by a (U)nconditional or (C)ondITional Jump at Address: |:0040C1E1(C) | :0040C1EE 25FF000000 and eax, 000000FF ;cmp al, 61后会跳到这里,eax保留低8位 :0040C1F3 6683E841 sub ax, 0041 ;0x41=’A’,计算与’A’差距
* Referenced by a (U)nconditional or (C)ondITional Jump at Address: |:0040C1EC(U) | :0040C1F7 8B550C mov edx, dword ptr [ebp+0C] ;edx保存第二个参数 :0040C1FA 8A5213 mov dl, byte ptr [edx+13] ;取0x13=19位 :0040C1FD 80FA61 cmp dl, 61 :0040C200 720C jb 0040C20E :0040C202 81E2FF000000 and edx, 000000FF :0040C208 6683EA61 sub dx, 0061 :0040C20C EB0A jmp 0040C218
上面这段与上面的代码几乎一样,不做分析。值得一提的是我们需要修正我们前面定义的结构,修正后:
struct test { char c18_unused[18]; char c19; char c20 };
等价c代码 int esi; char al; char dl; int edx; int edi; int eax; int ecx;
esi = 0;
int len = strlen(strUserName); if(len <= 0) goto _SKIP_USERNAME;
for(int i = 0 ; i < len ; ++i) { esi += strUserName[i]; //计算用户名ASC和 }
_SKIP_USERNAME:
al = pt->c19_IsNumber; if(al < ’a’) //判断字符大小写 goto IsNumber1;
al -= ’a’; goto _CONTINUE1; IsNumber1: al -= ’A’;
_CONTINUE1:
dl = pt->c20_IsNumber; if(dl < ’a’) //判断字符大小写 goto IsNumber2; dl -= ’a’; goto _CONTINUE2;
IsNumber2: dl -= ’A’;
}
我们的目标快要到达了,最后的一段代码 * Referenced by a (U)nconditional or (C)ondITional Jump at Address: |:0040C20C(U) | :0040C218 0FB7C0 movzx eax, ax :0040C21B 6BF81A imul edi, eax, 0000001A :0040C21E 0FB7C2 movzx eax, dx :0040C221 03F8 add edi, eax :0040C223 81F74D010000 xor edi, 0000014D :0040C229 83F701 xor edi, 00000001 :0040C22C 8BC3 mov eax, ebx ;第一个参数 :0040C22E E8D5A4FFFF call 00406708 ;和前面分析一样求长度 :0040C233 2BF8 sub edi, eax ;减去长度值 :0040C235 8BC6 mov eax, esi ;esi是第一个参数asc码和 :0040C237 B91A000000 mov ecx, 0000001A ;ecx=0x1a=26 :0040C23C 99 cdq ;eax扩展成edx:eax :0040C23D F7F9 idiv ecx ;除以ecx=26 :0040C23F 2BFA sub edi, edx ;减去余数 :0040C241 8BC7 mov eax, edi ;传给eax :0040C243 5F pop edi :0040C244 5E pop esi :0040C245 5B pop ebx :0040C246 5D pop ebp :0040C247 C20800 ret 0008
这段代码也很简单,到这里我们得到近似的c源代码,这里对于cdq指令完成的功能我没有实现,但是这对问题
没有影响: int GetUserNumber(char * strUserName,test * pt) { int esi; char al; char dl; int edx; int edi; int eax; int ecx;
esi = 0;
int len = strlen(strUserName); if(len <= 0) goto _SKIP_USERNAME;
for(int i = 0 ; i < len ; ++i) { esi += strUserName[i]; //计算用户名ASC和 }
_SKIP_USERNAME:
al = pt->c19_IsNumber; if(al < ’a’) //判断字符大小写 goto IsNumber1;
al -= ’a’; goto _CONTINUE1; IsNumber1: al -= ’A’;
_CONTINUE1:
dl = pt->c20_IsNumber; if(dl < ’a’) //判断字符大小写 goto IsNumber2; dl -= ’a’; goto _CONTINUE2;
IsNumber2: dl -= ’A’;
_CONTINUE2: edi = al*0x1a;//26 eax = dl; edi += eax; edi^=0x14d; edi^=0x1; edi -= len;
eax = esi; ecx = 0x1a; //26
//edx = eax的符号位扩展 edx = eax%ecx; eax/=ecx; edi -= edx; eax = edi;
return eax; }
到这里整个分析就结束了,我要说的是这里分析的函数比较简单,不具有一般性,涉及到更复杂的函数,比如
虚拟函数、类的分析,这里我的分析没有什么技术型可言,只是就一些简单的dll函数的反汇编,给出我的一点
经验,对您有帮助我感到很荣幸,对你没帮助浪费了您的时间我感到抱歉,希望您别骂我就好. 上一页 [1] [2] [3] |