HappyEO演算法分析 (11千字)

看雪資料發表於2015-11-15

HappyEO 2.40.2 演算法分析

作者:bbbsl
使用工具:trw v1.23
分析平臺:盜版Win98se
軟體介紹:HappyEO是一款用音效卡類比電子琴的軟體。有了它,您可以用計算機的鍵盤奏出美妙的樂曲。還有錄音、自動伴奏和效果等功能。假如您沒有音效卡,您仍然可以用計算機內部的揚聲器來發音。
(不是我說的,是作者說的,不過確實挺好玩的,只可惜我不識譜,唉,只能瞎彈!^_*)
分析過程:
先執行trw及該軟體,然後選註冊後,會出現註冊視窗,依次填入姓名,公司名及註冊碼,作者很細心,如果填錯位數他會提醒你的,然後下斷點
bpx hmemcpy,填getwindowtexta及getdlgitemtexta均不行,那樣就過了關鍵地方了!:-P,不過在Win2000下怎麼設斷點呢?有那位大蝦能告訴我嗎?謝謝!
廢話不多說了,回到註冊介面點選確定按鈕,然後程式會斷下,然後F10,經過N個ret後,我們來到這裡:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                第一個程式段                    
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    0167:51098C40  LEA      EDX,[EBP-04]
    0167:51098C43  MOV      EAX,[EBX+02D0]
    0167:51098C49  CALL    510312E0            ==>我們從這裡出來停在下一行!
    0167:51098C4E  MOV      EAX,[EBP-04]        ==>Name
    0167:51098C51  CALL    51003F28            ==>這裡計算長度
    0167:51098C56  CMP      EAX,BYTE +04        ==>Name<4?報錯:繼續
    0167:51098C59  JL      NEAR 51098DB0        
    0167:51098C5F  LEA      EDX,[EBP-08]        
    0167:51098C62  MOV      EAX,[EBX+02EC]
    0167:51098C68  CALL    510312E0            ==>經過這個call取公司名
    0167:51098C6D  MOV      EAX,[EBP-08]        ==>Corporation
    0167:51098C70  CALL    51003F28            ==>計算長度
    0167:51098C75  CMP      EAX,BYTE +0C        ==>Corporation<12?報錯:繼續
    0167:51098C78  JL      NEAR 51098DB0
    0167:51098C7E  LEA      EDX,[EBP-0C]        
    0167:51098C81  MOV      EAX,[EBX+02D4]        
    0167:51098C87  CALL    510312E0            ==>在這裡取註冊碼
    0167:51098C8C  MOV      EAX,[EBP-0C]        ==>我們輸入的註冊碼
    0167:51098C8F  CALL    51003F28            ==>計算長度
    0167:51098C94  CMP      EAX,BYTE +06        ==>長度<6?報錯:繼續
    0167:51098C97  JNZ      NEAR 51098DB0
    0167:51098C9D  LEA      EDX,[EBP-10]
    0167:51098CA0  MOV      EAX,[EBX+02D4]
    0167:51098CA6  CALL    510312E0            
    0167:51098CAB  MOV      EAX,[EBP-10]        ==>再取一遍?
    0167:51098CAE  PUSH    EAX            ==>註冊碼進棧
    0167:51098CAF  LEA      EDX,[EBP-18]        
    0167:51098CB2  MOV      EAX,[EBX+02EC]        
    0167:51098CB8  CALL    510312E0            
    0167:51098CBD  MOV      EAX,[EBP-18]            
    0167:51098CC0  PUSH    EAX            ==>Corp進棧    
    0167:51098CC1  LEA      EDX,[EBP-1C]
    0167:51098CC4  MOV      EAX,[EBX+02D0]
    0167:51098CCA  CALL    510312E0            
    0167:51098CCF  MOV      EAX,[EBP-1C]        ==>eax<--Name
    0167:51098CD2  LEA      ECX,[EBP-14]        ==>用來存放地址的一個指標
    0167:51098CD5  POP      EDX            ==>edx<--Corp    
    0167:51098CD6  CALL    510980B4            ==>關鍵,跟進!
    0167:51098CDB  MOV      EDX,[EBP-14]        ==>這裡D edx可得註冊碼
    0167:51098CDE  POP      EAX            ==>假註冊碼
    0167:51098CDF  CALL    51004038            ==>比較是否正確,就不看怎麼比較的了吧!
    0167:51098CE4  JNZ      NEAR 51098D9A        
    0167:51098CEA  MOV      EAX,51098E00
    0167:51098CEF  CALL    51056968
    0167:51098CF4  CALL    51009688
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//              這裡是剛才我說的關鍵call                    
//                                        
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
   
    0167:510980B4  PUSH    EBP
    0167:510980B5  MOV      EBP,ESP
    0167:510980B7  ADD      ESP,BYTE -10
    0167:510980BA  PUSH    EBX
    0167:510980BB  XOR      EBX,EBX
    0167:510980BD  MOV      [EBP-10],EBX        ==>相當於四個變數
    0167:510980C0  MOV      [EBP-0C],ECX        
    0167:510980C3  MOV      [EBP-08],EDX
    0167:510980C6  MOV      [EBP-04],EAX
    0167:510980C9  MOV      EAX,[EBP-04]        
    0167:510980CC  CALL    510040DC            
    0167:510980D1  MOV      EAX,[EBP-08]        
    0167:510980D4  CALL    510040DC            
    0167:510980D9  XOR      EAX,EAX            
    0167:510980DB  PUSH    EBP            
    0167:510980DC  PUSH    DWORD 5109814A        
    0167:510980E1  PUSH    DWORD [FS:EAX]        
    0167:510980E4  MOV      [FS:EAX],ESP        
    0167:510980E7  MOV      EAX,[EBP-0C]        
    0167:510980EA  CALL    51003CA8            
    0167:510980EF  MOV      EAX,[EBP-04]        ==>又來了,判斷名字長度
    0167:510980F2  CALL    51003F28            
    0167:510980F7  CMP      EAX,BYTE +04        
    0167:510980FA  JL      51098127            
    0167:510980FC  MOV      EAX,[EBP-08]        ==>判斷公司名長度
    0167:510980FF  CALL    51003F28
    0167:51098104  CMP      EAX,BYTE +0C        
    0167:51098107  JL      51098127            
    0167:51098109  LEA      EAX,[EBP-10]        
    0167:5109810C  MOV      ECX,[EBP-08]        ==>公司名
    0167:5109810F  MOV      EDX,[EBP-04]        ==>Name
    0167:51098112  CALL    51003F74            ==>這裡用來合併姓名和公司名
    0167:51098117  MOV      EAX,[EBP-10]        ==>eax<--合併後的字串
    0167:5109811A  CALL    51097F9C            ==>用這個字串來算一個重要數!跟進!
    0167:5109811F  MOV      EDX,[EBP-0C]        ==>透過運算得到一個數
    0167:51098122  CALL    51098024            ==>用這個數求最後的六位註冊碼
    0167:51098127  XOR      EAX,EAX            
    0167:51098129  POP      EDX            
    0167:5109812A  POP      ECX            
    0167:5109812B  POP      ECX            
    0167:5109812C  MOV      [FS:EAX],EDX        
    0167:5109812F  PUSH    DWORD 51098151        
    0167:51098134  LEA      EAX,[EBP-10]        
    0167:51098137  CALL    51003CA8
    0167:5109813C  LEA      EAX,[EBP-08]
    0167:5109813F  MOV      EDX,02
    0167:51098144  CALL    51003CCC
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                算註冊碼的CALL一                    
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    0167:51097F9C  PUSH    EBP
    0167:51097F9D  MOV      EBP,ESP
    0167:51097F9F  ADD      ESP,BYTE -10
    0167:51097FA2  MOV      [EBP-04],EAX
    0167:51097FA5  MOV      EAX,[EBP-04]
    0167:51097FA8  CALL    510040DC
    0167:51097FAD  XOR      EAX,EAX
    0167:51097FAF  PUSH    EBP
    0167:51097FB0  PUSH    DWORD 51098016
    0167:51097FB5  PUSH    DWORD [FS:EAX]
    0167:51097FB8  MOV      [FS:EAX],ESP
    0167:51097FBB  MOV      DWORD [EBP-08],FFFFFFFF    ==>設[ebp-8]為tempvar
    0167:51097FC2  MOV      EAX,[EBP-04]        ==>那串字串設為str[]
    0167:51097FC5  CALL    51003F28            
    0167:51097FCA  TEST    EAX,EAX            
    0167:51097FCC  JNG      51097FF5            
    0167:51097FCE  MOV      [EBP-10],EAX        ==>設[ebp-10]為lenofnc
    0167:51097FD1  MOV      DWORD [EBP-0C],01    ==>設[ebp-c]為i
    0167:51097FD8  MOV      EAX,[EBP-04]        ==>字串地址addrofstr<--[ebp-4]
    0167:51097FDB  MOV      EDX,[EBP-0C]        ==>用edx來從字串定位字元
    0167:51097FDE  MOV      AL,[EAX+EDX-01]        ==>一次取一個字元
    0167:51097FE2  MOV      EDX,[EBP-08]        ==>edx<--tempvar,初值為-1
    0167:51097FE5  CALL    51097F48            ==>中間為查表過程,過會詳細看看
    0167:51097FEA  MOV      [EBP-08],EAX        ==>得到的結果放入tempvar
    0167:51097FED  INC      DWORD [EBP-0C]        ==>i++
    0167:51097FF0  DEC      DWORD [EBP-10]        ==>lenofnc--
    0167:51097FF3  JNZ      51097FD8            ==>lenofnc==0?往下走:迴圈
    0167:51097FF5  MOV      EAX,[EBP-08]        
    0167:51097FF8  CALL    51097F80            ==>得到的最終結果取反
    0167:51097FFD  MOV      [EBP-08],EAX        
    0167:51098000  XOR      EAX,EAX            
    0167:51098002  POP      EDX
    0167:51098003  POP      ECX
    0167:51098004  POP      ECX
    0167:51098005  MOV      [FS:EAX],EDX
    0167:51098008  PUSH    DWORD 5109801D
    0167:5109800D  LEA      EAX,[EBP-04]
    0167:51098010  CALL    51003CA8
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                註冊碼從call                    
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////   
   
   
    0167:51097F48  PUSH    EBP
    0167:51097F49  MOV      EBP,ESP
    0167:51097F4B  ADD      ESP,BYTE -0C
    0167:51097F4E  MOV      [EBP-08],EDX        ==>tempvar
    0167:51097F51  MOV      [EBP-01],AL        ==>所取字元
    0167:51097F54  MOV      AL,[EBP-08]        
    0167:51097F57  XOR      AL,[EBP-01]        ==>tempvar^str[i]
    0167:51097F5A  AND      EAX,FF            ==>temp<--tempvar^str[i]&0xff
    0167:51097F5F  MOV      EAX,[EAX*4+510DFEB4]    ==>用temp查表送往eax
    0167:51097F66  MOV      EDX,[EBP-08]        
    0167:51097F69  SHR      EDX,08            ==>tempvar>>=8
    0167:51097F6C  AND      EDX,00FFFFFF        ==>tempvar&=0xffffff
    0167:51097F72  XOR      EAX,EDX            ==>eax<--tempvar^[temp*4+510dfeb4]
    0167:51097F74  MOV      [EBP-0C],EAX        
    0167:51097F77  MOV      EAX,[EBP-0C]
    0167:51097F7A  MOV      ESP,EBP
    0167:51097F7C  POP      EBP
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                在這裡面,剛才的最終數被取反                
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    0167:51097F80  PUSH    EBP
    0167:51097F81  MOV      EBP,ESP
    0167:51097F83  ADD      ESP,BYTE -08
    0167:51097F86  MOV      [EBP-04],EAX
    0167:51097F89  MOV      EAX,[EBP-04]
    0167:51097F8C  XOR      EAX,BYTE -01        ==>It's here!!!
    0167:51097F8F  MOV      [EBP-08],EAX
    0167:51097F92  MOV      EAX,[EBP-08]
    0167:51097F95  POP      ECX
    0167:51097F96  POP      ECX
    0167:51097F97  POP      EBP

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                        
//                最後一個call,用來算六位註冊碼                
//                                        
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    0167:51098024  PUSH    EBP
    0167:51098025  MOV      EBP,ESP
    0167:51098027  ADD      ESP,BYTE -14
    0167:5109802A  XOR      ECX,ECX
    0167:5109802C  MOV      [EBP-14],ECX
    0167:5109802F  MOV      [EBP-08],EDX
    0167:51098032  MOV      [EBP-04],EAX
    0167:51098035  XOR      EAX,EAX
    0167:51098037  PUSH    EBP
    0167:51098038  PUSH    DWORD 510980A6
    0167:5109803D  PUSH    DWORD [FS:EAX]
    0167:51098040  MOV      [FS:EAX],ESP
    0167:51098043  MOV      EAX,[EBP-08]
    0167:51098046  CALL    51003CA8
    0167:5109804B  XOR      EAX,EAX
    0167:5109804D  MOV      [EBP-0C],EAX
    0167:51098050  MOV      EAX,[EBP-04]            ==>剛才求得的那個數字
    0167:51098053  MOV      ECX,24                ==>除數為0x24
    0167:51098058  XOR      EDX,EDX                
    0167:5109805A  DIV      ECX                ==>edx=eax%0x24
    0167:5109805C  MOV      DL,[EDX+510E02B5]        ==>用餘數來查表
    0167:51098062  LEA      EAX,[EBP-14]            ==>這裡的地址用來存放註冊碼
    0167:51098065  CALL    51003E50                ==>存註冊碼
    0167:5109806A  MOV      EDX,[EBP-14]            
    0167:5109806D  MOV      EAX,[EBP-08]            
    0167:51098070  CALL    51003F30
    0167:51098075  MOV      EAX,[EBP-08]
    0167:51098078  MOV      EAX,[EBP-04]
    0167:5109807B  MOV      ECX,24
    0167:51098080  XOR      EDX,EDX
    0167:51098082  DIV      ECX
    0167:51098084  MOV      [EBP-04],EAX            ==>將除完了的數放回ebp-4
    0167:51098087  INC      DWORD [EBP-0C]            ==>迴圈計數器
    0167:5109808A  CMP      DWORD [EBP-0C],BYTE +06        ==>是否已經六位了?
    0167:5109808E  JNZ      51098050
    0167:51098090  XOR      EAX,EAX
    0167:51098092  POP      EDX
    0167:51098093  POP      ECX
    0167:51098094  POP      ECX
    0167:51098095  MOV      [FS:EAX],EDX
    0167:51098098  PUSH    DWORD 510980AD
    0167:5109809D  LEA      EAX,[EBP-14]
    0167:510980A0  CALL    51003CA8
   
##############################################################
我認為我分析的挺詳細了,有什麼地方不對謝謝指教!其實就是這麼簡單,不過我的序號產生器放2000下了,沒法帖出來,見諒,不過到這裡,大家也能自己寫出來了吧!

相關文章