序列号保护机制
四种基本方法:将用户名等信息作为自变量,通过函数F变换之后得到注册码;通过注册码验证用户名的正确性;通过对等函数检查注册码;同时将用户名和注册码作为自变量(采用二元函数)。
序列号 = F(用户名)
攻击序列号保护机制常用的api(GetWindowsTextA(W)、GetDlgItemTextA(W)、GetDlgItemInt、hmemcpy)
制作注册机
对明码比较软件的攻击
keymake软件能够拦截程序指令并将出现的明码以某种方式直接显示出来
keymake需要拦截两次地址
浏览-->TraceMe.exe-->内存方式
点击生成会生成一个注册机
点击输入用户名 序列号会生成注册码
非明码比较
通过对等函数检查序列号。
F1 (用户名) = F2(序列号)
可以用GetDlgItemTextA、EndDialog等函数设断拦截
找到关键代码之后进行单步分析
部分关键代码
00401228 . 68 8E214000 push serial.0040218E ;pediy入栈 设为NAME
0040122D . E8 4C010000 call serial.0040137E ;计算K1(用户名)
00401232 . 50 push eax ; K1入栈
00401233 . 68 7E214000 push serial.0040217E ; 字符串1234入栈 设CODE
00401238 . E8 9B010000 call serial.004013D8 ; 计算K2
0040123D . 83C4 04 add esp,0x4 ;平衡栈
00401240 . 58 pop eax ; kernel32.74558484
00401241 . 3BC3 cmp eax,ebx ; k1与K2比较
00401243 . 74 07 je short serial.0040124C ;相等则成功
00401245 . E8 18010000 call serial.00401362 ;失败
call 0040137E
0040137E /$ 8B7424 04 mov esi,dword ptr ss:[esp+0x4]
00401382 |. 56 push esi ; serial.<ModuleEntryPoint>
00401383 |> 8A06 /mov al,byte ptr ds:[esi]
00401385 |. 84C0 |test al,al
00401387 |. 74 13 |je short serial.0040139C
00401389 |. 3C 41 |cmp al,0x41 ;判断是否大于"A"
0040138B |. 72 1F |jb short serial.004013AC
0040138D |. 3C 5A |cmp al,0x5A ; 判断是否大于"Z"
0040138F |. 73 03 |jnb short serial.00401394
00401391 |. 46 |inc esi ; serial.<ModuleEntryPoint>
00401392 |.^ EB EF |jmp short serial.00401383
00401394 |> E8 39000000 |call serial.004013D2
00401399 |. 46 |inc esi ; serial.<ModuleEntryPoint>
0040139A |.^ EB E7 \jmp short serial.00401383
0040139C |> 5E pop esi ; kernel32.74558484
0040139D |. E8 20000000 call serial.004013C2
004013A2 |. 81F7 78560000 xor edi,0x5678
004013A8 |. 8BC7 mov eax,edi ; serial.<ModuleEntryPoint>
004013AA |. EB 15 jmp short serial.004013C1
004013AC |> 5E pop esi ; kernel32.74558484
004013AD |. 6A 30 push 0x30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013AF |. 68 60214000 push serial.00402160 ; |Title = "Error! "
004013B4 |. 68 69214000 push serial.00402169 ; |Text = "Incorrect!,Try Again"
004013B9 |. FF75 08 push [arg.1] ; |hOwner = 0029B000
004013BC |. E8 79000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
004013C1 \> C3 retn
004013C2 /$ 33FF xor edi,edi ; serial.<ModuleEntryPoint>
004013C4 |. 33DB xor ebx,ebx
004013C6 |> 8A1E /mov bl,byte ptr ds:[esi]
004013C8 |. 84DB |test bl,bl
004013CA |. 74 05 |je short serial.004013D1
004013CC |. 03FB |add edi,ebx
004013CE |. 46 |inc esi ; serial.<ModuleEntryPoint>
004013CF |.^ EB F5 \jmp short serial.004013C6
004013D1 \> C3 retn
004013D2 /$ 2C 20 sub al,0x20 ;将ASCII的值减去20h 将小写转换成大写
004013D4 |. 8806 mov byte ptr ds:[esi],al
004013D6 \. C3 retn
call 4013D8
004013D8 /$ 33C0 xor eax,eax
004013DA |. 33FF xor edi,edi ; serial.<ModuleEntryPoint>
004013DC |. 33DB xor ebx,ebx
004013DE |. 8B7424 04 mov esi,dword ptr ss:[esp+0x4]
004013E2 |> B0 0A /mov al,0xA
004013E4 |. 8A1E |mov bl,byte ptr ds:[esi]
004013E6 |. 84DB |test bl,bl
004013E8 |. 74 0B |je short serial.004013F5
004013EA |. 80EB 30 |sub bl,0x30
004013ED |. 0FAFF8 |imul edi,eax
004013F0 |. 03FB |add edi,ebx
004013F2 |. 46 |inc esi ; serial.<ModuleEntryPoint>
004013F3 |.^ EB ED \jmp short serial.004013E2
004013F5 |> 81F7 34120000 xor edi,0x1234
004013FB |. 8BDF mov ebx,edi ; serial.<ModuleEntryPoint>
004013FD \. C3 retn
大致的算法
int i,k1=0,k2=0;
char ch;
for(i=0; cName[i]!=0&&i<=9;i++)
{
ch=(BYTE)cName[i];
if(ch<'A') return FALSE;
k1+=(ch>'Z')?(ch-32):ch;
}
k2=k1^0x5678^0x1234