邪恶八进制信息安全团队技术讨论组's Archiver

pub!1c 2006-2-3 19:28

[转载]著名足球游戏软件FIFA 2005安装序列号算法之分析

<P>文章作者:debug</P>
<P><FONT face=宋体>软件功能:想必喜欢玩游戏的坛友都知道该款软件吧。UnitedKingdom人开发的大名鼎鼎的足球游戏。我这不玩游戏的人都知道!<BR><BR>可惜我不喜欢游戏。<BR>工具:SoftIce,W32Dasm<BR>目的:分析安装序列号算法并获得序列号。<BR><BR>引子:今天一个埃塞俄比亚的当地县农业局官员拿着一个FIFA2005游戏光盘找我,告诉我玩不了这个游戏。原来他从印度买了这个<BR><BR>FIFA2005游戏DB盘,印度人没有给他安装序列号,程序一启动就要输入序列号的,否则不能进行。所以那位先生说软件不工作,他<BR><BR>根本安装不上去。他让我给他检查一下什么问题。结果给了我好几天了,忙于工作,今天突然想起来了,赶紧给他检查一下到底为<BR><BR>什么不工作。我一安装就跟我要序列号,我把光盘翻了个底朝天,也没有发现序列号的影子。看来需要自己解决啦!!幸亏最近2个<BR><BR>月学了点破解功夫,结果在我手下,这个软件迎刃而解!赶紧把其过程整理出来,跟大家分享成功的喜悦啦!!下面且听详细分解<BR><BR>。可能代码太长了,看起来比较费劲些,这里说声“抱歉”了!祝你苦尽甘来!!<BR><BR>过程分析:<BR>这个软件的序列号验证是通过运行在\surport目录下面的FIFA2005_code.exe来进行的,非常不好意思,这是我在成功分析完后<BR><BR>,在寻求是哪个文件验证序列号时才发现的。拿PEID检查,发现是VC写的程序,没有加壳,这对于获取代码写破文非常有利啊。否<BR><BR>则真是不知多么麻烦的U出代码来。运行这个程序,在里面输入假序列号,格式自然是1111-2222-3333-4444-5555.共计5段20位码<BR><BR>。调出SOFTICE,下断点bpxmessageboxa。(为什么用这个下断点呢?因为在点击next按钮时,弹出提示框“序列号错误”。我<BR><BR>曾实验了getwindowtexta,getdlgitem,都不好用。只有hmemcpy比较好用,但离核心比较远了。用这个消息框下断点也是总结出<BR><BR>来的经验啦。一开始我也不知道!)F5退出,点击NEXT按钮,被拦截。按1次F12就来到主程序空间了。然后F10跟踪到如下代码处<BR><BR>,开始艰苦的旅程吧!!:)<BR>一开始我们回到:00402AD9处,:00402AD4处就是出现错误窗口的函数,所以我们应该从前面看起,注册码肯定在前面部分产生的。<BR><BR>我们就来到下面代码处:<BR>0040299E.E8BD190000CALLFIFA_200.00404360<BR>004029A3.A028D54200MOVAL,BYTEPTRDS:[42D528]<BR>004029A8.84C0TESTAL,AL<BR>004029AA.C784241C05000>MOVDWORDPTRSS:[ESP+51C],0<BR>004029B5.747AJESHORTFIFA_200.00402A31//此处自然跳走。<BR>*省去多行*<BR>00402A31>8B8680000000MOVEAX,DWORDPTRDS:[ESI+80]<BR>00402A37.50PUSHEAX<BR>00402A38.8D4C2408LEAECX,DWORDPTRSS:[ESP+8]<BR>00402A3C.E8AF200000CALLFIFA_200.00404AF0//这个函数产生100个4字节数,后面计算序列号用到。<BR>00402A41.8B467CMOVEAX,DWORDPTRDS:[ESI+7C]<BR>00402A44.8B4E70MOVECX,DWORDPTRDS:[ESI+70]<BR>00402A47.50PUSHEAX<BR>00402A48.51PUSHECX<BR>00402A49.8D4C240CLEAECX,DWORDPTRSS:[ESP+C]<BR>00402A4D.E87E1A0000CALLFIFA_200.004044D0<BR>00402A52.8B8E0C010000MOVECX,DWORDPTRDS:[ESI+10C]<BR>00402A58.8B9608010000MOVEDX,DWORDPTRDS:[ESI+108]<BR>00402A5E.8B8604010000MOVEAX,DWORDPTRDS:[ESI+104]<BR>00402A64.51PUSHECX<BR>00402A65.8B8E00010000MOVECX,DWORDPTRDS:[ESI+100]<BR>00402A6B.52PUSHEDX<BR>00402A6C.8B96FC000000MOVEDX,DWORDPTRDS:[ESI+FC]<BR>00402A72.50PUSHEAX<BR>00402A73.51PUSHECX<BR>00402A74.52PUSHEDX<BR>00402A75.8D442420LEAEAX,DWORDPTRSS:[ESP+20]<BR>00402A79.6870074200PUSHFIFA_200.00420770<BR>00402A7E.50PUSHEAX<BR>00402A7F.E8C9430000CALLFIFA_200.00406E4D//计算序列号长度。<BR>00402A84.83C41CADDESP,1C<BR>00402A87.8D4C240CLEAECX,DWORDPTRSS:[ESP+C]//假序列号地址送ECX。<BR>00402A8B.51PUSHECX<BR>00402A8C.8D4C2408LEAECX,DWORDPTRSS:[ESP+8]<BR>00402A90.E88B200000CALLFIFA_200.00404B20//看看这个调用及下面判断结构,分析见后面。(1)<BR>00402A95.84C0TESTAL,AL<BR>00402A97.757CJNZSHORTFIFA_200.00402B15//如果序列号正确则跳走。否则看看下面00402AD4处即明<BR><BR>白OVER。<BR>00402A99.A11CD64200MOVEAX,DWORDPTRDS:[42D61C]<BR>00402A9E.8D94241001000>LEAEDX,DWORDPTRSS:[ESP+110]<BR>00402AA5.6800040000PUSH400<BR>00402AAA.83F802CMPEAX,2<BR>00402AAD.8B8684000000MOVEAX,DWORDPTRDS:[ESI+84]<BR>00402AB3.52PUSHEDX<BR>00402AB4.7D2BJGESHORTFIFA_200.00402AE1<BR>00402AB6.6A66PUSH66<BR>00402AB8.50PUSHEAX<BR>00402AB9.E892100000CALLFIFA_200.00403B50<BR>00402ABE.8B86F4000000MOVEAX,DWORDPTRDS:[ESI+F4]<BR>00402AC4.83C410ADDESP,10<BR>00402AC7.6A30PUSH30<BR>00402AC9.50PUSHEAX<BR>00402ACA.8D8C241801000>LEAECX,DWORDPTRSS:[ESP+118]<BR>00402AD1.51PUSHECX<BR>00402AD2.8BCEMOVECX,ESI<BR>00402AD4.E8D23F0100CALLFIFA_200.00416AAB//这个CALL出现错误提示框。<BR>*省略多行*<BR>00402B15>6A01PUSH1<BR>00402B17.8BCEMOVECX,ESI<BR>00402B19.E89A280100CALLFIFA_200.004153B8<BR>00402B1E.8B467CMOVEAX,DWORDPTRDS:[ESI+7C]<BR>00402B21.8B7670MOVESI,DWORDPTRDS:[ESI+70]<BR>00402B24.8D54240CLEAEDX,DWORDPTRSS:[ESP+C]<BR>00402B28.52PUSHEDX<BR>00402B29.50PUSHEAX<BR>00402B2A.56PUSHESI<BR>00402B2B.8D4C2410LEAECX,DWORDPTRSS:[ESP+10]<BR>00402B2F.E8FC180000CALLFIFA_200.00404430<BR>00402B34>8D4C2404LEAECX,DWORDPTRSS:[ESP+4]<BR>00402B38.C784241C05000>MOVDWORDPTRSS:[ESP+51C],-1<BR>00402B43.E828180000CALLFIFA_200.00404370<BR>00402B48.8B8C241405000>MOVECX,DWORDPTRSS:[ESP+514]<BR>00402B4F.64:890D000000>MOVDWORDPTRFS:[0],ECX<BR>00402B56.8B8C241005000>MOVECX,DWORDPTRSS:[ESP+510]//ECX=7E0FB3A7<BR>00402B5D.5EPOPESI<BR>00402B5E.E83B370000CALLFIFA_200.0040629E//判断ECX是否等于7E0FB3A7。<BR>00402B63.81C41C050000ADDESP,51C<BR>00402B69.C3RETN<BR>======================================================================<BR>下面分析00402A90CALLFIFA_200.00404B20代码:(1)<BR>00404B20/$8B4104MOVEAX,DWORDPTRDS:[ECX+4]<BR>00404B23|.8B4C2404MOVECX,DWORDPTRSS:[ESP+4]<BR>00404B27|.50PUSHEAX<BR>00404B28|.51PUSHECX<BR>00404B29|.E832FFFFFFCALLFIFA_200.00404A60//跟入这个函数。(2)<BR>00404B2E|.83C408ADDESP,8<BR>00404B31|.F7D8NEGEAX<BR>00404B33|.1BC0SBBEAX,EAX//带借位减EAX。<BR>00404B35|.F7D8NEGEAX//求补码。如果EAX=1,则补码依然为1。说明正确。<BR>00404B37\.C20400RETN4<BR>======================================================================<BR>下面分析00404B29CALLFIFA_200.00404A60:(2)<BR>00404A60/$83EC40SUBESP,40<BR>00404A63|.53PUSHEBX<BR>00404A64|.56PUSHESI<BR>00404A65|.57PUSHEDI<BR>00404A66|.8B7C2450MOVEDI,DWORDPTRSS:[ESP+50]//假序列号地址送EDI。<BR>00404A6A|.8D44240CLEAEAX,DWORDPTRSS:[ESP+C]<BR>00404A6E|.57PUSHEDI<BR>00404A6F|.50PUSHEAX<BR>00404A70|.E8CBFDFFFFCALLFIFA_200.00404840//这个函数复制假序列号到另一地址,然后按某规律交换<BR><BR>位置。(3)<BR>00404A75|.8B4C245CMOVECX,DWORDPTRSS:[ESP+5C]<BR>00404A79|.51PUSHECX<BR>00404A7A|.8D542418LEAEDX,DWORDPTRSS:[ESP+18]//复制并交换位置后的假序列号地址送EDX。<BR>00404A7E|.52PUSHEDX<BR>00404A7F|.8D44243CLEAEAX,DWORDPTRSS:[ESP+3C]<BR>00404A83|.50PUSHEAX<BR>00404A84|.C644242D00MOVBYTEPTRSS:[ESP+2D],0//把第14位置0。<BR>00404A89|.E862FEFFFFCALLFIFA_200.004048F0//这个函数重要,跟入看看,代码分析后面。(4)<BR>00404A8E|.83C414ADDESP,14<BR>00404A91|.8D74242CLEAESI,DWORDPTRSS:[ESP+2C]//正确序列号地址送ESI。<BR>00404A95|.8BC7MOVEAX,EDI//假序列号地址送EAX。<BR>00404A97|>8A10/MOVDL,BYTEPTRDS:[EAX]//假码依次送DL。<BR>00404A99|.8A1E|MOVBL,BYTEPTRDS:[ESI]//真码依次送BL。<BR>00404A9B|.8ACA|MOVCL,DL//假码也送CL。<BR>00404A9D|.3AD3|CMPDL,BL//真假对比。<BR>00404A9F|.752C|JNZSHORTFIFA_200.00404ACD//不相等则OVER。<BR>00404AA1|.84C9|TESTCL,CL//测试CL。<BR>00404AA3|.7416|JESHORTFIFA_200.00404ABB//为0则OVER。<BR>00404AA5|.8A5001|MOVDL,BYTEPTRDS:[EAX+1]//下位假码依次送DL。<BR>00404AA8|.8A5E01|MOVBL,BYTEPTRDS:[ESI+1]//下位真码依次送BL。<BR>00404AAB|.8ACA|MOVCL,DL<BR>00404AAD|.3AD3|CMPDL,BL//真假对比。<BR>00404AAF|.751C|JNZSHORTFIFA_200.00404ACD//不相等则OVER。<BR>00404AB1|.83C002|ADDEAX,2<BR>00404AB4|.83C602|ADDESI,2<BR>00404AB7|.84C9|TESTCL,CL<BR>00404AB9|.^75DC\JNZSHORTFIFA_200.00404A97//没有比较完则继续。<BR>00404ABB|>33C0XOREAX,EAX//EAX清0。<BR>00404ABD|.33C9XORECX,ECX//ECX清0。<BR>00404ABF|.85C0TESTEAX,EAX//测试EAX。<BR>00404AC1|.0F94C1SETECL//如果EAX为0。则置CL为1。此为序列号正确标志。<BR>00404AC4|.5FPOPEDI<BR>00404AC5|.5EPOPESI<BR>00404AC6|.5BPOPEBX<BR>00404AC7|.8BC1MOVEAX,ECX//送入EAX返回正确标志到主调函数。<BR>00404AC9|.83C440ADDESP,40<BR>00404ACC|.C3RETN<BR>00404ACD|>1BC0SBBEAX,EAX//如果前面比较错误,则跳到这里,然后没戏了。<BR>00404ACF|.83D8FFSBBEAX,-1<BR>00404AD2|.33C9XORECX,ECX<BR>00404AD4|.85C0TESTEAX,EAX<BR>00404AD6|.0F94C1SETECL<BR>00404AD9|.5FPOPEDI<BR>00404ADA|.5EPOPESI<BR>00404ADB|.5BPOPEBX<BR>00404ADC|.8BC1MOVEAX,ECX<BR>00404ADE|.83C440ADDESP,40<BR>00404AE1\.C3RETN<BR>======================================================================<BR>下面分析00404A70CALLFIFA_200.00404840函数功能,代码如下:(3)<BR>00404840/$8B442404MOVEAX,DWORDPTRSS:[ESP+4]<BR>00404844|.8B4C2408MOVECX,DWORDPTRSS:[ESP+8]<BR>00404848|.53PUSHEBX<BR>00404849|.56PUSHESI<BR>0040484A|.8BF0MOVESI,EAX<BR>0040484C|.2BF1SUBESI,ECX<BR>0040484E|.8BFFMOVEDI,EDI<BR>00404850|>8A11/MOVDL,BYTEPTRDS:[ECX]//下面这个循环拷贝假序列号到新位置。<BR>00404852|.88140E|MOVBYTEPTRDS:[ESI+ECX],DL<BR>00404855|.41|INCECX<BR>00404856|.84D2|TESTDL,DL<BR>00404858|.^75F6\JNZSHORTFIFA_200.00404850<BR>0040485A|.0FBE0DD8BC420>MOVSXECX,BYTEPTRDS:[42BCD8]<BR>00404861|.8A1401MOVDL,BYTEPTRDS:[ECX+EAX]//第3位送DL。<BR>00404864|.8A580DMOVBL,BYTEPTRDS:[EAX+D]//第14位送BL。<BR>00404867|.881C01MOVBYTEPTRDS:[ECX+EAX],BL//BL送第3位。<BR>0040486A|.8A580EMOVBL,BYTEPTRDS:[EAX+E]//第15位送BL。<BR>0040486D|.88500DMOVBYTEPTRDS:[EAX+D],DL//DL送第14位。<BR>00404870|.0FBE15D9BC420>MOVSXEDX,BYTEPTRDS:[42BCD9]<BR>00404877|.03C8ADDECX,EAX<BR>00404879|.8D0C02LEAECX,DWORDPTRDS:[EDX+EAX]<BR>0040487C|.8A11MOVDL,BYTEPTRDS:[ECX]//第5位送DL。<BR>0040487E|.8819MOVBYTEPTRDS:[ECX],BL//BL送第5位。<BR>00404880|.8A580FMOVBL,BYTEPTRDS:[EAX+F]//第16位送BL。<BR>00404883|.88500EMOVBYTEPTRDS:[EAX+E],DL//DL送第15位。<BR>00404886|.0FBE0DDABC420>MOVSXECX,BYTEPTRDS:[42BCDA]<BR>0040488D|.8A1401MOVDL,BYTEPTRDS:[ECX+EAX]//第6位送DL。<BR>00404890|.881C01MOVBYTEPTRDS:[ECX+EAX],BL//BL送第6位。<BR>00404893|.8A5810MOVBL,BYTEPTRDS:[EAX+10]//第17位送BL。<BR>00404896|.88500FMOVBYTEPTRDS:[EAX+F],DL//DL送第16位。<BR>00404899|.0FBE15DBBC420>MOVSXEDX,BYTEPTRDS:[42BCDB]<BR>004048A0|.03C8ADDECX,EAX<BR>004048A2|.8D0C02LEAECX,DWORDPTRDS:[EDX+EAX]<BR>004048A5|.8A11MOVDL,BYTEPTRDS:[ECX]//第8位送DL。<BR>004048A7|.8819MOVBYTEPTRDS:[ECX],BL//BL送第8位。<BR>004048A9|.8A5811MOVBL,BYTEPTRDS:[EAX+11]//第18位送BL。<BR>004048AC|.885010MOVBYTEPTRDS:[EAX+10],DL//DL送第17位。<BR>004048AF|.0FBE0DDCBC420>MOVSXECX,BYTEPTRDS:[42BCDC]<BR>004048B6|.8A1401MOVDL,BYTEPTRDS:[ECX+EAX]//第13位送DL。<BR>004048B9|.881C01MOVBYTEPTRDS:[ECX+EAX],BL//BL送第13位。<BR>004048BC|.8A5812MOVBL,BYTEPTRDS:[EAX+12]//第19位送BL。<BR>004048BF|.03C8ADDECX,EAX<BR>004048C1|.885011MOVBYTEPTRDS:[EAX+11],DL//DL送第18位。<BR>004048C4|.0FBE15DDBC420>MOVSXEDX,BYTEPTRDS:[42BCDD]<BR>004048CB|.8D0C02LEAECX,DWORDPTRDS:[EDX+EAX]<BR>004048CE|.8A11MOVDL,BYTEPTRDS:[ECX]//第2位送DL。<BR>004048D0|.8819MOVBYTEPTRDS:[ECX],BL//BL送第2位。<BR>004048D2|.8A5813MOVBL,BYTEPTRDS:[EAX+13]//第20位送BL。<BR>004048D5|.885012MOVBYTEPTRDS:[EAX+12],DL//DL送第19位。<BR>004048D8|.0FBE0DDEBC420>MOVSXECX,BYTEPTRDS:[42BCDE]<BR>004048DF|.8A1401MOVDL,BYTEPTRDS:[ECX+EAX]//第4位送DL。<BR>004048E2|.03C8ADDECX,EAX<BR>004048E4|.8819MOVBYTEPTRDS:[ECX],BL//BL送第4位。<BR>004048E6|.5EPOPESI<BR>004048E7|.885013MOVBYTEPTRDS:[EAX+13],DL//DL送第20位。<BR>004048EA|.C6401400MOVBYTEPTRDS:[EAX+14],0<BR>004048EE|.5BPOPEBX<BR>004048EF\.C3RETN<BR>第一次由404A70处调用此函数把序列号从11112222333344445555变为15454425333351222411.后7位舍弃。记为<BR><BR>S0=1545442533335.<BR>第二次由4049F4处调用此函数,把序列号从1545442533335XQM5BEX变为1EXXQM253333B4445555。<BR>======================================================================<BR>下面分析00404A89CALLFIFA_200.004048F0代码,这个才是最最关键的地方(4):<BR>004048F0/$83EC40SUBESP,40<BR>004048F3|.53PUSHEBX<BR>004048F4|.55PUSHEBP<BR>004048F5|.56PUSHESI<BR>004048F6|.8B742454MOVESI,DWORDPTRSS:[ESP+54]//变换后的新串地址送ESI。<BR>004048FA|.57PUSHEDI//旧串地址在EDI。<BR>004048FB|.6A0DPUSH0D<BR>004048FD|.56PUSHESI<BR>004048FE|.E8EDFCFFFFCALLFIFA_200.004045F0//这个函数根据新串得到一个数值。(5)<BR>00404903|.8B5C2464MOVEBX,DWORDPTRSS:[ESP+64]//EBX=常数1D631。<BR>00404907|.33C3XOREAX,EBX//返回的EAX与EBX异或运算。<BR>00404909|.50PUSHEAX<BR>0040490A|.8D44243CLEAEAX,DWORDPTRSS:[ESP+3C]<BR>0040490E|.50PUSHEAX<BR>0040490F|.E8ACFDFFFFCALLFIFA_200.004046C0//这个函数获得一个7位子串,记S1,(6)<BR>00404914|.8D6C2420LEAEBP,DWORDPTRSS:[ESP+20]<BR>00404918|.83C410ADDESP,10<BR>0040491B|.8BC6MOVEAX,ESI<BR>0040491D|.2BEESUBEBP,ESI<BR>0040491F|.90NOP<BR>00404920|>8A08/MOVCL,BYTEPTRDS:[EAX]//变换后的假序列号依次送CL。<BR>00404922|.880C28|MOVBYTEPTRDS:[EAX+EBP],CL//保存CL到新地址。<BR>00404925|.40|INCEAX<BR>00404926|.84C9|TESTCL,CL<BR>00404928|.^75F6\JNZSHORTFIFA_200.00404920//循环。<BR>0040492A|.8D442430LEAEAX,DWORDPTRSS:[ESP+30]//由(6)计算得到的S1字符串地址送EAX。<BR>0040492E|.8BF0MOVESI,EAX<BR>00404930|>8A08/MOVCL,BYTEPTRDS:[EAX]//下面循环测试7位字符。<BR>00404932|.40|INCEAX<BR>00404933|.84C9|TESTCL,CL<BR>00404935|.^75F9\JNZSHORTFIFA_200.00404930<BR>00404937|.8D7C2410LEAEDI,DWORDPTRSS:[ESP+10]//假码串地址送EDI。<BR>0040493B|.2BC6SUBEAX,ESI<BR>0040493D|.4FDECEDI<BR>0040493E|.8BFFMOVEDI,EDI<BR>00404940|>8A4F01/MOVCL,BYTEPTRDS:[EDI+1]//下面循环依次测试假码串,得到最后一位假码地址。<BR>00404943|.47|INCEDI<BR>00404944|.84C9|TESTCL,CL<BR>00404946|.^75F8\JNZSHORTFIFA_200.00404940<BR>00404948|.8BC8MOVECX,EAX<BR>0040494A|.C1E902SHRECX,2<BR>0040494D|.F3:A5REPMOVSDWORDPTRES:[EDI],DWORDPTRDS:[ESI]//拷贝上述7位字符到假码后面,形成<BR><BR>20位码。<BR>0040494F|.8BC8MOVECX,EAX<BR>00404951|.83E103ANDECX,3<BR>00404954|.F3:A4REPMOVSBYTEPTRES:[EDI],BYTEPTRDS:[ESI]<BR>00404956|.8BC3MOVEAX,EBX//EAX=1D631h。后面用到。<BR>00404958|.33C9XORECX,ECX<BR>0040495A|.8D9B00000000LEAEBX,DWORDPTRDS:[EBX]<BR>00404960|>33D2/XOREDX,EDX//循环开始。<BR>00404962|.8A540C10|MOVDL,BYTEPTRSS:[ESP+ECX+10]//构造的新码串的各位依次送DL。<BR>00404966|.83C105|ADDECX,5//ECX循环步长增5。<BR>00404969|.33D0|XOREDX,EAX//EDX与EAX异或运算。<BR>0040496B|.81E2FF000000|ANDEDX,0FF//取最低字节。<BR>00404971|.8B1C9588DA420>|MOVEBX,DWORDPTRDS:[EDX*4+42DA88]//查表取值送EBX。<BR>00404978|.33D2|XOREDX,EDX//EDX清0。<BR>0040497A|.8A540C0C|MOVDL,BYTEPTRSS:[ESP+ECX+C]//下一位码串字符送DL。<BR>0040497E|.C1E808|SHREAX,8//EAX右移8次。<BR>00404981|.33C3|XOREAX,EBX//EAX异或EBX。<BR>00404983|.33D0|XOREDX,EAX//EDX异或EAX。<BR>00404985|.81E2FF000000|ANDEDX,0FF//取最低字节。<BR>0040498B|.8B3C9588DA420>|MOVEDI,DWORDPTRDS:[EDX*4+42DA88]//查表取值送EDI。<BR>00404992|.33D2|XOREDX,EDX//EDX清0。<BR>00404994|.8A540C0D|MOVDL,BYTEPTRSS:[ESP+ECX+D]//下一位码串字符送DL。<BR>00404998|.C1E808|SHREAX,8//EAX右移8次。<BR>0040499B|.33C7|XOREAX,EDI//EAX异或EDI。<BR>0040499D|.33D0|XOREDX,EAX//EDX异或EAX。<BR>0040499F|.81E2FF000000|ANDEDX,0FF//取最低字节。<BR>004049A5|.8B349588DA420>|MOVESI,DWORDPTRDS:[EDX*4+42DA88]//查表取值送EDI。<BR>004049AC|.33D2|XOREDX,EDX//EDX清0。<BR>004049AE|.8A540C0E|MOVDL,BYTEPTRSS:[ESP+ECX+E]//下一位码串字符送DL。<BR>004049B2|.C1E808|SHREAX,8//EAX右移8次。<BR>004049B5|.33C6|XOREAX,ESI//EAX异或ESI。<BR>004049B7|.33D0|XOREDX,EAX//EDX异或EAX。<BR>004049B9|.81E2FF000000|ANDEDX,0FF//取最低字节。<BR>004049BF|.8B1C9588DA420>|MOVEBX,DWORDPTRDS:[EDX*4+42DA88]//查表取值送EDI。<BR>004049C6|.33D2|XOREDX,EDX//EDX清0。<BR>004049C8|.8A540C0F|MOVDL,BYTEPTRSS:[ESP+ECX+F]//下一位码串字符送DL。<BR>004049CC|.C1E808|SHREAX,8//EAX右移8次。<BR>004049CF|.33C3|XOREAX,EBX//EAX异或EBX。<BR>004049D1|.33D0|XOREDX,EAX//EDX异或EAX。<BR>004049D3|.81E2FF000000|ANDEDX,0FF//取最低字节。<BR>004049D9|.8B3C9588DA420>|MOVEDI,DWORDPTRDS:[EDX*4+42DA88]//查表取值送EDI。<BR>004049E0|.C1E808|SHREAX,8//EAX右移8次。<BR>004049E3|.33C7|XOREAX,EDI//EAX异或EDI。<BR>004049E5|.83F914|CMPECX,14//比较循环次数。<BR>004049E8|.^0F8C72FFFFFF\JLFIFA_200.00404960//未完则继续循环,总共循环4次。<BR>004049EE|.50PUSHEAX//刚才循环结束得到的EAX进栈。<BR>004049EF|.8D442434LEAEAX,DWORDPTRSS:[ESP+34]//S1串的地址送EAX。<BR>004049F3|.50PUSHEAX<BR>004049F4|.E887FDFFFFCALLFIFA_200.00404780//该函数根据前面结果再次构造一个新串S2,(7)<BR>004049F9|.8B442460MOVEAX,DWORDPTRSS:[ESP+60]//EAX为新码串地址。<BR>004049FD|.83C408ADDESP,8<BR>00404A00|>8A08/MOVCL,BYTEPTRDS:[EAX]//循环复制到另一位置。<BR>00404A02|.880C28|MOVBYTEPTRDS:[EAX+EBP],CL<BR>00404A05|.40|INCEAX<BR>00404A06|.84C9|TESTCL,CL<BR>00404A08|.^75F6\JNZSHORTFIFA_200.00404A00<BR>00404A0A|.8D442430LEAEAX,DWORDPTRSS:[ESP+30]//取串S2的地址送EAX。<BR>00404A0E|.8BD0MOVEDX,EAX<BR>00404A10|>8A08/MOVCL,BYTEPTRDS:[EAX]//这个循环测试S2串,得最后一位地址。<BR>00404A12|.40|INCEAX<BR>00404A13|.84C9|TESTCL,CL<BR>00404A15|.^75F9\JNZSHORTFIFA_200.00404A10<BR>00404A17|.8D7C2410LEAEDI,DWORDPTRSS:[ESP+10]//新码串地址送EDI。<BR>00404A1B|.2BC2SUBEAX,EDX//获取S2串长。<BR>00404A1D|.4FDECEDI<BR>00404A1E|.8BFFMOVEDI,EDI<BR>00404A20|>8A4F01/MOVCL,BYTEPTRDS:[EDI+1]//下面循环结果为码串S0的第13位的地址。<BR>00404A23|.47|INCEDI<BR>00404A24|.84C9|TESTCL,CL<BR>00404A26|.^75F8\JNZSHORTFIFA_200.00404A20<BR>00404A28|.8BC8MOVECX,EAX<BR>00404A2A|.C1E902SHRECX,2<BR>00404A2D|.8BF2MOVESI,EDX<BR>00404A2F|.8B542454MOVEDX,DWORDPTRSS:[ESP+54]<BR>00404A33|.F3:A5REPMOVSDWORDPTRES:[EDI],DWORDPTRDS:[ESI]//复制新串S2到码串S0的后面。即<BR><BR>1545442533335XQM5BEX。<BR>00404A35|.8BC8MOVECX,EAX<BR>00404A37|.83E103ANDECX,3<BR>00404A3A|.F3:A4REPMOVSBYTEPTRES:[EDI],BYTEPTRDS:[ESI]<BR>00404A3C|.8D4C2410LEAECX,DWORDPTRSS:[ESP+10]//拼接后的新串地址送ECX。<BR>00404A40|.51PUSHECX<BR>00404A41|.52PUSHEDX<BR>00404A42|.E8F9FDFFFFCALLFIFA_200.00404840//这个函数对码串重新排序,得到真正序列号了。(3)<BR>00404A47|.83C408ADDESP,8<BR>00404A4A|.5FPOPEDI<BR>00404A4B|.5EPOPESI<BR>00404A4C|.5DPOPEBP<BR>00404A4D|.5BPOPEBX<BR>00404A4E|.83C440ADDESP,40<BR>00404A51\.C3RETN<BR>======================================================================<BR>下面分析004048FECALLFIFA_200.004045F0代码,(5):<BR>004045F0/$53PUSHEBX<BR>004045F1|.8B5C240CMOVEBX,DWORDPTRSS:[ESP+C]//循环次数送EBX。EBX=D。<BR>004045F5|.56PUSHESI<BR>004045F6|.57PUSHEDI<BR>004045F7|.33FFXOREDI,EDI<BR>004045F9|.33F6XORESI,ESI<BR>004045FB|.85DBTESTEBX,EBX<BR>004045FD|.B901000000MOVECX,1//ECX初始化为1。后面循环用到。<BR>00404602|.7E31JLESHORTFIFA_200.00404635<BR>00404604|.55PUSHEBP<BR>00404605|.8B6C2414MOVEBP,DWORDPTRSS:[ESP+14]<BR>00404609|.8DA4240000000>LEAESP,DWORDPTRSS:[ESP]<BR>00404610|>0FBE042E/MOVSXEAX,BYTEPTRDS:[ESI+EBP]//新串字符依次送EAX。<BR>00404614|.03C1|ADDEAX,ECX//EAX=EAX+ECX。<BR>00404616|.33D2|XOREDX,EDX<BR>00404618|.B9F1FF0000|MOVECX,0FFF1//EAX=FFF1。<BR>0040461D|.F7F1|DIVECX//EAX除以ECX,余数送EDX。<BR>0040461F|.8BCA|MOVECX,EDX//余数EDX送ECX。<BR>00404621|.8D040F|LEAEAX,DWORDPTRDS:[EDI+ECX]//EAX=EDI+ECX。<BR>00404624|.33D2|XOREDX,EDX<BR>00404626|.BFF1FF0000|MOVEDI,0FFF1//EDI=FFF1。<BR>0040462B|.F7F7|DIVEDI//EAX除以EDI。余数送EDX。<BR>0040462D|.46|INCESI<BR>0040462E|.3BF3|CMPESI,EBX//比较是否到了次数D。<BR>00404630|.8BFA|MOVEDI,EDX//余数送EDI。<BR>00404632|.^7CDC\JLSHORTFIFA_200.00404610//未完则继续。<BR>00404634|.5DPOPEBP<BR>00404635|>8BC7MOVEAX,EDI//计算结果送EAX。<BR>00404637|.5FPOPEDI<BR>00404638|.C1E010SHLEAX,10//EAX左移10h位。<BR>0040463B|.5EPOPESI<BR>0040463C|.03C1ADDEAX,ECX//EAX=EAX+ECX。<BR>0040463E|.5BPOPEBX<BR>0040463F\.C3RETN<BR>======================================================================<BR>下面分析0040490FCALLFIFA_200.004046C0的代码。这个地方关键!!(6)<BR>004046C0/$8B442404MOVEAX,DWORDPTRSS:[ESP+4]//目标地址送EAX。<BR>004046C4|.8B4C2408MOVECX,DWORDPTRSS:[ESP+8]//ECX=前面004048FE处函数计算的结果。<BR>004046C8|.8AD1MOVDL,CL//CL送DL。<BR>004046CA|.80E21FANDDL,1F//DL与1F做“与运算”<BR>004046CD|.885006MOVBYTEPTRDS:[EAX+6],DL//保存结果。<BR>004046D0|.8BD1MOVEDX,ECX//ECX送EDX。<BR>004046D2|.C1EA05SHREDX,5//右移5次。<BR>004046D5|.80E21FANDDL,1F//DL与1F做“与运算”<BR>004046D8|.885005MOVBYTEPTRDS:[EAX+5],DL//保存结果。<BR>004046DB|.8BD1MOVEDX,ECX//ECX送EDX。<BR>004046DD|.C1EA0ASHREDX,0A//右移A次。<BR>004046E0|.80E21FANDDL,1F//DL与1F做“与运算”<BR>004046E3|.885004MOVBYTEPTRDS:[EAX+4],DL//保存结果。<BR>004046E6|.8BD1MOVEDX,ECX//ECX送EDX。<BR>004046E8|.C1EA0FSHREDX,0F//右移F次。<BR>004046EB|.80E21FANDDL,1F//DL与1F做“与运算”<BR>004046EE|.885003MOVBYTEPTRDS:[EAX+3],DL//保存结果。<BR>004046F1|.8BD1MOVEDX,ECX//ECX送EDX。<BR>004046F3|.C1EA14SHREDX,14//右移14h次。<BR>004046F6|.80E21FANDDL,1F//DL与1F做“与运算”<BR>004046F9|.885002MOVBYTEPTRDS:[EAX+2],DL//保存结果。<BR>004046FC|.8BD1MOVEDX,ECX//ECX送EDX。<BR>004046FE|.C1E91ESHRECX,1E//ECX右移1Eh次。<BR>00404701|.C1EA19SHREDX,19//EDX右移19h次。<BR>00404704|.80E11FANDCL,1F//DL与1F做“与运算”<BR>00404707|.8808MOVBYTEPTRDS:[EAX],CL//保存结果。<BR>00404709|.80E21FANDDL,1F//DL与1F做“与运算”<BR>0040470C|.885001MOVBYTEPTRDS:[EAX+1],DL//保存结果。<BR>0040470F|.8A4806MOVCL,BYTEPTRDS:[EAX+6]//取出第6位送CL。<BR>00404712|.8A10MOVDL,BYTEPTRDS:[EAX]//取出第0位送DL。<BR>00404714|.80E107ANDCL,7//与7相与。<BR>00404717|.C0E102SHLCL,2//左移2位。<BR>0040471A|.0AD1ORDL,CL//DL与CL或运算。<BR>0040471C|.8810MOVBYTEPTRDS:[EAX],DL//保存结果。<BR>0040471E|.0FBED2MOVSXEDX,DL//把DL送EDX。<BR>00404721|.8A8AB8BC4200MOVCL,BYTEPTRDS:[EDX+42BCB8]//查表得一数送CL。<BR>00404727|.0FBE5001MOVSXEDX,BYTEPTRDS:[EAX+1]//把第1位送EDX。<BR>0040472B|.8808MOVBYTEPTRDS:[EAX],CL//保存前面查表结果。<BR>0040472D|.8A8AB8BC4200MOVCL,BYTEPTRDS:[EDX+42BCB8]//查表得一数送CL。<BR>00404733|.0FBE5002MOVSXEDX,BYTEPTRDS:[EAX+2]//把第2位送EDX。<BR>00404737|.884801MOVBYTEPTRDS:[EAX+1],CL//保存前面查表结果。<BR>0040473A|.8A8AB8BC4200MOVCL,BYTEPTRDS:[EDX+42BCB8]//查表得一数送CL。<BR>00404740|.0FBE5003MOVSXEDX,BYTEPTRDS:[EAX+3]//把第3位送EDX。<BR>00404744|.884802MOVBYTEPTRDS:[EAX+2],CL//保存前面查表结果。<BR>00404747|.8A8AB8BC4200MOVCL,BYTEPTRDS:[EDX+42BCB8]//查表得一数送CL。<BR>0040474D|.0FBE5004MOVSXEDX,BYTEPTRDS:[EAX+4]//把第4位送EDX。<BR>00404751|.884803MOVBYTEPTRDS:[EAX+3],CL//保存前面查表结果。<BR>00404754|.8A8AB8BC4200MOVCL,BYTEPTRDS:[EDX+42BCB8]//查表得一数送CL。<BR>0040475A|.0FBE5005MOVSXEDX,BYTEPTRDS:[EAX+5]//把第5位送EDX。<BR>0040475E|.884804MOVBYTEPTRDS:[EAX+4],CL//保存前面查表结果。<BR>00404761|.8A8AB8BC4200MOVCL,BYTEPTRDS:[EDX+42BCB8]//查表得一数送CL。<BR>00404767|.0FBE5006MOVSXEDX,BYTEPTRDS:[EAX+6]//把第6位送EDX。<BR>0040476B|.884805MOVBYTEPTRDS:[EAX+5],CL//保存前面查表结果。<BR>0040476E|.8A8AB8BC4200MOVCL,BYTEPTRDS:[EDX+42BCB8]//查表得一数送CL。<BR>00404774|.884806MOVBYTEPTRDS:[EAX+6],CL//保存前面查表结果。<BR>00404777|.C6400700MOVBYTEPTRDS:[EAX+7],0//最后一位置0。<BR>0040477B\.C3RETN<BR>该函数做完上述工作,得到一个7位的字符串。记为S1=2K59X2T。<BR>======================================================================<BR>下面是004049F4CALLFIFA_200.00404780代码,跟上面这部分类似。(7)<BR>00404780/$8B442404MOVEAX,DWORDPTRSS:[ESP+4]//S1串地址送EAX。<BR>00404784|.8B4C2408MOVECX,DWORDPTRSS:[ESP+8]//4049EE处的结果送ECX。<BR>00404788|.8AD1MOVDL,CL<BR>0040478A|.80E203ANDDL,3<BR>0040478D|.C0E203SHLDL,3<BR>00404790|.885006MOVBYTEPTRDS:[EAX+6],DL//下面总共计算出7个DL值依次覆盖原来数值。<BR>00404793|.C1E902SHRECX,2<BR>00404796|.8AD1MOVDL,CL<BR>00404798|.80E21FANDDL,1F<BR>0040479B|.885005MOVBYTEPTRDS:[EAX+5],DL<BR>0040479E|.8BD1MOVEDX,ECX<BR>004047A0|.C1EA05SHREDX,5<BR>004047A3|.80E21FANDDL,1F<BR>004047A6|.885004MOVBYTEPTRDS:[EAX+4],DL<BR>004047A9|.8BD1MOVEDX,ECX<BR>004047AB|.C1EA0ASHREDX,0A<BR>004047AE|.80E21FANDDL,1F<BR>004047B1|.885003MOVBYTEPTRDS:[EAX+3],DL<BR>004047B4|.8BD1MOVEDX,ECX<BR>004047B6|.C1EA0FSHREDX,0F<BR>004047B9|.80E21FANDDL,1F<BR>004047BC|.885002MOVBYTEPTRDS:[EAX+2],DL<BR>004047BF|.8BD1MOVEDX,ECX<BR>004047C1|.C1EA14SHREDX,14<BR>004047C4|.C1E919SHRECX,19<BR>004047C7|.80E21FANDDL,1F<BR>004047CA|.885001MOVBYTEPTRDS:[EAX+1],DL<BR>004047CD|.80E11FANDCL,1F<BR>004047D0|.8808MOVBYTEPTRDS:[EAX],CL<BR>004047D2|.8A5006MOVDL,BYTEPTRDS:[EAX+6]<BR>004047D5|.80E107ANDCL,7<BR>004047D8|.0AD1ORDL,CL<BR>004047DA|.885006MOVBYTEPTRDS:[EAX+6],DL<BR>004047DD|.0FBE10MOVSXEDX,BYTEPTRDS:[EAX]//下面代码依次取出上面刚刚得到的7位数值送EDX。<BR>004047E0|.8A8A98BC4200MOVCL,BYTEPTRDS:[EDX+42BC98]//用EDX作为地址偏移查表,结果送CL。<BR>004047E6|.0FBE5001MOVSXEDX,BYTEPTRDS:[EAX+1]<BR>004047EA|.8808MOVBYTEPTRDS:[EAX],CL//保存CL。<BR>004047EC|.8A8A98BC4200MOVCL,BYTEPTRDS:[EDX+42BC98]<BR>004047F2|.0FBE5002MOVSXEDX,BYTEPTRDS:[EAX+2]<BR>004047F6|.884801MOVBYTEPTRDS:[EAX+1],CL<BR>004047F9|.8A8A98BC4200MOVCL,BYTEPTRDS:[EDX+42BC98]<BR>004047FF|.0FBE5003MOVSXEDX,BYTEPTRDS:[EAX+3]<BR>00404803|.884802MOVBYTEPTRDS:[EAX+2],CL<BR>00404806|.8A8A98BC4200MOVCL,BYTEPTRDS:[EDX+42BC98]<BR>0040480C|.0FBE5004MOVSXEDX,BYTEPTRDS:[EAX+4]<BR>00404810|.884803MOVBYTEPTRDS:[EAX+3],CL<BR>00404813|.8A8A98BC4200MOVCL,BYTEPTRDS:[EDX+42BC98]<BR>00404819|.0FBE5005MOVSXEDX,BYTEPTRDS:[EAX+5]<BR>0040481D|.884804MOVBYTEPTRDS:[EAX+4],CL<BR>00404820|.8A8A98BC4200MOVCL,BYTEPTRDS:[EDX+42BC98]<BR>00404826|.0FBE5006MOVSXEDX,BYTEPTRDS:[EAX+6]<BR>0040482A|.884805MOVBYTEPTRDS:[EAX+5],CL<BR>0040482D|.8A8A98BC4200MOVCL,BYTEPTRDS:[EDX+42BC98]<BR>00404833|.884806MOVBYTEPTRDS:[EAX+6],CL<BR>00404836|.C6400700MOVBYTEPTRDS:[EAX+7],0<BR>0040483A\.C3RETN<BR>这个函数根据参数得到一个7位的新串,记为S2=XQM5BEX。<BR>======================================================================<BR>后记:经过1个小时的艰苦追踪,写了3页A4跟踪笔记,终于搞定这个序列号计算方法了,然后用了2个小时才把追踪笔记整理出来,<BR><BR>因为代码太长了,所以耽误不少时间。最后总算得到了结果,我真是高兴极了!立即写出这篇破文跟你分享我的快乐和成功!!我<BR><BR>猜你看完这篇破文,大概也哈欠连天了吧!!!我现在可是哈欠连天的啦!!没有想到这个FIFA开发者搞的注册码这么麻烦,但是<BR><BR>他发行的软件没有加壳,给我们获取代码带来了极大方便。否则,这么长的代码怎么搞出来呀???希望对菜鸟能够起点启发作用<BR><BR>!著名软件不见得就保护的很到位。如果保护的太厉害了,我也就没有这篇破文跟大家分享了!!感谢这位不列颠王国的FIFA2005<BR><BR>软件的开发者!!<BR><BR>另外,特别感谢“看雪”斑竹给予的特别关照,使我能够充满激情和动力地去写更好的破文奉献给各位!!!另外,还要感谢各位<BR><BR>大侠的热情支持和技术指导!!向关注我的破文的各位坛友表示衷心感谢!!祝我们看雪论坛人才辈出,日益红火!!!<BR><BR>结论:序列号:1EXX-QM25-3333-B444-5555<BR><BR><BR><BR></FONT></P>

页: [1]
© 1999-2008 EvilOctal Security Team