悬赏区的CrackMe分析
原帖地址:https://www.52hb.com/thread-36070-1-1.html因为是用流量共享手机开热点上网的,图不是很方便发。各位凑合一下吧。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
话说这好像是小生第一次逛悬赏区,悬赏CrackMe真的是清流啊。大汗。闲来无事,来调戏一下这个小CrackMe。这个CrackMe在启动的时候就有一个注册验证,分析如下:0041FD3B 55 push ebp
0041FD3C 8BEC mov ebp, esp
0041FD3E 81EC 44000000 sub esp, 0x44
0041FD44 C745 FC 0000000>mov dword ptr ss:, 0x0
0041FD4B C745 F8 0000000>mov dword ptr ss:, 0x0
0041FD52 C745 F4 0000000>mov dword ptr ss:, 0x0
0041FD59 C745 F0 0000000>mov dword ptr ss:, 0x0
0041FD60 6A FF push -0x1
0041FD62 6A 08 push 0x8
0041FD64 68 14000116 push 0x16010014
0041FD69 68 01000152 push 0x52010001
0041FD6E E8 EC040000 call Cm.0042025F
0041FD73 83C4 10 add esp, 0x10
0041FD76 8945 EC mov dword ptr ss:, eax
0041FD79 8D45 EC lea eax, dword ptr ss:
0041FD7C 50 push eax
0041FD7D E8 3CFFFFFF call Cm.0041FCBE ; 这里调用了一个易未知支持库函数,得到的文本从十六进制转换,保存结果,记为k
0041FD82 8945 E4 mov dword ptr ss:, eax ; 我这里得到的结果一直是0,不知道各位的呢?
0041FD85 8955 E8 mov dword ptr ss:, edx
0041FD88 8B5D EC mov ebx, dword ptr ss:
0041FD8B 85DB test ebx, ebx
0041FD8D 74 09 je short Cm.0041FD98
0041FD8F 53 push ebx
0041FD90 E8 A6040000 call Cm.0042023B
0041FD95 83C4 04 add esp, 0x4
0041FD98 DF6D E4 fild qword ptr ss:
0041FD9B DD5D DC fstp qword ptr ss:
0041FD9E DD45 DC fld qword ptr ss:
0041FDA1 DC05 00C34000 fadd qword ptr ds: ; k += *(double *)0x40C300
0041FDA7 DD5D D4 fstp qword ptr ss: ; 保存结果
0041FDAA DD45 D4 fld qword ptr ss: ; 装载结果
0041FDAD DC25 08C34000 fsub qword ptr ds: ; -= *(double *)0x40C308
0041FDB3 DD5D CC fstp qword ptr ss: ; 保存
0041FDB6 DD45 CC fld qword ptr ss: ; 装载
0041FDB9 DC05 10C34000 fadd qword ptr ds: ; += *(double *)0x40C310
0041FDBF DD5D C4 fstp qword ptr ss: ; 出
0041FDC2 DD45 C4 fld qword ptr ss: ; 入
0041FDC5 DC25 18C34000 fsub qword ptr ds: ; -= *(double *)0x40C318
0041FDCB DD5D BC fstp qword ptr ss: ; 出
0041FDCE DD45 BC fld qword ptr ss: ; 入
0041FDD1 E8 74F9FFFF call Cm.0041F74A ; 运算结果转换为int64(返回值由EAX:EDX传递)
0041FDD6 8945 FC mov dword ptr ss:, eax ; 取低32位保存进,记为f
0041FDD9 B8 20C34000 mov eax, Cm.0040C320 ; ASCII "acbd"
0041FDDE 8945 EC mov dword ptr ss:, eax
0041FDE1 8D45 EC lea eax, dword ptr ss:
0041FDE4 50 push eax
0041FDE5 E8 D4FEFFFF call Cm.0041FCBE ; 十六进制转换得到 EAX - > 0xABCD
0041FDEA 8945 E4 mov dword ptr ss:, eax ; = 0xABCD
0041FDED 8955 E8 mov dword ptr ss:, edx ; 这里ABCD的高32位就是0
0041FDF0 8B5D EC mov ebx, dword ptr ss:
0041FDF3 85DB test ebx, ebx
0041FDF5 74 09 je short Cm.0041FE00
0041FDF7 53 push ebx
0041FDF8 E8 3E040000 call Cm.0042023B ; 释放内存
0041FDFD 83C4 04 add esp, 0x4
0041FE00 8B45 E4 mov eax, dword ptr ss: ; ntdll.7C93532A
0041FE03 8945 F8 mov dword ptr ss:, eax ; = EAX(0xABCD)
0041FE06 DB45 FC fild dword ptr ss: ; 入0xABCD
0041FE09 DD5D E8 fstp qword ptr ss: ; 出double
0041FE0C DD45 E8 fld qword ptr ss: ; 压入f
0041FE0F DB45 F8 fild dword ptr ss: ; 压入0xABCD
0041FE12 DD5D E0 fstp qword ptr ss: ; 出double,
0041FE15 DC4D E0 fmul qword ptr ss: ; f *= 0xABCD
0041FE18 DD5D D8 fstp qword ptr ss: ; 结果出
0041FE1B DD45 D8 fld qword ptr ss: ; 再入
0041FE1E E8 27F9FFFF call Cm.0041F74A ; 结果转为int64
0041FE23 8945 F4 mov dword ptr ss:, eax ; 保存低32位,这是真正的注册码。记为x
0041FE26 68 00000000 push 0x0
0041FE2B BB 04010000 mov ebx, 0x104
0041FE30 E8 1E040000 call Cm.00420253
0041FE35 83C4 04 add esp, 0x4
0041FE38 8945 EC mov dword ptr ss:, eax
0041FE3B 68 78C34000 push Cm.0040C378 ; ASCII "\lzq.ini"
0041FE40 FF75 EC push dword ptr ss:
0041FE43 B9 02000000 mov ecx, 0x2
0041FE48 E8 15FEFFFF call Cm.0041FC62
0041FE4D 83C4 08 add esp, 0x8
0041FE50 8945 E8 mov dword ptr ss:, eax
0041FE53 8B5D EC mov ebx, dword ptr ss:
0041FE56 85DB test ebx, ebx
0041FE58 74 09 je short Cm.0041FE63
0041FE5A 53 push ebx
0041FE5B E8 DB030000 call Cm.0042023B
0041FE60 83C4 04 add esp, 0x4
0041FE63 6A 00 push 0x0
0041FE65 6A 00 push 0x0
0041FE67 6A 00 push 0x0
0041FE69 68 04000080 push 0x80000004
0041FE6E 6A 00 push 0x0
0041FE70 68 81C34000 push Cm.0040C381 ; ASCII "cmm"
0041FE75 68 04000080 push 0x80000004
0041FE7A 6A 00 push 0x0
0041FE7C 68 85C34000 push Cm.0040C385 ; ASCII "lzq"
0041FE81 68 04000080 push 0x80000004
0041FE86 6A 00 push 0x0
0041FE88 8B45 E8 mov eax, dword ptr ss:
0041FE8B 85C0 test eax, eax
0041FE8D 75 05 jnz short Cm.0041FE94
0041FE8F B8 89C34000 mov eax, Cm.0040C389
0041FE94 50 push eax
0041FE95 68 04000000 push 0x4
0041FE9A BB C8080000 mov ebx, 0x8C8
0041FE9F E8 AF030000 call Cm.00420253 ; 读取运行目录下的lzq.ini,并判断节中的cmm项是否为x
如果那个未知库函数的返回结果和我一样为0的话,那么,KeyFile就是lzq.ini,放到程序目录下面就OK了。
Lzq.ini内容如下:
cmm = 648285852
;爆破的话,Very Easy.
0041FF22 /0F84 CB000000 je Cm.0041FFF3
0041FF08 0f94c0 sete al
0041FF0B 8945 E8 mov dword ptr ss:, eax
然后是灰色按钮分析,对于楼主所说易语言的窗体格式编译后的保存形式,我没有研究,也觉得没必要研究,汗。我一般如果补丁的话,就是自己写Loader,在一些恶心的地方,比如CreateWindow上面做文章,慢慢玩,不急嘛~~~在CreateWindowExA上面写断点。若干次中断后。0012FA50 100AE189/CALL 到 CreateWindowExA 来自 krnln.100AE183
0012FA54 00000000|ExtStyle = 0
0012FA58 100E2B30|Class = "BUTTON"
0012FA5C 00B23F90|WindowName = "注册"
0012FA60 4C012F00|Style = WS_CHILD|WS_TABSTOP|WS_CLIPSIBLINGS|WS_DISABLED|2F00
0012FA64 00000020|X = 20 (32.)
0012FA68 00000050|Y = 50 (80.)
0012FA6C 00000038|Width = 38 (56.)
0012FA70 00000020|Height = 20 (32.)
0012FA74 00040912|hParent = 00040912 ('未注册 By:kkbblzq',class='Afx:10000000:b:10011:1900015:0')
0012FA78 000000A0|hMenu = 000000A0 (window)
0012FA7C 10000000|hInst = 10000000
0012FA80 00000000\lParam = NULL
类名是Windows预定义的BUTTON错不了的,而且风格里面,有个WS_DISABLED。修改的办法很简单。转到0x12FA60,也就是那个风格参数的地方,从4C012F00改为44012F00。然后去掉断点,F9运行起来。不过在此之前,还得把我们的lzq.ini删掉。不出意外,按钮已经激活了。0041F9AB 55 push ebp
0041F9AC 8BEC mov ebp, esp
0041F9AE 81EC 40000000 sub esp, 0x40
0041F9B4 C745 FC 0000000>mov dword ptr ss:, 0x0
0041F9BB C745 F8 0000000>mov dword ptr ss:, 0x0
0041F9C2 C745 F4 0000000>mov dword ptr ss:, 0x0
0041F9C9 6A FF push -0x1
0041F9CB 6A 08 push 0x8
0041F9CD 68 14000116 push 0x16010014
0041F9D2 68 01000152 push 0x52010001
0041F9D7 E8 83080000 call Cm.0042025F ; 取A码
0041F9DC 83C4 10 add esp, 0x10
0041F9DF 8945 F0 mov dword ptr ss:, eax ; = A码
0041F9E2 8D45 F0 lea eax, dword ptr ss:
0041F9E5 50 push eax
0041F9E6 E8 D3020000 call Cm.0041FCBE ; A码从十六进制转int
0041F9EB 8945 E8 mov dword ptr ss:, eax ; = intA码
0041F9EE 8955 EC mov dword ptr ss:, edx ; = 高16位
0041F9F1 8B5D F0 mov ebx, dword ptr ss:
0041F9F4 85DB test ebx, ebx ; krnln.100E33E4
0041F9F6 74 09 je short Cm.0041FA01
0041F9F8 53 push ebx ; krnln.100E33E4
0041F9F9 E8 3D080000 call Cm.0042023B ; 释放内存
0041F9FE 83C4 04 add esp, 0x4
0041FA01 DF6D E8 fild qword ptr ss: ; 入A码
0041FA04 DD5D E0 fstp qword ptr ss: ; 出0041FA07 DD45 E0 fld qword ptr ss:
0041FA0A DC05 00C34000 fadd qword ptr ds: ; += *(double *)0x40C300
0041FA10 DD5D D8 fstp qword ptr ss: ; 出
0041FA13 DD45 D8 fld qword ptr ss: ; 入
0041FA16 DC25 08C34000 fsub qword ptr ds: ; -= *(double *)0x40C300
0041FA1C DD5D D0 fstp qword ptr ss: ; 出
0041FA1F DD45 D0 fld qword ptr ss: ; 入
0041FA22 DC05 10C34000 fadd qword ptr ds: ; += *(double *)0x40C310
0041FA28 DD5D C8 fstp qword ptr ss: ; 出
0041FA2B DD45 C8 fld qword ptr ss: ; 入
0041FA2E DC25 18C34000 fsub qword ptr ds: ; -= *(double *)0x40C318
0041FA34 DD5D C0 fstp qword ptr ss: ; 出
0041FA37 DD45 C0 fld qword ptr ss: ; 入
0041FA3A E8 0BFDFFFF call Cm.0041F74A ; 转int64,只要低32位
0041FA3F 8945 FC mov dword ptr ss:, eax ; 结果记为k
0041FA42 B8 20C34000 mov eax, Cm.0040C320 ; ASCII "acbd"
0041FA47 8945 F0 mov dword ptr ss:, eax
0041FA4A 8D45 F0 lea eax, dword ptr ss:
0041FA4D 50 push eax ; "ABCD"从十六转十
0041FA4E E8 6B020000 call Cm.0041FCBE ; EAX - > 0xABCD
0041FA53 8945 E8 mov dword ptr ss:, eax ; 保存
0041FA56 8955 EC mov dword ptr ss:, edx
0041FA59 8B5D F0 mov ebx, dword ptr ss:
0041FA5C 85DB test ebx, ebx ; krnln.100E33E4
0041FA5E 74 09 je short Cm.0041FA69
0041FA60 53 push ebx ; krnln.100E33E4
0041FA61 E8 D5070000 call Cm.0042023B ; 释放内存
0041FA66 83C4 04 add esp, 0x4
0041FA69 8B45 E8 mov eax, dword ptr ss:
0041FA6C 8945 F8 mov dword ptr ss:, eax ; = 0xABCD
0041FA6F DB45 FC fild dword ptr ss: ; 入k
0041FA72 DD5D EC fstp qword ptr ss: ; 出
0041FA75 DD45 EC fld qword ptr ss: ; 入
0041FA78 DB45 F8 fild dword ptr ss: ; 入0xABCD
0041FA7B DD5D E4 fstp qword ptr ss: ; 出
0041FA7E DC4D E4 fmul qword ptr ss: ; 0xABCD * k
0041FA81 DD5D DC fstp qword ptr ss: ; 结果出
0041FA84 DD45 DC fld qword ptr ss: ; 入
0041FA87 E8 BEFCFFFF call Cm.0041F74A ; 转为int64
0041FA8C 8945 F4 mov dword ptr ss:, eax ; 只要低32位
0041FA8F 68 01030080 push 0x80000301
0041FA94 6A 00 push 0x0
0041FA96 FF75 F4 push dword ptr ss:
0041FA99 68 01000000 push 0x1
0041FA9E BB 68010000 mov ebx, 0x168
0041FAA3 E8 AB070000 call Cm.00420253 ; 到文本(十进制)
0041FAA8 83C4 10 add esp, 0x10
0041FAAB 8945 F0 mov dword ptr ss:, eax
0041FAAE 6A FF push -0x1
0041FAB0 6A 08 push 0x8
0041FAB2 68 03000116 push 0x16010003
0041FAB7 68 01000152 push 0x52010001
0041FABC E8 9E070000 call Cm.0042025F ; 取注册码
0041FAC1 83C4 10 add esp, 0x10
0041FAC4 8945 EC mov dword ptr ss:, eax
0041FAC7 8B45 F0 mov eax, dword ptr ss:
0041FACA 50 push eax
0041FACB FF75 EC push dword ptr ss:
0041FACE E8 3BFEFFFF call Cm.0041F90E ; 比较
算法都是一样的,只是用前面提到的未知支持库函数替换了A码。来一发注册机吧。我都不好意思说这是算法分析了,因为这种类型的注册验证。。。。。。直接把反汇编代码抠出来用就好了,毫无技术含量可言。Code = f(user)
if (Code == 用户输入)
.686
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
.data
Key1 db 00h,0E0h,45h,0D1h,05h,5Eh,63h,42h
Key2 db 00,00,80h,0B0h,28h,41h,0CEh,41h
Key3 db 00,00,0E2h,0EAh,0C4h,08h,2Fh,42h
Key4 db 00,00,00,00,80h,0B9h,0C2h,40h
Key5 dd 0ACBDh
ACode dq 2341h ;你的A码
Buf dq 0
Set dw 0
Old dw 0
szText db '注册码是:%d',0
szTitle db 'OK!',0
szBuf db 255 dup(0)
.code
_START:
fild ACode
fstp ACode
fld ACode
fadd qword ptr Key1
fstp Buf
fld Buf
fsub qword ptr Key2
fstp Buf
fld Buf
fadd qword ptr Key3
fstp Buf
fld Buf
fsub qword ptr Key4
fstp Buf
fld Buf
fstcw Old
mov ax,Old
or ax,0Ch
mov Set,ax
fldcw Set
fistp Buf
fldcw Old
mov dword ptr Buf,0
fild dword ptr Buf
fstp Buf
fld Buf
fild Key5
fstp qword ptr Key1
fmul qword ptr Key1
fstcw Old
mov ax,Old
or ax,0Ch
mov Set,ax
fldcw Set
fistp Buf
fldcw Old
mov dword ptr Buf,0
invoke wsprintf,offset szBuf,offset szText,Buf
invoke MessageBox,0,offset szBuf,offset szTitle,MB_ICONINFORMATION
invoke ExitProcess,0
end _START
感谢楼主分享 厉害了,过年来赶紧来学习一下。 @李沉舟楼主,这里还有个问题。你的激活按钮,是修改了堆栈吧,只能运行一次。我之前看到的小生我怕怕的成品逆向,打开直接看到按钮是激活了的。这是怎么做到的,不知道楼主能否指点一下 过林黑马 发表于 2018-2-22 18:24
@李沉舟楼主,这里还有个问题。你的激活按钮,是修改了堆栈吧,只能运行一次。我之前看到的小生我怕怕的 ...
在内存里面找“按钮2”,往后面找07,改05即可激活。
李沉舟 发表于 2018-2-23 09:32
在内存里面找“按钮2”,往后面找07,改05即可激活。
你的怎么都能查看到按钮2,还有能看到注册这些中文,我查找都是没有的 过林黑马 发表于 2018-2-23 21:38
你的怎么都能查看到按钮2,还有能看到注册这些中文,我查找都是没有的
点一下上面的M,或者按atl+m,ctrl+b,勾选查找整个块
李沉舟 发表于 2018-2-23 22:01
点一下上面的M,或者按atl+m,ctrl+b,勾选查找整个块
找到了,但是不能保存的,这个内存修改。我保存的时候只能保存为mem文件 过林黑马 发表于 2018-2-23 22:58
找到了,但是不能保存的,这个内存修改。我保存的时候只能保存为mem文件
终于搞定了,原来这是要在内存找地址,然后返回数据窗口修改才可以保存。哈哈 思考了许久 感觉难
页:
[1]
2