【使用工具】: OD、Atlantis Word Processor --------------------------------------------------------- Atlantis Word Processor 一個獨(dú)立的word處理器,支持讀取并編輯*.rtf *.doc *.docx *.cod *.txt等數(shù)種格式的文檔,支持命令行,軟件小巧界面清爽,占用內(nèi)存小,處理速度快,打開保存文件時支持全word格式的預(yù)覽。(兩個小小遺憾--word文檔中的中文引號會顯示亂碼;竟不支持中文txt文件,汗。期待更新) 試運(yùn)行得知軟件以用戶名、注冊碼方式保護(hù)(其實(shí)用戶名不參與運(yùn)算),有出錯提示,UPX弱殼。 脫殼OD加載后,查找字符串“invalid”找到以下關(guān)鍵部位,以用戶名playboysen,注冊碼HelloHenu試煉(算法分析一般都是隨便輸入假碼后粗略跟蹤幾次注冊碼的驗(yàn)證流程,根據(jù)驗(yàn)證流程一次次地修正假碼,最終得出一組可用注冊碼,弄清算法) 00495FC7 E8 9CC31600 call Atlantis.00602368 00495FCC 837D FC 00 cmp dword ptr ss:[ebp-4],0 00495FD0 75 17 jnz short Atlantis.00495FE9 00495FD2 B8 88604900 mov eax,Atlantis.00496088 ; ASCII "Please enter your registration code." 00495FD7 E8 28E31400 call Atlantis.005E4304 00495FDC 8B86 9C010000 mov eax,dword ptr ds:[esi+19C] 00495FE2 8B10 mov edx,dword ptr ds:[eax] 00495FE4 FF52 68 call dword ptr ds:[edx+68] 00495FE7 EB 45 jmp short Atlantis.0049602E 00495FE9 8D55 FC lea edx,dword ptr ss:[ebp-4] 00495FEC 8B86 9C010000 mov eax,dword ptr ds:[esi+19C] 00495FF2 E8 71C31600 call Atlantis.00602368 ; 算出注冊碼長度 00495FF7 8B45 FC mov eax,dword ptr ss:[ebp-4] ; 假碼放入eax 00495FFA E8 0D060000 call Atlantis.0049660C ; 關(guān)鍵處,跟進(jìn) 00495FFF 84C0 test al,al 00496001 75 17 jnz short Atlantis.0049601A 00496003 B8 B8604900 mov eax,Atlantis.004960B8 ; ASCII "The registration code you have specified is invalid..." 跟進(jìn)00495FFA關(guān)鍵call ...... 00496640 8B45 FC mov eax,dword ptr ss:[ebp-4] 00496643 E8 4C5AF7FF call Atlantis.0040C094 ; 注冊碼第一次變形,把假碼中的小寫字母轉(zhuǎn)換成大寫 00496648 8B45 F0 mov eax,dword ptr ss:[ebp-10] ; 轉(zhuǎn)換后的假碼放入 0049664B B1 30 mov cl,30 ; 數(shù)字“0” 0049664D B2 4F mov dl,4F ; 大寫字母“O” 0049664F E8 CC711400 call Atlantis.005DD820 ; 看上面入棧的參數(shù),猜測這個函數(shù)里面有貓膩兒 00496654 8B55 F4 mov edx,dword ptr ss:[ebp-C] ; 上面的函數(shù)就是注冊碼的第二次變形了 數(shù)字“0”、大寫字符“O”和假碼同時入棧,葫蘆里賣的什么藥?進(jìn)去遛遛 ...... 005DD83C E8 4B5DE2FF call Atlantis.0040358C ; 算出注冊碼長度 005DD841 83F8 01 cmp eax,1 005DD844 7C 1D jl short Atlantis.005DD863 005DD846 89C7 mov edi,eax ; 注冊碼長度放入 005DD848 8B06 mov eax,dword ptr ds:[esi] ; 注冊碼放入 005DD84A 3A5C38 FF cmp bl,byte ptr ds:[eax+edi-1] ; 假碼從后往前逐位與大寫字母“O”比較 005DD84E 75 0E jnz short Atlantis.005DD85E ; 一路小跑過去,發(fā)現(xiàn)這里是把注冊碼中出現(xiàn)的字母“O”替換成數(shù)字“0” 005DD850 8BC6 mov eax,esi ; 企圖混淆視聽啊 005DD852 E8 055FE2FF call Atlantis.0040375C 汗,這都行?至此,我們的假碼經(jīng)過了兩次加工,記住 ...... 0049665F 8B45 FC mov eax,dword ptr ss:[ebp-4] 00496662 E8 25CFF6FF call Atlantis.0040358C ; 算出注冊碼長度 00496667 8BF0 mov esi,eax 00496669 83FE 01 cmp esi,1 0049666C 7C 3D jl short Atlantis.004966AB 0049666E 8B45 FC mov eax,dword ptr ss:[ebp-4] ; 經(jīng)過以上兩次加工后的變形假碼放入EAX 00496671 8A4430 FF mov al,byte ptr ds:[eax+esi-1] ; 注冊碼從后往前依次參與運(yùn)算 00496675 8BD0 mov edx,eax 00496677 80EA 20 sub dl,20 ; 逐位比較是不是空格 0049667A 74 05 je short Atlantis.00496681 0049667C 80EA 0D sub dl,0D ; 逐位比較是不是連字符“-” 0049667F 75 11 jnz short Atlantis.00496692 00496681 8D45 FC lea eax,dword ptr ss:[ebp-4] 00496684 B9 01000000 mov ecx,1 00496689 8BD6 mov edx,esi 0049668B E8 40D1F6FF call Atlantis.004037D0 ; 去除注冊碼中的“-” 00496690 EB 14 jmp short Atlantis.004966A6 00496692 8B55 FC mov edx,dword ptr ss:[ebp-4] ; 假碼放入edx 00496695 25 FF000000 and eax,0FF 0049669A 8B15 4C7E6100 mov edx,dword ptr ds:[617E4C] ; Atlantis.0061CC30 004966A0 803C02 FF cmp byte ptr ds:[edx+eax],0FF ; 此時eax的值就是假碼中每一位字母或數(shù)字的十六進(jìn)制值 004966A4 74 77 je short Atlantis.0049671D ; 注冊碼中的每一位只能是 數(shù)字或a~f或A~F或字母o/O(不明白看下面的分析) 004966A6 4E dec esi 004966A7 85F6 test esi,esi 004966A9 ^ 75 C3 jnz short Atlantis.0049666E 004966AB 8B45 FC mov eax,dword ptr ss:[ebp-4] ; 無連字符“-”的大寫注冊碼放入 004966AE E8 D9CEF6FF call Atlantis.0040358C ; 求經(jīng)過三次變形后的假碼長度 004966B3 83F8 10 cmp eax,10 ; 注冊碼16位啊 004966B6 75 65 jnz short Atlantis.0049671D 上述代碼的后半部分理解有些費(fèi)力 0049669A 8B15 4C7E6100 mov edx,dword ptr ds:[617E4C] ; Atlantis.0061CC30 [617E4C]指向的地址是0061CC30,我們看一下數(shù)據(jù)窗口對應(yīng)位置的數(shù)值 醒目一點(diǎn)的估計(jì)看出來了,截圖上的地址是從0061CC60開始的,為什么呢? 0049669A 8B15 4C7E6100 mov edx,dword ptr ds:[617E4C] ; Atlantis.0061CC30 004966A0 803C02 FF cmp byte ptr ds:[edx+eax],0FF ; 此時eax的值就是假碼中每一位字母或數(shù)字對應(yīng)的十六進(jìn)制值 問題就出在第二句的[edx+eax]處,靜態(tài)解釋不易理解,動態(tài)跟蹤一下就明白了 假設(shè)假碼中其中一位字符是“8” 對應(yīng)十六進(jìn)制是 0x38 而edx == 0061CC30,所以[edx+eax] == 0061CC68 這個地址對應(yīng)上圖可知值為0x08,并不等于0xFF,證明假碼中的這一位合格 好,跟蹤至此,我們的假碼可以進(jìn)行修正了 HelloHenu --> Babe-5214-0987-acef 以上都是一些準(zhǔn)備工作,下面就真的進(jìn)入了算法核心了 …… 004966B8 BE 01000000 mov esi,1 ; 核心算法開始了 esi初始值為1 004966BD 8BC6 mov eax,esi ; 一個大的算法循環(huán) 開始處 004966BF 48 dec eax 004966C0 03C0 add eax,eax 004966C2 40 inc eax 004966C3 8B55 FC mov edx,dword ptr ss:[ebp-4] ; 幾次變形后的注冊碼放入 004966C6 0FB65402 FF movzx edx,byte ptr ds:[edx+eax-1] ; 注冊碼從前往后依次運(yùn)算 004966CB 8B0D 4C7E6100 mov ecx,dword ptr ds:[617E4C] ; Atlantis.0061CC30 004966D1 8A1411 mov dl,byte ptr ds:[ecx+edx] 004966D4 C1E2 04 shl edx,4 004966D7 8B4D FC mov ecx,dword ptr ss:[ebp-4] 004966DA 0FB60401 movzx eax,byte ptr ds:[ecx+eax] 004966DE 8B0D 4C7E6100 mov ecx,dword ptr ds:[617E4C] ; Atlantis.0061CC30 004966E4 021401 add dl,byte ptr ds:[ecx+eax] 004966E7 8855 FA mov byte ptr ss:[ebp-6],dl ; 可以看出,從前往后依次取出注冊碼的每兩位進(jìn)行下面的運(yùn)算 004966EA B8 58674900 mov eax,Atlantis.00496758 ; 00496758地址處有段8位的密鑰參與運(yùn)算 004966EF 8A4430 FF mov al,byte ptr ds:[eax+esi-1] 004966F3 C645 F9 01 mov byte ptr ss:[ebp-7],1 ; (這里 標(biāo)志位哦) 004966F7 B3 08 mov bl,8 004966F9 E8 0AFFFFFF call Atlantis.00496608 ; 把密鑰的對應(yīng)位數(shù)值做一次ror(循環(huán)右移)運(yùn)算 004966FE 3A45 FA cmp al,byte ptr ss:[ebp-6] ; 比較置換后的對應(yīng)位注冊碼值是否等于ror后的密鑰值 00496701 75 06 jnz short Atlantis.00496709 ; 事實(shí)證明,如果不等于,最終就提示注冊碼錯誤 00496703 C645 F9 00 mov byte ptr ss:[ebp-7],0 00496707 EB 04 jmp short Atlantis.0049670D 00496709 FECB dec bl ; 對應(yīng)密鑰可以循環(huán)8次ror運(yùn)算,共產(chǎn)生8個值 0049670B ^ 75 EC jnz short Atlantis.004966F9 ; 每次對應(yīng)取出的兩位注冊碼值必須等于上述8個結(jié)果的其中一個 其實(shí),軟件核心的算法就是: 1、 注冊碼應(yīng)為16位,有沒有“-”連接都可以 2、 注冊碼中的每一位只能是 0~9或a~f或A~F或字母o/O 3、 從前往后每次取出2位注冊碼值,轉(zhuǎn)換成一個字節(jié)的十六進(jìn)制值 如字符“a5c3” 就轉(zhuǎn)換成 0xA5 0xC3 這樣十六位的注冊碼,就變成了占8字節(jié)的一串十六進(jìn)制值 4、 程序預(yù)置8位密鑰,如下 5、 每位密鑰都進(jìn)行 至少一次的ror運(yùn)算,把第一次ror后得出的值與相應(yīng)位置的注冊碼值比較,如果不相等則在第一次算出值的基礎(chǔ)上進(jìn)行第二次的ror運(yùn)算,依次循環(huán),共可循環(huán)8次--如果還不相等,就說明是錯誤注冊碼了,不再繼續(xù)運(yùn)算 可以004966FE處為切入點(diǎn),其中al的值就是密鑰ror運(yùn)算出的值--可用的注冊碼的其中兩個值。在004966FE處下斷,修改00496701處的jnz跳轉(zhuǎn)為NOP,F(xiàn)9繼續(xù)運(yùn)算可以很輕易地跟出可用注冊碼 004966FE 3A45 FA cmp al,byte ptr ss:[ebp-6] ; 比較置換后的對應(yīng)位注冊碼值是否等于ror后的密鑰值 隨便F9了幾下 總結(jié)了幾個類似A7B1-A6B4-2732-E1F2 7A1B6A4B72231E2F這樣的值,不知道有什么用o_0 軟件注冊后,相關(guān)信息保存于注冊表以下位置(軟件沒有對關(guān)鍵信息加密,也是一個敗筆): Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Rising Sun Solutions, Inc.\Atlantis.1_x\RegInfo] "RegCode"="XXXXXXXXXXXXXXXX" "RegTo"="playboysen" 總結(jié): 看算法的分析有很多,但最主要的驗(yàn)證算法只有以下幾行 Mov esi,1 mov eax,00496758 //這里是預(yù)置的一個8位數(shù)組,具體參考上圖 mov al,byte ptr ds:[eax+esi-1] mov bl,8 004966F9: Ror al,1 cmp al,byte ptr ss:[ebp-6] //在這里添加相應(yīng)代碼取出al中的值轉(zhuǎn)換后連接成16位的字符串即為一組注冊碼 dec bl jnz 004966F9 inc esi cmp esi,9 jz XXXXX 其實(shí),上周就開始分析這個程序了,一路小跑幾次覺得算法不難,但很繁瑣,沒有耐心看,擱置一周。偶爾看到kanxue十天前留下的信息,感動老大還記得我輩之余頓悟自己今年確實(shí)墮落了,莫說文章之類,就連論壇都鮮有登陸,慚愧!新入職,一切都不穩(wěn)定,有些心浮氣躁。 離開幾個月回來發(fā)現(xiàn)大家都跑去搞VM、驅(qū)動之類去了,牛X新殼如雨后春筍層出不窮,自己竟成了古董。唏噓不已,感慨IT業(yè)發(fā)展之迅猛。也鮮有大蝦寫些算法分析之流的東西,自己也懼怕貽笑大方??爝^年了,寫篇文章湊個數(shù),算是給自己一個交代。 補(bǔ)充注冊機(jī)代碼: 代碼: .data szFormat db '%s-%s-%s-%s',0 error db 'Please input your name!',0 Temp db 4Fh,63h,4Dh,69h,4Eh,64h,0C3h,0E5h .data? hInstance dd ? S1 db 8 dup(?) S2 db 8 dup(?) S3 db 8 dup(?) S4 db 8 dup(?) S5 db 8 dup(?) S6 db 8 dup(?) S7 db 8 dup(?) S8 db 8 dup(?) Serial db 8 dup(?) ;注意此處不能定義成4字節(jié),必須留5字節(jié)以上的空間,因?yàn)樽址詈笥幸粋€'\0' FinalSn1 db 5 dup(?) FinalSn2 db 5 dup(?) FinalSn3 db 5 dup(?) FinalSn4 db 5 dup(?) Sn db 20 dup(?) FinalSn db 20 dup(?) 算了,代碼太長 直接發(fā)Radasm工程文件吧 |
|