举个简单的例子说明下,以下就是软件的注册码关键代码,根据其生成注册码的函数,分析其思路,写出相应的程序生成注册码即可。
004011AE . 6A 51 PUSH 51 ; /Count = 51 (81.)
004011B0 . 50 PUSH EAX ; |Buffer
004011B1 . 6A 6E PUSH 6E ; |ControlID = 6E (110.)
004011B3 . 56 PUSH ESI ; |hWnd
004011B4 . FFD7 CALL EDI ; \GetDlgItemTextA
004011B6 . 8D8C24 9C0000>LEA ECX,DWORD PTR SS:[ESP+9C]
004011BD . 6A 65 PUSH 65 ; /Count = 65 (101.)
004011BF . 51 PUSH ECX ; |Buffer
004011C0 . 68 E8030000 PUSH 3E8 ; |ControlID = 3E8 (1000.)
004011C5 . 56 PUSH ESI ; |hWnd
004011C6 . 8BD8 MOV EBX,EAX ; |EBX存放用户名的长度
004011C8 . FFD7 CALL EDI ; \GetDlgItemTextA
004011CA . 8A4424 4C MOV AL,BYTE PTR SS:[ESP+4C]
004011CE . 84C0 TEST AL,AL ; 是否结束
004011D0 . 74 76 JE SHORT TraceMe.00401248
004011D2 . 83FB 05 CMP EBX,5
004011D5 . 7C 71 JL SHORT TraceMe.00401248 ; 如果用户名长度小于5,跳
004011D7 . 8D5424 4C LEA EDX,DWORD PTR SS:[ESP+4C] ; EDX指向用户名
004011DB . 53 PUSH EBX ; 用户名长度
004011DC . 8D8424 A00000>LEA EAX,DWORD PTR SS:[ESP+A0]
004011E3 . 52 PUSH EDX ; 用户名
004011E4 . 50 PUSH EAX ; key
004011E5 . E8 56010000 CALL TraceMe.00401340 ; 判断注册码是否正确,有三个参数[输入key,用户名,用户名长度]
思路:
从用户名的第4个字符开始分别与全局的一个长度为7的标识相乘最后和就为key
--注册码部分--
00401340 /$ 55 PUSH EBP ; 保存EBP
00401341 |. 8B6C24 0C MOV EBP,DWORD PTR SS:[ESP+C] ; 获取第2个参数,用户名
00401345 |. 56 PUSH ESI ; 保护ESI,EDI
00401346 |. 57 PUSH EDI
00401347 |. 8B7C24 18 MOV EDI,DWORD PTR SS:[ESP+18] ; 取第一个参数,用户名长度
0040134B |. B9 03000000 MOV ECX,3
00401350 |. 33F6 XOR ESI,ESI
00401352 |. 33C0 XOR EAX,EAX
00401354 |. 3BF9 CMP EDI,ECX
00401356 |. 7E 21 JLE SHORT TraceMe.00401379 ; 如果用户名长度小于等于3,跳
00401358 |. 53 PUSH EBX
00401359 |> 83F8 07 /CMP EAX,7
0040135C |. 7E 02 |JLE SHORT TraceMe.00401360 ; 如果EAX小于等于7,跳
0040135E |. 33C0 |XOR EAX,EAX
00401360 |> 33D2 |XOR EDX,EDX
00401362 |. 33DB |XOR EBX,EBX
00401364 |. 8A1429 |MOV DL,BYTE PTR DS:[ECX+EBP] ; DL存放从用户名中取出的第ECX字符
00401367 |. 8A98 30504000 |MOV BL,BYTE PTR DS:[EAX+405030] ; BL存放某个全局变量
0040136D |. 0FAFD3 |IMUL EDX,EBX ; 某个用户名×全局变量C
00401370 |. 03F2 |ADD ESI,EDX ; ESI似乎是这些值的统计
00401372 |. 41 |INC ECX
00401373 |. 40 |INC EAX
00401374 |. 3BCF |CMP ECX,EDI ; 如果ECX小于用户名的长度则继续循环
00401376 |.^ 7C E1 \JL SHORT TraceMe.00401359
00401378 |. 5B POP EBX ; 还原EBX,不需要使用了
00401379 |> 56 PUSH ESI ; /<%ld>
0040137A |. 68 78504000 PUSH TraceMe.00405078 ; |Format = "%ld"
0040137F |. 55 PUSH EBP ; |s
00401380 |. FF15 9C404000 CALL DWORD PTR DS:[<&USER32.wsprintfA>] ; \wsprintfA
00401386 |. 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]
0040138A |. 83C4 0C ADD ESP,0C ; C调用方式
0040138D |. 55 PUSH EBP ; /String2
0040138E |. 50 PUSH EAX ; |String1
0040138F |. FF15 04404000 CALL DWORD PTR DS:[<&KERNEL32.lstrcmpA>] ; \lstrcmpA
00401395 |. F7D8 NEG EAX
00401397 |. 1BC0 SBB EAX,EAX
00401399 |. 5F POP EDI
0040139A |. 5E POP ESI
0040139B |. 40 INC EAX
0040139C |. 5D POP EBP
0040139D \. C3 RETN
004011AE . 6A 51 PUSH 51 ; /Count = 51 (81.)
004011B0 . 50 PUSH EAX ; |Buffer
004011B1 . 6A 6E PUSH 6E ; |ControlID = 6E (110.)
004011B3 . 56 PUSH ESI ; |hWnd
004011B4 . FFD7 CALL EDI ; \GetDlgItemTextA
004011B6 . 8D8C24 9C0000>LEA ECX,DWORD PTR SS:[ESP+9C]
004011BD . 6A 65 PUSH 65 ; /Count = 65 (101.)
004011BF . 51 PUSH ECX ; |Buffer
004011C0 . 68 E8030000 PUSH 3E8 ; |ControlID = 3E8 (1000.)
004011C5 . 56 PUSH ESI ; |hWnd
004011C6 . 8BD8 MOV EBX,EAX ; |EBX存放用户名的长度
004011C8 . FFD7 CALL EDI ; \GetDlgItemTextA
004011CA . 8A4424 4C MOV AL,BYTE PTR SS:[ESP+4C]
004011CE . 84C0 TEST AL,AL ; 是否结束
004011D0 . 74 76 JE SHORT TraceMe.00401248
004011D2 . 83FB 05 CMP EBX,5
004011D5 . 7C 71 JL SHORT TraceMe.00401248 ; 如果用户名长度小于5,跳
004011D7 . 8D5424 4C LEA EDX,DWORD PTR SS:[ESP+4C] ; EDX指向用户名
004011DB . 53 PUSH EBX ; 用户名长度
004011DC . 8D8424 A00000>LEA EAX,DWORD PTR SS:[ESP+A0]
004011E3 . 52 PUSH EDX ; 用户名
004011E4 . 50 PUSH EAX ; key
004011E5 . E8 56010000 CALL TraceMe.00401340 ; 判断注册码是否正确,有三个参数[输入key,用户名,用户名长度]
思路:
从用户名的第4个字符开始分别与全局的一个长度为7的标识相乘最后和就为key
--注册码部分--
00401340 /$ 55 PUSH EBP ; 保存EBP
00401341 |. 8B6C24 0C MOV EBP,DWORD PTR SS:[ESP+C] ; 获取第2个参数,用户名
00401345 |. 56 PUSH ESI ; 保护ESI,EDI
00401346 |. 57 PUSH EDI
00401347 |. 8B7C24 18 MOV EDI,DWORD PTR SS:[ESP+18] ; 取第一个参数,用户名长度
0040134B |. B9 03000000 MOV ECX,3
00401350 |. 33F6 XOR ESI,ESI
00401352 |. 33C0 XOR EAX,EAX
00401354 |. 3BF9 CMP EDI,ECX
00401356 |. 7E 21 JLE SHORT TraceMe.00401379 ; 如果用户名长度小于等于3,跳
00401358 |. 53 PUSH EBX
00401359 |> 83F8 07 /CMP EAX,7
0040135C |. 7E 02 |JLE SHORT TraceMe.00401360 ; 如果EAX小于等于7,跳
0040135E |. 33C0 |XOR EAX,EAX
00401360 |> 33D2 |XOR EDX,EDX
00401362 |. 33DB |XOR EBX,EBX
00401364 |. 8A1429 |MOV DL,BYTE PTR DS:[ECX+EBP] ; DL存放从用户名中取出的第ECX字符
00401367 |. 8A98 30504000 |MOV BL,BYTE PTR DS:[EAX+405030] ; BL存放某个全局变量
0040136D |. 0FAFD3 |IMUL EDX,EBX ; 某个用户名×全局变量C
00401370 |. 03F2 |ADD ESI,EDX ; ESI似乎是这些值的统计
00401372 |. 41 |INC ECX
00401373 |. 40 |INC EAX
00401374 |. 3BCF |CMP ECX,EDI ; 如果ECX小于用户名的长度则继续循环
00401376 |.^ 7C E1 \JL SHORT TraceMe.00401359
00401378 |. 5B POP EBX ; 还原EBX,不需要使用了
00401379 |> 56 PUSH ESI ; /<%ld>
0040137A |. 68 78504000 PUSH TraceMe.00405078 ; |Format = "%ld"
0040137F |. 55 PUSH EBP ; |s
00401380 |. FF15 9C404000 CALL DWORD PTR DS:[<&USER32.wsprintfA>] ; \wsprintfA
00401386 |. 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]
0040138A |. 83C4 0C ADD ESP,0C ; C调用方式
0040138D |. 55 PUSH EBP ; /String2
0040138E |. 50 PUSH EAX ; |String1
0040138F |. FF15 04404000 CALL DWORD PTR DS:[<&KERNEL32.lstrcmpA>] ; \lstrcmpA
00401395 |. F7D8 NEG EAX
00401397 |. 1BC0 SBB EAX,EAX
00401399 |. 5F POP EDI
0040139A |. 5E POP ESI
0040139B |. 40 INC EAX
0040139C |. 5D POP EBP
0040139D \. C3 RETN
private
string
GetKey(
string
userName,
int
userNameLength)
{
int ecx = 3 ;
int sum = 0 ;
int eax = 0 ;
int [] flag = { 0x0C , 0x0A , 0x13 , 0x09 , 0x0C , 0x0B , 0x0A , 0x08 };
while (ecx < userNameLength)
{
if (eax >= flag.Length)
eax = eax % flag.Length;
sum += userName[ecx] * flag[eax];
ecx ++ ;
eax ++ ;
}
return sum.ToString();
}
{
int ecx = 3 ;
int sum = 0 ;
int eax = 0 ;
int [] flag = { 0x0C , 0x0A , 0x13 , 0x09 , 0x0C , 0x0B , 0x0A , 0x08 };
while (ecx < userNameLength)
{
if (eax >= flag.Length)
eax = eax % flag.Length;
sum += userName[ecx] * flag[eax];
ecx ++ ;
eax ++ ;
}
return sum.ToString();
}