【使用工具】: OD、Atlantis Word Processor
---------------------------------------------------------
Atlantis Word Processor 一個(gè)獨(dú)立的word處理器,支持讀取并編輯*.rtf *.doc *.docx *.cod *.txt等數(shù)種格式的文檔,支持命令行,軟件小巧界面清爽,占用內(nèi)存小,處理速度快,打開保存文件時(shí)支持全word格式的預(yù)覽。(兩個(gè)小小遺憾--word文檔中的中文引號(hào)會(huì)顯示亂碼;竟不支持中文txt文件,汗。期待更新)
試運(yùn)行得知軟件以用戶名、注冊(cè)碼方式保護(hù)(其實(shí)用戶名不參與運(yùn)算),有出錯(cuò)提示,UPX弱殼。
脫殼OD加載后,查找字符串“invalid”找到以下關(guān)鍵部位,以用戶名playboysen,注冊(cè)碼HelloHenu試煉(算法分析一般都是隨便輸入假碼后粗略跟蹤幾次注冊(cè)碼的驗(yàn)證流程,根據(jù)驗(yàn)證流程一次次地修正假碼,最終得出一組可用注冊(cè)碼,弄清算法)
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
; 算出注冊(cè)碼長度00495FF7 8B45 FC
mov eax,
dword ptr ss:[
ebp-4]
; 假碼放入eax00495FFA E8 0D060000
call Atlantis.0049660C
; 關(guān)鍵處,跟進(jìn)00495FFF 84C0
test al,
al00496001 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
; 注冊(cè)碼第一次變形,把假碼中的小寫字母轉(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ù),猜測這個(gè)函數(shù)里面有貓膩兒00496654 8B55 F4
mov edx,
dword ptr ss:[
ebp-C]
; 上面的函數(shù)就是注冊(cè)碼的第二次變形了數(shù)字“0”、大寫字符“O”和假碼同時(shí)入棧,葫蘆里賣的什么藥?進(jìn)去遛遛
......
005DD83C E8 4B5DE2FF
call Atlantis.0040358C
; 算出注冊(cè)碼長度005DD841 83F8 01
cmp eax,1
005DD844 7C 1D
jl short Atlantis.005DD863
005DD846 89C7
mov edi,
eax ; 注冊(cè)碼長度放入005DD848 8B06
mov eax,
dword ptr ds:[
esi]
; 注冊(cè)碼放入005DD84A 3A5C38 FF
cmp bl,
byte ptr ds:[
eax+
edi-1]
; 假碼從后往前逐位與大寫字母“O”比較005DD84E 75 0E
jnz short Atlantis.005DD85E
; 一路小跑過去,發(fā)現(xiàn)這里是把注冊(cè)碼中出現(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
; 算出注冊(cè)碼長度00496667 8BF0
mov esi,
eax00496669 83FE 01
cmp esi,1
0049666C 7C 3D
jl short Atlantis.004966AB
0049666E 8B45 FC
mov eax,
dword ptr ss:[
ebp-4]
; 經(jīng)過以上兩次加工后的變形假碼放入EAX00496671 8A4430 FF
mov al,
byte ptr ds:[
eax+
esi-1]
; 注冊(cè)碼從后往前依次參與運(yùn)算00496675 8BD0
mov edx,
eax00496677 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,
esi0049668B E8 40D1F6FF
call Atlantis.004037D0
; 去除注冊(cè)碼中的“-”00496690 EB 14
jmp short Atlantis.004966A6
00496692 8B55 FC
mov edx,
dword ptr ss:[
ebp-4]
; 假碼放入edx00496695 25 FF000000
and eax,0FF
0049669A 8B15 4C7E6100
mov edx,
dword ptr ds:[617E4C]
; Atlantis.0061CC30004966A0 803C02 FF
cmp byte ptr ds:[
edx+
eax],0FF
; 此時(shí)eax的值就是假碼中每一位字母或數(shù)字的十六進(jìn)制值004966A4 74 77
je short Atlantis.0049671D
; 注冊(cè)碼中的每一位只能是 數(shù)字或a~f或A~F或字母o/O(不明白看下面的分析)004966A6 4E
dec esi004966A7 85F6
test esi,
esi004966A9 ^ 75 C3
jnz short Atlantis.0049666E
004966AB 8B45 FC
mov eax,
dword ptr ss:[
ebp-4]
; 無連字符“-”的大寫注冊(cè)碼放入004966AE E8 D9CEF6FF
call Atlantis.0040358C
; 求經(jīng)過三次變形后的假碼長度004966B3 83F8 10
cmp eax,10
; 注冊(cè)碼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ù)窗口對(duì)應(yīng)位置的數(shù)值
醒目一點(diǎn)的估計(jì)看出來了,截圖上的地址是從0061CC60開始的,為什么呢?
0049669A 8B15 4C7E6100
mov edx,
dword ptr ds:[617E4C]
; Atlantis.0061CC30004966A0 803C02 FF
cmp byte ptr ds:[
edx+
eax],0FF
; 此時(shí)eax的值就是假碼中每一位字母或數(shù)字對(duì)應(yīng)的十六進(jìn)制值問題就出在第二句的[
edx+
eax]處,靜態(tài)解釋不易理解,動(dòng)態(tài)跟蹤一下就明白了
假設(shè)假碼中其中一位字符是“8” 對(duì)應(yīng)十六進(jìn)制是 0x38
而edx == 0061CC30,所以[
edx+
eax] == 0061CC68 這個(gè)地址對(duì)應(yīng)上圖可知值為0x08,并不等于0xFF,證明假碼中的這一位合格
好,跟蹤至此,我們的假碼可以進(jìn)行修正了
HelloHenu --> Babe-5214-0987-acef
以上都是一些準(zhǔn)備工作,下面就真的進(jìn)入了算法核心了
……
004966B8 BE 01000000
mov esi,1
; 核心算法開始了 esi初始值為1004966BD 8BC6
mov eax,
esi ; 一個(gè)大的算法循環(huán) 開始處004966BF 48
dec eax004966C0 03C0
add eax,
eax004966C2 40
inc eax004966C3 8B55 FC
mov edx,
dword ptr ss:[
ebp-4]
; 幾次變形后的注冊(cè)碼放入004966C6 0FB65402 FF
movzx edx,
byte ptr ds:[
edx+
eax-1]
; 注冊(cè)碼從前往后依次運(yùn)算004966CB 8B0D 4C7E6100
mov ecx,
dword ptr ds:[617E4C]
; Atlantis.0061CC30004966D1 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.0061CC30004966E4 021401
add dl,
byte ptr ds:[
ecx+
eax]
004966E7 8855 FA
mov byte ptr ss:[
ebp-6],
dl ; 可以看出,從前往后依次取出注冊(cè)碼的每兩位進(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
; 把密鑰的對(duì)應(yīng)位數(shù)值做一次ror(循環(huán)右移)運(yùn)算004966FE 3A45 FA
cmp al,
byte ptr ss:[
ebp-6]
; 比較置換后的對(duì)應(yīng)位注冊(cè)碼值是否等于ror后的密鑰值00496701 75 06
jnz short Atlantis.00496709
; 事實(shí)證明,如果不等于,最終就提示注冊(cè)碼錯(cuò)誤00496703 C645 F9 00
mov byte ptr ss:[
ebp-7],0
00496707 EB 04
jmp short Atlantis.0049670D
00496709 FECB
dec bl ; 對(duì)應(yīng)密鑰可以循環(huán)8次ror運(yùn)算,共產(chǎn)生8個(gè)值0049670B ^ 75 EC
jnz short Atlantis.004966F9
; 每次對(duì)應(yīng)取出的兩位注冊(cè)碼值必須等于上述8個(gè)結(jié)果的其中一個(gè)其實(shí),軟件核心的算法就是:
1、 注冊(cè)碼應(yīng)為16位,有沒有“-”連接都可以
2、 注冊(cè)碼中的每一位只能是 0~9或a~f或A~F或字母o/O
3、 從前往后每次取出2位注冊(cè)碼值,轉(zhuǎn)換成一個(gè)字節(jié)的十六進(jìn)制值
如字符“a5c3” 就轉(zhuǎn)換成 0xA5 0xC3
這樣十六位的注冊(cè)碼,就變成了占8字節(jié)的一串十六進(jìn)制值
4、 程序預(yù)置8位密鑰,如下
5、 每位密鑰都進(jìn)行 至少一次的ror運(yùn)算,把第一次ror后得出的值與相應(yīng)位置的注冊(cè)碼值比較,如果不相等則在第一次算出值的基礎(chǔ)上進(jìn)行第二次的ror運(yùn)算,依次循環(huán),共可循環(huán)8次--如果還不相等,就說明是錯(cuò)誤注冊(cè)碼了,不再繼續(xù)運(yùn)算
可以004966FE處為切入點(diǎn),其中al的值就是密鑰ror運(yùn)算出的值--可用的注冊(cè)碼的其中兩個(gè)值。在004966FE處下斷,修改00496701處的jnz跳轉(zhuǎn)為NOP,F(xiàn)9繼續(xù)運(yùn)算可以很輕易地跟出可用注冊(cè)碼
004966FE 3A45 FA
cmp al,
byte ptr ss:[
ebp-6]
; 比較置換后的對(duì)應(yīng)位注冊(cè)碼值是否等于ror后的密鑰值隨便F9了幾下
總結(jié)了幾個(gè)類似A7B1-A6B4-2732-E1F2 7A1B6A4B72231E2F這樣的值,不知道有什么用o_0
軟件注冊(cè)后,相關(guān)信息保存于注冊(cè)表以下位置(軟件沒有對(duì)關(guān)鍵信息加密,也是一個(gè)敗筆):
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ù)置的一個(gè)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位的字符串即為一組注冊(cè)碼
dec bljnz 004966F9
inc esicmp esi,9
jz XXXXX
其實(shí),上周就開始分析這個(gè)程序了,一路小跑幾次覺得算法不難,但很繁瑣,沒有耐心看,擱置一周。偶爾看到kanxue十天前留下的信息,感動(dòng)老大還記得我輩之余頓悟自己今年確實(shí)墮落了,莫說文章之類,就連論壇都鮮有登陸,慚愧!新入職,一切都不穩(wěn)定,有些心浮氣躁。
離開幾個(gè)月回來發(fā)現(xiàn)大家都跑去搞VM、驅(qū)動(dòng)之類去了,牛X新殼如雨后春筍層出不窮,自己竟成了古董。唏噓不已,感慨IT業(yè)發(fā)展之迅猛。也鮮有大蝦寫些算法分析之流的東西,自己也懼怕貽笑大方。快過年了,寫篇文章湊個(gè)數(shù),算是給自己一個(gè)交代。
補(bǔ)充注冊(cè)機(jī)代碼:
代碼:
.dataszFormat db '%s-%s-%s-%s',0error db 'Please input your name!',0Temp 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)樽址詈笥幸粋€(gè)'\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工程文件吧