Bengly-km3 的分析过程(学习笔记)
1. 工具:w32dasm中文版, od1.10,peid
2. 运行环境:windows xp
3. 目的:制作keygen
首先,用peid查是否有壳,经查无壳(一般crackme都无壳,除非是用来练习脱壳的);
然后,用w32dasm反汇编,查找字符串:
" Please Fill In 1 Char to Continue!!"
" +=========================+
" Great, You are ranked as Level-3 "
" KeygenMe - #3"
" You Have Entered A Wrong Serial, "
"Bengaly"
"KeygenMe #3"
"MainWindow"
双击" Please Fill In 1 Char to Continue!!"
后向上看
* Possible Reference to Dialog: MAINWINDOW, CONTROL_ID:006A, ""
|
:004012B8 6A6A push 0000006A ;
:004012BA FF7508 push [ebp+08] 对话框的句柄
;
* Reference To: USER32.GetDlgItemTextA, Ord:0102h
|
:004012BD E80C010000 Call 004013CE ;调注册名
:004012C2 83F800 cmp eax, 00000000 ;判断是否输入注册名
:004012C5 7418 je 004012DF ;没有则over
:004012C7 6A40 push 00000040
:004012C9 683F314000 push 0040313F
* Possible Reference to Dialog: MAINWINDOW, CONTROL_ID:006B, ""
|
:004012CE 6A6B push 0000006B
:004012D0 FF7508 push [ebp+08]
* Reference To: USER32.GetDlgItemTextA, Ord:0102h
|
:004012D3 E8F6000000 Call 004013CE ;调注册码
:004012D8 83F800 cmp eax, 00000000 ;是否输入
:004012DB 7402 je 004012DF ;没有则over
:004012DD EB17 jmp 004012F6 ;都输入则跳到比较的程序
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004012C5(C), :004012DB(C)
|
:004012DF 6A00 push 00000000
* Possible StringData Ref from Data Obj ->"KeygenMe #3"
|
:004012E1 688C344000 push 0040348C
* Possible StringData Ref from Data Obj ->" Please Fill In 1 Char to Continue!!"
|
:004012E6 6800304000 push 00403000
:004012EB 6A00 push 00000000
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004012DD(U)
|
:004012F6 683F304000 push 0040303F
* Reference To: KERNEL32.lstrlenA, Ord:02E2h
|
:004012FB E834010000 Call 00401434
:00401300 33F6 xor esi, esi
:00401302 33DB xor ebx, ebx
:00401304 8BC8 mov ecx, eax ;注册名的位数保存在ecx中
:00401306 B801000000 mov eax, 00000001 ;eax 初始为1
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401331(C)
|
:0040130B 8B1D3F304000 mov ebx, dword ptr [0040303F] ;将注册名的前四位倒序送入ebx
:00401311 0FBE901F354000 movsx edx, byte ptr [eax+0040351F] ;这里是一个密码表
------------------------
[0040351f]: 0040351F 20 25 40 24 65 72 77 72 %@$erwr
00403527 23 40 24 24 21 40 23 32 #@$$!@#2
0040352F 31 24 40 5E 26 2A 26 28 1$@^&*&(
00403537 25 72 74 68 64 68 64 66 %rthdhdf
0040353F 77 34 32 33 25 23 44 53 w423%#DS
00403547 67 66 59 24 25 5E 23 24 gfY$%^#$
0040354F 25 62 72 65 23 42 40 40 %bre#B@@
00403557 25 23 47 33 72 65 00 00 %#G3re..
-------------------------------------------------------------------------
:00401318 2BDA sub ebx, edx ;ebx=ebx-edx
:0040131A 0FAFDA imul ebx, edx ;ebx=ebx*edx
:0040131D 8BF3 mov esi, ebx ;ebx---》esi,结果保存到esi
:0040131F 2BD8 sub ebx, eax ;ebx=ebx-eax
:00401321 81C343353504 add ebx, 04353543 ;ebx=04353504+ebx
:00401327 03F3 add esi, ebx ;刚才保存的结果加上ebx中的,,,esi=esi+ebx
:00401329 33F2 xor esi, edx ;esi=esi xor edx
:0040132B B804000000 mov eax, 00000004 ;[eax]=4
:00401330 49 dec ecx ;注册名的位数减1;这是循环变量
:00401331 75D8 jne 0040130B ;未取完继续循环
:00401333 56 push esi ;结果保存
:00401334 683F314000 push 0040313F
(下面的这个调用是注册码的计算过程)
:00401339 E84A000000 call 00401388 ;这是一个关键的call,进去看看
:0040133E 5E pop esi ,esi出栈;
:0040133F 3BC6 cmp eax, esi ;关键比较
:00401341 7515 jne 00401358 ;不等则over
:00401343 6A00 push 00000000
* Possible StringData Ref from Data Obj ->"KeygenMe #3"
:00401345 688C344000 push 0040348C
* Possible StringData Ref from Data Obj ->" Great, You are ranked as Level-3 "
->"at Keygening now"
|
:0040134A 68DD344000 push 004034DD
:0040134F 6A00 push 00000000
* Reference To: USER32.MessageBoxA, Ord:01BBh
|
:00401351 E89C000000 Call 004013F2
:00401356 EB13 jmp 0040136B
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401341(C)
:00401358 6A00 push 00000000
* Possible StringData Ref from Data Obj ->"KeygenMe #3"
|
:0040135A 688C344000 push 0040348C
* Possible StringData Ref from Data Obj ->" You Have Entered A Wrong Serial, ->"Please Try Again"
:0040135F 68AA344000 push 004034AA
:00401364 6A00 push 00000000
-----------------------------------------------
---------------------------------------------
这是刚才的 call 00401388 *(注册码的计算过程)
-------------------------------------------------
----------------------------------------------------
--------------------------------------------------------
00401388 /$ 55 push ebp
00401389 |. 8BEC mov ebp, esp
0040138B |. FF75 08 push dword ptr ss:[ebp+8] ; /String
0040138E.E8A1000000call <jmp.&KERNEL32.lstrlenA> ; \lstrlenA
00401393 |. 53 push ebx
00401394 |. 33DB xor ebx, ebx
00401396 |. 8BC8 mov ecx, eax ;注册码的位数送入ecx
00401398 |. 8B75 08 mov esi, dword ptr ss:[ebp+8] ;将注册码的内存地址送入esi
0040139B |> 51 /push ecx ;ecx入栈保存
0040139C |. 33C0 |xor eax, eax ;eax清零
0040139E |. AC |lods byte ptr ds:[esi] ;将注册码逐位送入eax,,(lods装入串, 把源串中的元素(字或字节)逐一装入AL或AX中.)
0040139F |. 83E8 30 |sub eax, 30 ;eax=eax-30
004013A2 |. 49 |dec ecx ;ecx减1,,,循环变量
004013A3 |. 74 05 |je short Key4.004013AA ;是零则跳
004013A5 |> 6BC0 0A |/imul eax, eax, 0A ;eax*A结果送eax
004013A8 |.^ E2 FB |\loopd short Key4.004013A5 ;直到ecx为零结束循环
004013AA |> 03D8 |add ebx, eax ;ebx=ebx+eax
004013AC |. 59 |pop ecx ;ecx出栈
004013AD |.^ E2 EC \loopd short Key4.0040139B ;直到ecx为零循环结束
004013AF |. 8BC3 mov eax, ebx ;eax=ebx
004013B1 |. 5B pop ebx
004013B2 |. C9 leave
004013B3 \. C2 0400 retn 4
将ebx的结果与以前的esi比较
二.总结:
1. 注册名的加密过程:将注册名的前四位的值倒序送入ebx,将eax初始位1,将密码表送入edx,
ebx=ebx-edx
ebx=ebx*edx
ebx--esi
ebx=ebx-eax
ebx=ebx+04353504
esi=esi+ebx
esi=esi^edx
eax=4
这样进行注册名的位数次循环,得出的值送入esi待用.
2 注册码的计算过程
将注册码值-30,送入eax,将注册码得长度送入len2,
len2-1, 然后eax=eax*0A;反复乘,即乘以0A的len2-1次方直到len2=0
ebx=eax+ebx,即eax反复累加
2. 进行比较
用esi 和 ebx进行比较
注册机由于编程水平不够,还在思考中,
有高手写出的话,贴出来学习一下!!!!
附件我没有权限,,没办法~~~~~~
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)