【文章标题】: veneta的Crackme v22分析
【文章作者】: HappyTown
【作者邮箱】: [email]wxr277@163.com[/email]
【作者主页】: www.pediy.com
【软件名称】: Crackme_v22_(mini-psyho).exe
【下载地址】: 附件
【加壳方式】: FSG 2.0
【保护方式】: SHA1 + ElGamal
【编写语言】: VC6
【使用工具】: OD,IDA,DAMN_Hash
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
一、基本情况:
1. 先脱去FSG 2.0的壳;
2. 用PEiD的KANAL插件分析得知,该程序使用了SHA1和miracl库;
3. IDA载入,按Shift + F5键,右击鼠标,选择CryptoSIG,OK;
4. 在IDA的File菜单中选择Produce file -> Create MAP file...保存之;
二、分析:
1. 在OD中载入刚才生成的map文件,下断点bpx GetDlgItemTextA,F9运行;
2. 输入试炼码:
Name: happy
Serial: 1234567890ABCDEF9876543210DEABCF 9638527410963258AADDCCDDFFBBABCD(中间有一空格,原因在后面)
3. 从断点处向上翻:
004048A0 lea eax, [ebp-168]
004048A6 push eax
004048A7 call <_shs_init>
004048AC add esp, 4
004048AF push 0
004048B1 call <_mirvar>
004048B6 add esp, 4
004048B9 mov [41BA64], eax
004048BE push 0
004048C0 call <_mirvar>
004048C5 add esp, 4
004048C8 mov [41BA54], eax
004048CD push 0
004048CF call <_mirvar>
004048D4 add esp, 4
004048D7 mov [41BA50], eax
004048DC push 0
004048DE call <_mirvar>
004048E3 add esp, 4
004048E6 mov [41BA4C], eax
004048EB push 0
004048ED call <_mirvar>
004048F2 add esp, 4
004048F5 mov [41BA58], eax
004048FA push 0
004048FC call <_mirvar>
00404901 add esp, 4
00404904 mov [41BA48], eax
00404909 push 0
0040490B call <_mirvar>
00404910 add esp, 4
00404913 mov [41BA60], eax
00404918 push <a9a45bbf7bd4859> ;y ASCII "9A45BBF7BD4859AF4D4979978BA7F35F"
0040491D mov ecx, [41BA58]
00404923 push ecx
00404924 call <_cinstr>
00404929 add esp, 8
0040492C push <a985ad5d73b0481> ;g ASCII "985AD5D73B04816BD6CF039C125A52EA"
00404931 mov edx, [41BA48]
00404937 push edx
00404938 call <_cinstr>
0040493D add esp, 8
00404940 push <aF79a48c7431f55> ;p ASCII "F79A48C7431F55787B2BEA04B447ED73"
00404945 mov eax, [41BA50] ;
0040494A push eax
0040494B call <_cinstr>
00404950 add esp, 8
00404953 push 80 ; /Count = 80 (128.)
00404958 push <String> ; |Buffer = <dump.String>
0040495D push 3EA ; |ControlID = 3EA (1002.)
00404962 mov ecx, [<hWnd>] ; |
00404968 push ecx ; |hWnd => 0003016C (class='#32770')
00404969 call [<&USER32.GetDlgItemTextA>] ; \GetDlgItemTextA
0040496F mov [41B834], eax ; len(name)
00404974 mov dword ptr [41B1EC], 0
0040497E jmp short 0040498F
00404980 /mov edx, [41B1EC]
00404986 |add edx, 1
00404989 |mov [41B1EC], edx
0040498F mov eax, [41B1EC]
00404994 |cmp eax, [41B834]
0040499A |je short 004049BB
0040499C |mov ecx, [41B1EC]
004049A2 |movsx edx, byte ptr [ecx+<String>]
004049A9 |push edx
004049AA |lea eax, [ebp-168]
004049B0 |push eax
004049B1 |call <_shs_update>
004049B6 |add esp, 8
004049B9 \jmp short 00404980
004049BB push 0041B1F0
004049C0 lea ecx, [ebp-168]
004049C6 push ecx
004049C7 call <_shs_hash> ; ecx = sha1(name)
004049CC add esp, 8
004049CF mov edx, [41BA4C] ; h
004049D5 push edx
004049D6 push 0041B1F0 ; sha1(happy)=3978D009748EF54AD6EF7BF851BD55491B1FE6BB
004049DB push 10 ; 只取16个字节
004049DD call <_bytes_to_big>
004049E2 add esp, 0C
004049E5 push 100 ; /Count = 100 (256.)
004049EA push 0041B848 ; |Buffer = dump.0041B848
004049EF push 3EB ; |ControlID = 3EB (1003.)
004049F4 mov eax, [<hWnd>] ; |
004049F9 push eax ; |hWnd => 0003016C (class='#32770')
004049FA call [<&USER32.GetDlgItemTextA>] ; \GetDlgItemTextA
00404A00 mov [41B30C], eax
00404A05 push 0041B988 ; sn_2
00404A0A push 0041B948 ; sn_1
00404A0F push <aSS> ; ASCII "%s %s "(这里决定了中间的空格)
00404A14 push 0041B848 ; sn
00404A19 call <_sscanf>
00404A1E add esp, 10
00404A21 push 0041B948 ; sn_1
00404A26 mov ecx, [41BA64]
00404A2C push ecx
00404A2D call <_cinstr>
00404A32 add esp, 8
00404A35 push 0041B988 ; ASCII "9638527410963258AADDCCDDFFBBABCD"
00404A3A mov edx, [41BA60] ; sn_2
00404A40 push edx
00404A41 call <_cinstr>
00404A46 add esp, 8
00404A49 mov eax, [41BA58] ; y:9A45BBF7BD4859AF4D4979978BA7F35F
00404A4E push eax
00404A4F mov ecx, [41BA50] ; p:F79A48C7431F55787B2BEA04B447ED73
00404A55 push ecx
00404A56 mov edx, [41BA64] ; sn_1
00404A5C push edx
00404A5D mov eax, [41BA58] ; y
00404A62 push eax
00404A63 call <_powmod> ; y=y^sn_1(mod p)
00404A68 add esp, 10
00404A6B mov ecx, [41BA64] ; sn_1
00404A71 push ecx
00404A72 mov edx, [41BA50] ; p:F79A48C7431F55787B2BEA04B447ED73
00404A78 push edx
00404A79 mov eax, [41BA4C] ; h:SHA1(name)前16字节:3978D009748EF54AD6EF7BF851BD5549
00404A7E push eax
00404A7F mov ecx, [41BA64] ; sn_1
00404A85 push ecx
00404A86 call <_powmod> ; sn_1=sn_1^h (mod p)
00404A8B add esp, 10
00404A8E mov edx, [41BA60] ; sn_2
00404A94 push edx
00404A95 mov eax, [41BA50] ; p
00404A9A push eax
00404A9B mov ecx, [41BA60] ; sn_2
00404AA1 push ecx
00404AA2 mov edx, [41BA48] ; g
00404AA8 push edx
00404AA9 call <_powmod> ; sn_2=g^sn_2 (mod p)
00404AAE add esp, 10
00404AB1 mov eax, [41BA58] ; y:remainder
00404AB6 push eax
00404AB7 mov ecx, [41BA50] ; p
00404ABD push ecx
00404ABE mov edx, [41BA50] ; p
00404AC4 push edx
00404AC5 mov eax, [41BA54] ; 0
00404ACA push eax
00404ACB mov ecx, [41BA64] ; sn_1
00404AD1 push ecx
00404AD2 mov edx, [41BA58] ; y
00404AD8 push edx
00404AD9 call <_mad> ; y=(y*sn_1+0) (mod p)
00404ADE add esp, 18
00404AE1 mov eax, [41BA60] ; sn_2
00404AE6 push eax
00404AE7 mov ecx, [41BA58] ; y
00404AED push ecx
00404AEE call <_compare>
00404AF3 add esp, 8
00404AF6 test eax, eax
00404AF8 je short 00404B01
可以看出,这个Crackme属ElGamal签名验证算法。
该Crackme验证方式:(y^sn_1) * (sn_1^h)(mod p) ?= g^sn_2 (mod p),与标准验证方法有所差异。 (*)
ElGamal的标准验证:(y^sn_1)*(sn_1^sn_2)(mod p) ?= g^h (mod p)
所以对于(*),需求出:
1. sn_1 = g^x (mod p)
2. sn_2 = (x * sn_1 + k*h )(mod p-1),然后级联"sn_1 sn_2"即可,中间要用空格隔开。
通过http://www.alpertron.com.ar/DILOG.HTM在线计算出x(等待的时间太长了^_^):
x=B687E4D07A6A92A201627CC069866815
注意上面的计算只能使用10进制,所以得转换一下;看雪论坛提供的DLPTool算不出来。
剩下的就是写注册机了,详见附件内。
给出一组可用的注册码:
name:happy
serial:1F7A7AAE98F9CCA6740CAC3C74C6B520 CF93590A5397DC3D99562B23359EFDBF
--------------------------------------------------------------------------------
【经验总结】
很有可能 g 这个参数不是 p 的原根,导致在做出的注册机中当算出的sn_1或者sn_2较小时,生成的注册码不能通过验证。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年10月14日 20:34:32
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课