文章作者:divinomas
这个crackme是tkm2004年的strainer,用ECC保护的。虽然ECC大家玩得比较熟了,不过这个东东的保护方法还是有点意思。
用PEiD查壳并脱壳,unpack不是目的,算法才是关键。unpack后载入ida,用miracl的sig,或
http://www.secretashell.com/cryptocrk/tutorials/miracl.calls.zip这里的方法识别miracl库函数,检查序列号的流程一目了然。
1.获取name,sn1,sn2
代码:
Un_FSG__:0040194Cloc_40194C:
Un_FSG__:0040194Cpush50h
Un_FSG__:0040194Epushoffsetname
Un_FSG__:00401953push2
Un_FSG__:00401955pushedi
Un_FSG__:00401956callGetDlgItemText;name>=4
Un_FSG__:0040195Bmovesi,eax
Un_FSG__:0040195Dpush50h
Un_FSG__:0040195Fpushoffsetsn1
Un_FSG__:00401964push3
Un_FSG__:00401966pushedi
Un_FSG__:00401967callGetDlgItemText;sn1>=4
Un_FSG__:0040196Cmovebx,eax
Un_FSG__:0040196Epush50h
Un_FSG__:00401970pushoffsetsn2
Un_FSG__:00401975push4
Un_FSG__:00401977pushedi
Un_FSG__:00401978callGetDlgItemText;sn2>=1
2.检查序列号
1)椭圆曲线E(a,b,p)、点(pt1,pt2,pt3,pt4,pt5)初始化
代码:
Un_FSG__:0040149Ccallepoint_init
Un_FSG__:004014A1movedi,eax
Un_FSG__:004014A3mov[esp+1F8h+var_1F8],0
Un_FSG__:004014AAcall_mirvar
Un_FSG__:004014AFmov[ebp+pt2_x],eax
Un_FSG__:004014B5callepoint_init
Un_FSG__:004014BAmov[esp+1F8h+var_1F8],0
Un_FSG__:004014C1mov[ebp+pt2],eax
Un_FSG__:004014C7call_mirvar
Un_FSG__:004014CCmov[ebp+big_t],eax
Un_FSG__:004014D2callepoint_init
Un_FSG__:004014D7mov[ebp+pt3],eax
Un_FSG__:004014DDcallepoint_init
Un_FSG__:004014E2mov[ebp+pt4],eax
Un_FSG__:004014E8callepoint_init
Un_FSG__:004014EDmovdwordptr[esi+220h],10h
Un_FSG__:004014F7mov[ebp+pt5],eax
...
Un_FSG__:00401512movebx,[ebp+a]
Un_FSG__:00401518pushoffseta416d656e657369;"416D656E65736961"
Un_FSG__:0040151Dpushebx
Un_FSG__:0040151Ecall_cinstr
Un_FSG__:00401523popeax
Un_FSG__:00401524popedx
Un_FSG__:00401525moveax,[ebp+b]
Un_FSG__:0040152Bpushoffseta1b35b7093fee5a;"1B35B7093FEE5AE601A"
Un_FSG__:00401530pusheax
Un_FSG__:00401531call_cinstr
Un_FSG__:00401536popebx
Un_FSG__:00401537popesi
Un_FSG__:00401538movesi,[ebp+p]
Un_FSG__:0040153EpushoffsetaFffffffdffffff;"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"
Un_FSG__:00401543pushesi
Un_FSG__:00401544call_cinstr
Un_FSG__:00401549popeax
Un_FSG__:0040154Apopedx
Un_FSG__:0040154Bmovedx,[ebp+pt1_x]
Un_FSG__:00401551pushoffseta71263a72c2fdfb;"71263A72C2FDFB8FE851182B408210A4"
Un_FSG__:00401556pushedx
Un_FSG__:00401557call_cinstr
Un_FSG__:0040155Cmoveax,[ebp+pt2_x]
Un_FSG__:00401562popecx
Un_FSG__:00401563popebx
Un_FSG__:00401564pushoffseta2c052124bdd94e;"2C052124BDD94E5645E99B01DCECA28D"
Un_FSG__:00401569pusheax
Un_FSG__:0040156Acall_cinstr
Un_FSG__:0040156Fmoveax,[ebp+p]
Un_FSG__:00401575push1
Un_FSG__:00401577pusheax
Un_FSG__:00401578moveax,[ebp+b]
Un_FSG__:0040157Epusheax
Un_FSG__:0040157Fmoveax,[ebp+a]
Un_FSG__:00401585pusheax
Un_FSG__:00401586call_ecurve_init
Un_FSG__:0040158Bmoveax,[ebp+pt1_x]
Un_FSG__:00401591addesp,20h
Un_FSG__:00401594pushedi;pt1
Un_FSG__:00401595push0
Un_FSG__:00401597pusheax
Un_FSG__:00401598moveax,[ebp+pt1_x]
Un_FSG__:0040159Epusheax
Un_FSG__:0040159Fcall_epoint_set
Un_FSG__:004015A4movecx,[ebp+pt2_x]
Un_FSG__:004015AAmoveax,[ebp+pt2]
Un_FSG__:004015B0movebx,[ebp+pt2_x]
Un_FSG__:004015B6pusheax
Un_FSG__:004015B7push1
Un_FSG__:004015B9pushebx
Un_FSG__:004015BApushecx
Un_FSG__:004015BBcall_epoint_set
其中E的参数为:
a:416D656E65736961
b:1B35B7093FEE5AE601A
p:FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF
pt1的x坐标为:71263A72C2FDFB8FE851182B408210A4
pt2的x坐标为:2C052124BDD94E5645E99B01DCECA28D
2)sn1,sn2转变为大数,并变形
代码:
Un_FSG__:004015C0movesi,[ebp+big_sn1]
Un_FSG__:004015C6addesp,18h
Un_FSG__:004015C9movsxebx,ds:Serial_sign
Un_FSG__:004015D0pushoffsetsn1
Un_FSG__:004015D5subebx,30h
Un_FSG__:004015D8pushesi
Un_FSG__:004015D9leaesi,[ebp+var_1A8]
Un_FSG__:004015DFcall_cinstr
Un_FSG__:004015E4popeax
Un_FSG__:004015E5popedx
Un_FSG__:004015E6moveax,[ebp+big_sn2]
Un_FSG__:004015ECpushoffsetsn2
Un_FSG__:004015F1pusheax
Un_FSG__:004015F2call_cinstr
其中sn1的第一个byte是正负标志位,剩下的部分转化为大数
代码:
Un_FSG__:004015F7moveax,[ebp+big_t]
Un_FSG__:004015FDpusheax
Un_FSG__:004015FEmoveax,[ebp+p]
Un_FSG__:00401604pusheax
Un_FSG__:00401605moveax,[ebp+big_sn1]
Un_FSG__:0040160Bpush1
Un_FSG__:0040160Dpusheax
Un_FSG__:0040160Ecall_powmod
Un_FSG__:00401613moveax,[ebp+big_t]
Un_FSG__:00401619addesp,20h
Un_FSG__:0040161Cmovedx,[ebp+pt3]
Un_FSG__:00401622pushedx
Un_FSG__:00401623pushebx
Un_FSG__:00401624xorebx,ebx
Un_FSG__:00401626pusheax
Un_FSG__:00401627moveax,[ebp+big_t]
Un_FSG__:0040162Dpusheax
Un_FSG__:0040162Ecall_epoint_set
pt3的x坐标为big_sn1%p
3)计算name的sha值,并变形
代码:
Un_FSG__:00401636call_shs_init
Un_FSG__:0040163Bmoval,ds:name
Un_FSG__:00401640addesp,10h
Un_FSG__:00401643testal,al
Un_FSG__:00401645jzshortloc_401661
Un_FSG__:00401647
Un_FSG__:00401647loc_401647:;CODEXREF:_check+27Fj
Un_FSG__:00401647movsxecx,al
Un_FSG__:0040164Apushedx
Un_FSG__:0040164Bincebx
Un_FSG__:0040164Cpushedx
Un_FSG__:0040164Dpushecx
Un_FSG__:0040164Epushesi
Un_FSG__:0040164Fcall_shs_process
Un_FSG__:00401654moval,ds:name[ebx]
Un_FSG__:0040165Aaddesp,10h
Un_FSG__:0040165Dtestal,al
Un_FSG__:0040165Fjnzshortloc_401647
Un_FSG__:00401661
Un_FSG__:00401661loc_401661:;CODEXREF:_check+265j
Un_FSG__:00401661pushebx
Un_FSG__:00401662pushebx
Un_FSG__:00401663leaebx,[ebp+var_38]
Un_FSG__:00401666pushebx
Un_FSG__:00401667pushesi
Un_FSG__:00401668call_shs_hash
Un_FSG__:0040166Dmovedx,[ebp+big_hName]
Un_FSG__:00401673addesp,0Ch
Un_FSG__:00401676pushedx
Un_FSG__:00401677pushebx
Un_FSG__:00401678push14h
Un_FSG__:0040167Acall_bytes_to_big
Un_FSG__:0040167Fmoveax,[ebp+big_hName]
Un_FSG__:00401685pusheax
Un_FSG__:00401686moveax,[ebp+p2];FFFFFFFE000000006FAFED9C3353F08D
Un_FSG__:0040168Cpusheax
Un_FSG__:0040168Dmoveax,[ebp+big_hName]
Un_FSG__:00401693push3
Un_FSG__:00401695pusheax
Un_FSG__:00401696call_powmod
big_hName=sha(name)^3%p2
p2被初始化为FFFFFFFE000000006FAFED9C3353F08D
4)计算中间值
代码:
Un_FSG__:0040169Bmoveax,[ebp+pt4]
Un_FSG__:004016A1addesp,1Ch
Un_FSG__:004016A4pusheax
Un_FSG__:004016A5moveax,[ebp+pt3]
Un_FSG__:004016ABpusheax
Un_FSG__:004016ACmoveax,[ebp+big_sn2]
Un_FSG__:004016B2pusheax
Un_FSG__:004016B3call_ecurve_mult;pt4=pt3*big_sn2
Un_FSG__:004016B8moveax,[ebp+big_hName]
Un_FSG__:004016BEaddesp,0Ch
Un_FSG__:004016C1pushedi
Un_FSG__:004016C2pushedi
Un_FSG__:004016C3pusheax
Un_FSG__:004016C4call_ecurve_mult;pt1=pt1*big_hName
Un_FSG__:004016C9movebx,[ebp+big_sn1]
Un_FSG__:004016CFaddesp,0Ch
Un_FSG__:004016D2movecx,[ebp+pt5]
Un_FSG__:004016D8movesi,[ebp+pt2]
Un_FSG__:004016DEpushecx
Un_FSG__:004016DFpushesi
Un_FSG__:004016E0pushebx
Un_FSG__:004016E1call_ecurve_mult;pt5=pt2*big_sn1
Un_FSG__:004016E6popeax
Un_FSG__:004016E7popedx
Un_FSG__:004016E8movedx,[ebp+pt5]
Un_FSG__:004016EEpushedx
Un_FSG__:004016EFpushedi
Un_FSG__:004016F0call_ecurve_add;pt5=pt5+pt1
Un_FSG__:004016F0;pt5=pt1*big_hName+
Un_FSG__:004016F0;pt2*big_sn1
pt4=pt3*big_sn2
pt5=pt5+pt1
=pt1*big_hName+pt2*big_sn1
5)比较
通过两处进行比较
代码:
Un_FSG__:004016F5moveax,[ebp+pt4]
Un_FSG__:004016FBpopecx
Un_FSG__:004016FCpopebx
Un_FSG__:004016FDpusheax
Un_FSG__:004016FEmoveax,[ebp+pt5]
Un_FSG__:00401704pusheax
Un_FSG__:00401705call_epoint_comp;pt4=t5
...
Un_FSG__:004017F5moveax,[ebp+pt5]
Un_FSG__:004017FBpushedi
Un_FSG__:004017FCpusheax
Un_FSG__:004017FDcall_epoint_comp;pt5!=pt1
如果pt4=pt5且pt5!=pt1则通过
3.Keygen
最终只要pt3*big_sn2=pt1*big_hName+pt2*big_sn1即可通过检查
其中pt3的x坐标为big_sn1%p
big_hName是name的hash值变形得来,是不可逆的,同样pt1,pt2是给定的也做不了文章,能下手的就是pt3,sn1,sn2这几部分
不妨试试,令pt3=pt1+pt2,big_sn2=big_hName
那么方程被简化为pt2*big_hName=pt2*big_sn1
椭圆曲线作为一个阶数为n的有限群,它上面任意一点满足pt*n=indefinite(因为元素的阶是群的阶的因子)。如果椭圆曲线不好理解,可以拿模质数的乘法群来类比。indefinite相当于1。在{1,2,3,4,5,6}这几个数构成的mod7群里,群的阶(元素个数)为6,任意一个数的6次方除以7均余1也就是那个单位元。
所以只要big_sn1%n=big_hName即可
那么最终我们得到了一组同余方程
big_sn1=pt3_xmodp
big_sn1=big_hNamemodn
得到sn1
利用big_sn2=big_hName
得到sn2
当时在keygen的时候我对miracl还不熟,我自己手工解这个同余方程,大家可以用miracl实现一个更好的keygen,因为传不了附件,下面是keygen的链接
keygen