有个哲人说:凡人总是迷失在call的海洋中。
=============================================
用PEid查壳:Borland Delphi 6.0 - 7.0 用Delphi写的,无壳。 用w32asm 查看竟然“Could not get file handle” 看雪大神说:先用peid查查是不是有壳,如果没壳还这错误,试试其他反汇编工具,如IDA等 不纠结了。OD架起。 Ctrl+N捉不到关键API。 用超级字符串,发现奇怪字样。 0048C718 |. E8 D77EFAFF CALL 壹只老虎.004345F4 ; 下断 0048C71D |. 8D45 F4 LEA EAX,DWORD PTR SS:[EBP-C] 0048C720 |. BA 80C84800 MOV EDX,壹只老虎.0048C880 ; i am Bin Laden 0048C725 |. E8 CA77F7FF CALL 壹只老虎.00403EF4 0048C72A |. 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10] 0048C72D |. BA 98C84800 MOV EDX,壹只老虎.0048C898 ; i am yi zhi lao hu 0048C732 |. E8 BD77F7FF CALL 壹只老虎.00403EF4 0048C737 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; [EBP-4]为用户名xihuan 0048C73A |. E8 DD79F7FF CALL 壹只老虎.0040411C ; 检查字符串长度为 6 0048C73F |. 83F8 0A CMP EAX,0A ; 如果长度比 0xA 小,则挂 0048C742 |. 0F8C FC000000 JL 壹只老虎.0048C844 0048C748 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 0048C74B |. E8 CC79F7FF CALL 壹只老虎.0040411C 0048C750 |. 83F8 10 CMP EAX,10 ;这里namelen <= 0x10 0048C753 |. 0F8F EB000000 JG 壹只老虎.0048C844 0048C759 |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] 0048C75C |. E8 BB79F7FF CALL 壹只老虎.0040411C ; 返回serialLen 0048C761 |. 83F8 11 CMP EAX,11 ; serialLen >= 0x11 0048C764 |. 0F8C DA000000 JL 壹只老虎.0048C844 0048C76A |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] 0048C76D |. E8 AA79F7FF CALL 壹只老虎.0040411C 0048C772 |. 83F8 16 CMP EAX,16 ; serialLen <= 0x16 0048C775 |. 0F8F C9000000 JG 壹只老虎.0048C844 0048C77B |. 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4] 0048C77E |. 8B55 F4 MOV EDX,DWORD PTR SS:[EBP-C] ; 壹只老虎.0048C880 0048C781 |. E8 9E79F7FF CALL 壹只老虎.00404124 0048C786 |. BB 64000000 MOV EBX,64 0048C78B |. 8D45 88 LEA EAX,DWORD PTR SS:[EBP-78] 调整namelen[0xA,0x10],serialLen[0x11,0x16], 我们重新开始后,F9,我们输入xihuanshagua (12) woaininiaiwomaoyjg(18) 发现关键代码: 0048C781 |. E8 9E79F7FF CALL 壹只老虎.00404124 ; strcpt -> string1 0048C786 |. BB 64000000 MOV EBX,64 ; 100 0048C78B |. 8D45 88 LEA EAX,DWORD PTR SS:[EBP-78] 0048C78E |> C600 2E /MOV BYTE PTR DS:[EAX],2E ; 初始化,100次2E 0048C791 |. 40 |INC EAX 0048C792 |. 4B |DEC EBX 0048C793 |.^ 75 F9 \JNZ SHORT 壹只老虎.0048C78E 0048C795 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 0048C798 |. E8 7F79F7FF CALL 壹只老虎.0040411C ; strlen 0048C79D |. 8BF8 MOV EDI,EAX 0048C79F |. 85FF TEST EDI,EDI 0048C7A1 |. /7E 47 JLE SHORT 壹只老虎.0048C7EA 0048C7A3 |. |BB 01000000 MOV EBX,1 ; 这里开始一波循环运算 0048C7A8 |> |8B45 F0 /MOV EAX,DWORD PTR SS:[EBP-10] ; 壹只老虎.0048C898 0048C7AB |. |E8 6C79F7FF |CALL 壹只老虎.0040411C ; strlen 0048C7B0 |. |8BF0 |MOV ESI,EAX 0048C7B2 |. |85F6 |TEST ESI,ESI 0048C7B4 |. |7E 30 |JLE SHORT 壹只老虎.0048C7E6 0048C7B6 |. |B9 01000000 |MOV ECX,1 ; EBX = i ECX =j 0048C7BB |> |8B45 FC |/MOV EAX,DWORD PTR SS:[EBP-4] ; string1 0048C7BE |. |0FB64418 FF ||MOVZX EAX,BYTE PTR DS:[EAX+EBX-1]; string1[i] 0048C7C3 |. |8B55 F8 ||MOV EDX,DWORD PTR SS:[EBP-8] ; SN 0048C7C6 |. |0FB6540A FF ||MOVZX EDX,BYTE PTR DS:[EDX+ECX-1]; SN[j] 0048C7CB |. |F7EA ||IMUL EDX ; string1[i] * SN[j] 0048C7CD |. |51 ||PUSH ECX 0048C7CE |. |B9 1A000000 ||MOV ECX,1A ; ECX = 1A 0048C7D3 |. |33D2 ||XOR EDX,EDX 0048C7D5 |. |F7F1 ||DIV ECX ; string1[i]*SN[j] / 1A 0048C7D7 |. |59 ||POP ECX ; 0012FDDC 0048C7D8 |. |83C2 41 ||ADD EDX,41 ; string1[i]*SN[j] mod 1A +41 0048C7DB |. |8D0419 ||LEA EAX,DWORD PTR DS:[ECX+EBX] ; EAX = i + j 0048C7DE |. |885405 87 ||MOV BYTE PTR SS:[EBP+EAX-79],DL ; 结果DL存放起来 0048C7E2 |. |41 ||INC ECX 0048C7E3 |. |4E ||DEC ESI 0048C7E4 |.^|75 D5 |\JNZ SHORT 壹只老虎.0048C7BB 0048C7E6 |> |43 |INC EBX 0048C7E7 |. |4F |DEC EDI 0048C7E8 |.^|75 BE \JNZ SHORT 壹只老虎.0048C7A8 0048C7EA |> \8D45 EC LEA EAX,DWORD PTR SS:[EBP-14] 0048C7ED |. E8 6A76F7FF CALL 壹只老虎.00403E5C ; ? 0048C7F2 |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] 0048C7F5 |. E8 2279F7FF CALL 壹只老虎.0040411C ; strlen 0048C7FA |. 8BF8 MOV EDI,EAX 0048C7FC |. 85FF TEST EDI,EDI 0048C7FE |. 7E 1F JLE SHORT 壹只老虎.0048C81F ; 第二波运算 0048C800 |. 8D5D 8E LEA EBX,DWORD PTR SS:[EBP-72] ; string2的第六位开始算 0048C803 |> 8D45 84 /LEA EAX,DWORD PTR SS:[EBP-7C] 0048C806 |. 8A13 |MOV DL,BYTE PTR DS:[EBX] ; string2[i] 0048C808 |. E8 3778F7FF |CALL 壹只老虎.00404044 0048C80D |. 8B55 84 |MOV EDX,DWORD PTR SS:[EBP-7C] 0048C810 |. 8D45 EC |LEA EAX,DWORD PTR SS:[EBP-14] 0048C813 |. 8B4D EC |MOV ECX,DWORD PTR SS:[EBP-14] 0048C816 |. E8 4D79F7FF |CALL 壹只老虎.00404168 0048C81B |. 43 |INC EBX 0048C81C |. 4F |DEC EDI 0048C81D |.^ 75 E4 \JNZ SHORT 壹只老虎.0048C803 ; 长度为 SNlen 0048C81F |> 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14] ; 以上的运算讲的是倒序存储 0048C822 |. 8B55 F8 MOV EDX,DWORD PTR SS:[EBP-8] ; 尽量别跟进call,会晕,看结果容易些 0048C825 |. E8 3E7AF7FF CALL 壹只老虎.00404268 ; strcmp 0048C82A |. 75 18 JNZ SHORT 壹只老虎.0048C844 0048C82C |. 6A 40 PUSH 40 0048C82E |. B9 ACC84800 MOV ECX,壹只老虎.0048C8AC ; 恭喜你 0048C833 |. BA B4C84800 MOV EDX,壹只老虎.0048C8B4 ; 注册成功!请联系我!QQ:609841314 0048C838 |. A1 D0EB4800 MOV EAX,DWORD PTR DS:[48EBD0] 0048C83D |. 8B00 MOV EAX,DWORD PTR DS:[EAX] 0048C83F |. E8 F478FCFF CALL 壹只老虎.00454138 看到第一波运算的时候,就发现注册机不好写,因为序列号也参加运算了。 条件:SN.运算后 == SN.运算前 这个不仅仅注册机不好写,连正确的SN都不好获得。 注册机思路: 我猜到原作者的思想: 1. strcat(name,Laden); 2. 两层循环,i外j内,name[i] * SN[j] % 0x1A +0x41 的值赋值给 Result1[i+j] 3. 从Result1的第六位开始,截取len(SN)位,赋值为Result2 4. 逆序,使Result2为真正的SN 关键在第2点上: Result1[i+j],这将导致: 赋值顺序:i=0 0,1,2,3,4,5... i=1 1,2,3,4,5,6... i=2 2,3,4,5,6,7... 前面的除了每一轮的首位不会被覆盖掉,其它都会被覆盖掉,而每一轮的首位就是我们Result1[i] 所以:name[i] -> Result1[i] 通过(name[i] * SN[0] % 0x1A +0x41 ) 明显:我们只要先求出SN[0]即可。 Ps:在求的过程中,发现18的SN的首位得不到,转为求17位的SN,成功。
// getSerial.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "string.h" #include "stdlib.h" int main(int argc, char* argv[]) { int i,j; char name[100]; char laden[] = "i am Bin Laden"; char *SN =(char*)malloc(sizeof(char) * 100); while(true) { printf("Please enter name[10,16],finished with '#':"); scanf("%s",name); if(0 == strcmp(name,"#") ) break; strcat(name,laden); //这里我假设SN的长度为17..注意SN不唯一 //实验证明,如果取18则找不到SN[0] int cnt = 0 ; int lastCharIndex = 21; int startCharIndex = 5; for(j = 'A'; j <= 'Z' ;j++) { if(j == (((name[lastCharIndex] * j) % 0x1A) + 0x41) ) { SN[cnt++] = j; } } for(i = lastCharIndex-1; i >= startCharIndex ; i--) { SN[cnt++] = name[i] * SN[0] % 0x1A +0x41; } SN[cnt]='\0'; printf("Serial number is %s\n",SN); } return 0; }