有个哲人说:凡人总是迷失在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;
}