逆向分析學習入門教程

轉在於 逆向工廠(一):從hello world開始

前沿

從本篇起,逆向工廠帶大家從程序起源講起,領略計算機程序逆向技術,瞭解程序的運行機制,逆向通用技術手段和軟件保護技術,更加深入地去探索逆向的魅力。

一、程序如何誕生?

這裏寫圖片描述

1951年4月開始在英國牛津郡哈維爾原子能研究基地正式投入使用的英國數字計算機“哈維爾·德卡特倫”,是當時世界上僅有的十幾臺電腦之一。圖中兩人手持的“紙帶”即是早期的程序,紙帶通過是否穿孔記錄1或0,而這些正好對應電子器件的開關狀態,這便是機器碼,是一種早期計算機程序的存儲形式。
這裏寫圖片描述

計算機程序是用來實現某特定目標功能,所以需要將人類思維轉換爲計算機可識別的語言,從人類語言到電子器件開關的閉合,這中間的媒介便是“編程語言”。

“編程語言”大致分爲三類:

1、機器語言,又稱機器碼、原生碼,電腦CPU可直接解讀,因該語言與運行平臺密切相關,故通用性很差,上面提到的利用卡帶記錄的便屬於該類語言;

2、彙編語言,是一種用於電子計算機、微處理器、微控制器或其他可編程器件的低級語言,亦稱爲符號語言。在不同的設備中,彙編語言對應着不同的機器語言指令集, 運行時按照設備對應的機器碼指令進行轉換,所以彙編語言可移植性也較差;
這裏寫圖片描述

3、高級語言,與前兩種語言相比,該類語言高度抽象封裝,語法結構更接近人類語言,邏輯也與人類思維邏輯相似,因此具有較高的可讀性和編程效率。但是高級語言與彙編語言相比,因編譯生成的輔助代碼較多,使運行速度相對“較慢”。 java,c,c++,C#,pascal,python,lisp,prolog,FoxPro,易語言等等 均屬於高級語言。

學會編程語言各種基本語義語法後,就可以實戰了,而實戰場所由IDE提供。IDE(集成開發環境Integrated Development Environment)是用於提供程序開發環境的應用程序,目前IDE的種類繁多,不再敖述,只要自己用得順手、開發效率高、你開心就好。
這裏寫圖片描述

通過IDE可快速生成程序,根據程序的生成和運行過程,程序大致可分爲兩類:編譯型程序解釋型程序

編譯型程序:程序在執行前編譯成機器語言文件,運行時不需要重新翻譯,直接供機器運行,該類程序執行效率高,依賴編譯器,跨平臺性差,如C、C++、Delphi等;

解釋型程序:程序在用編程語言編寫後,不需要編譯,以文本方式存儲原始代碼,在運行時,通過對應的解釋器解釋成機器碼後再運行,如Basic語言,執行時逐條讀取解釋每個語句,然後再執行。由此可見解釋型語言每執行一句就要翻譯一次,效率比較低,但是相比較編譯型程序來說,優勢在於跨平臺性好。

Q : Java屬於編譯型語言OR解釋型語言?

這裏寫圖片描述

Java首先將源代碼通過編譯器編譯成.class類型文件(字節碼),這是java自定義的一種類型,只能由JAVA虛擬機(JVM)識別。程序運行時JVM從.class文件中讀一行解釋執行一行。另外JAVA爲實現跨平臺,不同操作系統對應不同的JVM。從這個過程來看JAVA程序前半部分經過了編譯,而後半部分又經過解析才能運行,可以說是一種混合型程序,由於該類程序運行依賴虛擬機,一些地方稱其爲“虛擬機語言”。下圖展現各語言之間關係。

這裏寫圖片描述

硬件->機器語言->彙編語言->系統語言(C和C++)->解釋型語言(python)和虛擬機語言(java),語言的封裝程度越來越高,也更加抽象,貼近於人類思維,即“造車前不用再考慮車輪怎麼造”。同時,層次越高意味着程序在執行時經歷的轉化步驟越多,畢竟都要轉換爲機器語言才能被硬件直接運行,這也是一些高級語言無法應用在效率要求較苛刻場景的原因之一。

Java爲了對運行效率進行優化,提出“JIT (Just-In-Time Compiliation)”優化技術,中文爲“即時編譯”。JVM會分析Java應用程序的函數調用並且達到內部一些閥值後將這些函數編譯爲本地更高效的機器碼,當執行中遇到這類函數,直接執行編譯好的機器碼,從而避免頻繁翻譯執行的耗時。

重點看看C\C++語言生成程序的過程及程序是以怎樣的形態存儲。
這裏寫圖片描述

上圖爲c語言程序的生成過程,主要經過編譯鏈接兩大過程。

編譯是指編譯器將源代碼進行詞法和語法的分析,將高級語言指令轉換爲彙編代碼。主要包含3個步驟:

1、預處理。正式編譯前,根據已放置在文件中的預處理指令來修改源文件的內容,包含宏定義指令,條件編譯指令,頭文件包含指令,特殊符號替換等。

2、編譯、優化。編譯程序通過詞法分析和語法分析,將其翻譯成等價的中間代碼表示或彙編代碼。

3、目標代碼生成。將上面生成的彙編代碼譯成目標機器指令的過程。目標文件中所存放着與源程序等效的目標的機器語言代碼。

鏈接是指將有關的目標文件彼此相連接生成可加載、可執行的目標文件,其核心工作是符號表解析重定位鏈接按照工作模式分靜態動態鏈接兩類

靜態鏈接:鏈接器將函數的代碼從其所在地(目標文件或靜態鏈接庫中)拷貝到最終的可執行程序中,整個過程在程序生成時完成。靜態鏈接庫實際上是一個目標文件的集合,其中的每個文件含有庫中的一個或者一組相關函數的代碼,靜態鏈接則是把相關代碼拷貝到源碼相關位置處參與程序的生成。

動態鏈接:動態鏈接庫在編譯鏈接時只提供符號表和其他少量信息用於保證所有符號引用都有定義,保證編譯順利通過。程序執行時,動態鏈接庫的全部內容將被映射到運行時相應進程的虛地址空間,根據可執行程序中記錄的信息找到相應的函數地址並調用執行。

經過編譯鏈接後,程序生成,windows程序則都已PE文件形式存儲。

PE文件全稱Portable Executable,意爲可移植可執行文件,常見的EXE、DLL、OCX、SYS、COM都是PE文件。 PE文件以段的形式存儲代碼和相關資源數據,其中數據段和代碼段是必不可少的兩個段。

Windows NT 預定義的段分別爲
.text、.bss、.rdata、.data、.rsrc、.edata、.idata、.pdata和.debug。這些段並不是都是必須的,另外也可以根據需要定義更多的段,常見的一些加殼程序則擁有自己命名的段。

在應用程序中最常出現的段有以下6種:

1、執行代碼段,.text命名;
2、數據段,.data、.rdata 命名;
3、資源段,.rsrc命名;
4、導出表,.edata命名;
5、導入表,.idata命名;
6、調試信息段,.debug命名。

下圖爲一個標準的PE文件結構。

這裏寫圖片描述

[NOTE]
到此爲止,程序就誕生了,如果你對文件形態足夠了解,就完全可以向網上的某些大牛一樣,純手工打造一個PE文件

二、程序如何運行

程序誕生後,我們就可以運行了,也就是雙擊程序後的事兒(本節重點描述windows平臺程序)。需要說明的是,上面產生的程序文件是存儲在硬盤(外存)裏的二進制數據,當你雙擊程序後,windows系統會根據後綴名進行註冊表查找相應的啓動程序,這裏我們編譯出的是以exe後綴的可執行程序,則系統對程序進行運行。

Q:系統如何運行可執行程序?

系統並非在硬盤上直接運行程序,而是將其裝載進內存裏,包括其中的代碼段、數據段等。

Q:爲什麼在這會多此一舉,把程序複製到內存再執行呢?

內存直接由CPU控制,享受與CPU通信的最優帶寬,然而硬盤是通過主板上的橋接芯片與CPU相連,所以速度比較慢。再加上傳統機械式硬盤靠電機帶動盤片轉動來讀寫數據,磁頭尋道等機械操作耗費時間,而內存條通過電路來讀寫數據,顯然電機的轉速肯定沒有電的傳輸速度快。後來的固態硬盤則大大提升了讀寫速度,但是由於控制方式依舊不同於內存,讀寫速度任然慢於內存。

爲了程序運行速率,任何程序在運行時,都是有一個叫做“裝載器”的程序先將硬盤上的數據複製到內存,然後才讓CPU來處理,這個過程就是程序的裝載。裝載器根據程序的PE頭中的各種信息,進行堆棧的申請和代碼數據的映射裝載,在完成所有的初始化工作後,程序從入口點地址進入,開始執行代碼段的第一條指令。


這裏寫圖片描述

程序從入口點開始順序執行,CPU直接與內存中的程序打交道,讀取內存中的數據進行處理,並將結果保存到內存,除非代碼段中還有保存數據到硬盤的代碼,否則程序全程都不會在硬盤中存儲任何數據。這就好比我們打開文檔編輯器去編譯文檔,不管輸入多少內容,在我們點擊“保存”前,硬盤上的程序文件都沒有變動,輸入的數據都只是存儲在內存上,如果此時很不幸斷電了,內存上的數據會立刻丟失。爲了應對這種尷尬局面,一些編輯軟件會定期自動保存新數據至硬盤上,以防意外丟失數據的情況發生。

既然程序在運行時需要加載到內存中才能運行,那麼問題來了,對於目前體積越來越龐大的遊戲來說,豈不是要把40~50G(可見使命召喚系列)的數據全塞進內存裏。在某貓上搜索某品牌電腦,按價格排序後,某款3w RMB的移動工作站的內存也只是32G,這顯然不滿足一下子裝載一款遊戲的需求。而查看該遊戲的運行配置需求,內存需求也只是幾個G而已,這是怎麼回事呢?

原來,操作系統爲解決此問題:當程序運行需要的空間大於內存容量時,會將內存中暫時不用的數據寫回硬盤;需要時再從硬盤中讀取,並將另外一部分不用的數據寫入硬盤。這樣,硬盤中部分空間會用於存儲內存中暫時不用的數據,這一部分空間就叫做虛擬內存(Virtual Memory)。其中內存交換、內存管理等詳細過程,感興趣的同學可以查閱操作系統相關書籍。


這裏寫圖片描述

一些同學看到這,就單純的認爲,調整虛擬內存空間即可變向提高內存空間,從而提升運行速度。硬盤的讀寫速度遠遠慢於內存,所以虛擬內存和內存頻繁進行數據交換會浪費很多時間,嚴重影響計算機的運行速度。所以同學們還是要努力學習,早日當上高富帥白富美,換高配置電腦吧。

這裏寫圖片描述

三、逆向目的和原理

簡要了解計算機程序基礎知識後,我們進入【逆向工廠】的正題——逆向。

Q:爲什麼要逆向?

1、破解正版軟件的授權


這裏寫圖片描述

這裏寫圖片描述

由於一些軟件採用商業化運營模式,並不開源,同時需要付費使用。爲此這些軟件採用各種保護技術對使用做了限制,而一些想享受免費的童鞋則對這些保護技術發起進攻,其中的主要技術便是逆向,通過逆向梳理出保護技術的運行機制,從而尋找突破口。

2、挑戰自我、學習提高

這裏寫圖片描述

crackme是一些公開給別人嘗試破解的小程序,製作 crackme 的人可能是程序員,想測試一下自己的軟件保護技術,也可能是一位 cracker,想挑戰一下其它 cracker 的破解實力,也可能是一些正在學習破解的人,自己編一些小程序給自己破,不管是什麼目的,都是通過crackme提高了自身能力。另外, 一些互聯網安全公司也會在面試中採取這種形式對應聘者進行測試。

3、挖掘漏洞與安全性檢測

一些安全性要求較高的行業,爲確保所用軟件的安全,而又無法獲取源碼時,也需逆向還原軟件的運行過程,確保軟件的安全可靠。另外,挖洞高手在挖掘漏洞時,經常採用逆向手段,尋找可能存在的溢出點。病毒分析師通過逆向,分析病毒的運行機制,提取特徵。

4、還原非開源項目

當你想模仿某優秀軟件實現某功能時,發現該軟件並未開源,而又很難從其他渠道獲取該軟件的具體技術細節,那麼逆向也許會幫你敲開思想的大門。

Q:既然逆向這麼神通廣大,可以解決很多問題,那麼它的原理機制是什麼?

“逆向”顧名思義,就是與將源碼變爲可執行程序的順序相反,將編譯鏈接好的程序反過來恢復成“代碼級別”。這裏之所以用到“代碼級別”一詞,是因源代碼編譯是“不可逆”過程,無法從編譯後的程序逆推出源代碼。

“逆向”通常通過工具軟件對程序進行反編譯,將二進制程序反編譯成彙編代碼,甚至可以將一些程序恢復成更爲高級的僞代碼狀態。C\C++程序在經過編譯鏈接後,程序爲機器碼,直接可供CPU使用,對於這類程序我們使用IDA、OD等逆向程序,只能將其恢復成彙編代碼狀態,然後通過讀彙編代碼來解讀程序的運行過程機制,顯然這對於新手來說,直接閱讀彙編代碼門檻較高,所以一些逆向工具提供插件可以將一些函數恢復成僞代碼級別。

這裏寫圖片描述

相比C\C++這一類編譯運行類程序,依靠java虛擬機、.NET等運行的程序,由於所生成的字節碼(供虛擬機解釋運行)仍然具有高度抽象性,所以對這類程序的逆向得到的僞代碼可讀性更強,有時甚至接近與源代碼。但是在生成字節碼的過程中,變量名、函數名是丟失的,所以逆向出的僞代碼中這些名稱也是隨機命名的,從而給代碼的閱讀製造的一定障礙。而對於這類易反編譯的程序,爲了保護軟件不被逆向,通常採用代碼混淆技術,打亂其中的命名,加入干擾代碼來設置各種障礙。

至此,我們把程序恢復成了可讀代碼,如果你僅僅依靠閱讀這些代碼來梳理程序運行過程,這叫做“靜態調試”。與此對應的“動態調試”則是讓程序運行起來,更加直觀的觀察程序的運行過程。經常編寫程序的同學在debug時常常用到“斷點”,而在動態調試中,斷點起着很大的作用,否則程序將不會暫停下來讓你慢慢觀察各寄存器狀態。

Q:“斷點”是如何工作的?


x86系列處理器從8086開始就提供了一條專門用來支持調試的指令,即INT 3。簡單地說,這條指令的目的就是使CPU中斷(break)到調試器,以供調試者對執行現場進行各種分析。我們可以在想要觀察的指令處設置一個斷點,則程序會運行到該處後自動停下來;“單步調試”則是每條語句後面都會有INT3指令來阻斷程序的運行,而這些INT3是對用戶透明的,逆向工具並未將這些指令顯示出來。

這裏寫圖片描述

四、反彙編的多樣性

現在大多數程序是利用高級語言如C,C++,Delphi等進行編寫 ,然後再經過編譯鏈接,生成可被計算機系統直接執行的文件。不同的操作系統,不同的編程語言,反彙編出的代碼大相庭徑。反彙編工具如何選擇?彙編代碼如何分析?如何調試修改代碼?這些問題都會讓剛入門的新童鞋困惑。

下面我們簡單對比c++和c#程序反彙編後得到的代碼:
圖1

圖2

圖1是c++程序反彙編結果,圖2爲.net程序反彙編結果,兩者功能都只是打印一句話。C++以push指令將字符串壓入棧中,而.net以ldstr指令將字符串壓入棧中,調用打印函數結束後,.net反彙編代碼直接以ret指令返回結束,而c++反彙編代碼先平衡完棧,再執行retn指令返回結束。

由此可見,在反彙編過程中,我們確認好程序的編寫語言和運行環境,纔可選擇適當的工具來反彙編程序。在分析反彙編代碼時,如果熟悉高級語言的開發、運行過程及其反彙編指令,那更是事半功倍。

五、常用的軟件分析工具

對於軟件逆向分析,分爲靜態分析和動態分析,常用的軟件如下:

靜態分析工具

IDA Pro(Interactive Disassembler Professional )

IDA Pro是總部位於比利時列日市(Liège)的Hex-Rayd公司的一款產品。IDA 的主要目標之一,在於呈現儘可能接近源代碼的代碼,而且通過派生的變量和函數名稱來盡其所能地註釋生成的反彙編代碼,適用於三大主流操作 系統:Microsoft Windows.Mac OS X 和 Linux。IDA Pro提供了許多強大功能,例如函數的交叉引用查看、函數執行流程圖及僞代碼等,並且也有一定的動態調試功能。同時,IDA pro可以在windows、linux、ios下進行二進制程序的動態調試和動態附加,支持查看程序運行內存空間,設置內存斷點和硬件斷點。

IDA Pro是許多軟件安全專家和黑客所青睞的“神兵利器”。

這裏寫圖片描述

c32asm

c32asm 是款非常好用的反彙編程序,具有反彙編模式和十六進制編輯模式,能跟蹤exe文件的斷點,也可直接修改軟件內部代碼 ,提供輸入表、輸出表、參考字符、跳轉、調用、PE文件分析結果等顯示 ,提供彙編語句逐字節分析功能,有助於分析花指令等干擾代碼。
這裏寫圖片描述

Win32Dasm

Win32dasm可以將應用程序靜態反編譯爲WIN 32彙編代碼,利用Win32dasm我們可以對程序進行靜態分析,幫助快速找到程序的破解突破口。筆者下載的 Win32Dasm還可以附加到正在運行的進程,對進程進行動態調試,但如果原程序經過了加密變換處理或着是被EXE壓縮工具壓縮過,那麼用Win32dasm對程序進行反彙編就沒有任何意義了。
這裏寫圖片描述

VB Decompiler pro

VB Decompiler pro是一個用來反編譯VB編寫的程序的工具。VB Decompiler反編譯成功後,能夠修改VB窗體的屬性,查看函數過程等 ,VB Decompiler Pro 能反編譯Visual Basic 5.0/6.0的p-code形式的EXE, DLL 或 OCX文件。對native code形式的EXE, DLL或OCX文件,VB Decompiler Pro 也能給出反編譯線索。

這裏寫圖片描述

還有對.net程序和delphi程序的靜態反彙編分析工具,在以後的章節中會使用到,到時再詳細講解。

動態分析工具

Ollydbg

Ollydbg運行在windows平臺上,是 Ring 3級調試器,可以對程序進行動態調試和附加調試,支持對線程的調試同時還支持插件擴展功能, 它會分析函數過程、循環語句、選擇語句、表[tables]、常量、代碼中的字符串、欺騙性指令、API調用、函數中參數的數目,import表等等 ;支持調試標準動態鏈接庫(Dlls),目前已知 OllyDbg 可以識別 2300 多個 C 和 Windows API 中的常用函數及其使用的參數,是 Ring3級功能最強大的一款動態調試工具。
這裏寫圖片描述

Windbg

Windbg是Microsoft公司免費調試器調試集合中的GUI的調試器,支持Source和Assembly兩種模式的調試。Windbg不僅可以調試應用程序,還可以 對內核進行調試。結合Microsoft的Symbol Server,可以獲取系統符號文件,便於應用程序和內核的調試。Windbg支持的平臺包括X86、IA64、AMD64。Windbg 安裝空間小,具有圖形操作界面,但其最強大的地方是有豐富的調試指令。
這裏寫圖片描述

其它對.net,delphi等程序的動態調試工具在以後的章節中介紹。

輔助工具

系統監視工具:
Wireshark (免費軟件,網絡監視和包分析類軟件)
Outpost Firewall (共享軟件,使用hook技術的Windows防火牆)
ProcExp (免費軟件,強大的進程分析軟件)
FileMon (免費軟件,強大的文件讀寫監視軟件)
RegMon (免費軟件,強大的註冊表讀寫監視軟件)


反保護工具:

LordPE (Win32 PE文件修改,轉存工具)
ImportREC (Win32 PE文件結構修復軟件)
AIl versions ASPack unpacker (免費軟件,ASPack壓縮殼脫殼工具)
UnPECompact(免費軟件,PECompact壓縮殼脫殼工具)
UPX(自由軟件,UPX壓縮殼加殼和脫殼工具)


其它:

Hedit (共享軟件,16進制編輯器)
PEiD (免費較件,軟件信息和編寫語言分析工具)
以上只是常用的一些程序分析工具,還有很多工具這裏沒有提到,有興趣的讀者可以根據自身需求查找下載。

六、從hello world說起

爲了讓大家直觀地瞭解逆向的過程,我們就從大家最初學習編程時的hello world程序開始講解:

#include <stdio.h>

void main() 

{

    printf("hello world!\n");

}

這是我們編寫的打印hello world程序,是不是看起來很親切,接下來將編譯好的hello

world程序用IDA反彙編,生成的代碼如下圖:

這裏寫圖片描述

第一行main函數名前面的__cdecl,是C Declaration的縮寫(declaration,聲明),表示C語言默認的函數調用方法:所有參數從右到左依次入棧,這些參數由調用者清除 。還有__fastcall與__stdcall,三者都是調用約定(Calling convention),它決定以下內容:

1、函數參數的壓棧順序
2、由調用者還是被調用者把參數彈出棧
3、產生函數修飾名的方法

push offset Format是將參數壓入棧,在這裏就是講要打印的“hello world!\n”壓入棧,供printf函數使用,在反彙編程序代碼中,如果調用的函數有參數,都是先將函數的參數先用push指令壓入棧中,例如:add(int a,int b),調用add函數前,先將參數a和b壓入棧,根據 __cdecl調用規則,先push b,再push a,最後再調用add函數。
call ds:printf就是調用printf函數打印“hello world“字符。
add esp, 4是平衡棧,平衡掉剛纔壓入的函數參數。
xor eax, eax將eax寄存器清零。
retn 返回,程序執行結束。

這就是hello world程序的逆向代碼分析,只是舉一個簡單的例子,真正要逆向分析一個較大較複雜的程序還是有一定難度,需要更多的知識與經驗。

七、Crackme

crackme(通常簡稱CM)是用來測試程序設計人員的逆向工程技能的小程序。
KeygenMe、ReverseMe、UnpackMe,KeygenMe是要求別人做出程序對應的 keygen (序號產生器)。
ReverseMe 要求別人把它的算法做出逆向分析。
UnpackMe 是則是要求別人把它成功脫殼 。

分析這些程序都能提高個人的程序分析能力,這些程序都有各自側重的知識點。
下面就以一個驗證序列號的crackme小程序作爲例子進行破解,得到正確的序列號。
直接運行程序是這樣的
這裏寫圖片描述

開始破解程序,首先用IDA打開文件
這裏寫圖片描述

在函數(Function name)窗口中看見CWinApp,CCmdTarget更類,熟悉的同學已經知道該程序使用MFC編寫,結合自己的開發經驗,就能猜到獲取編輯框中的內容用的函數是GetDlgItemText(),定位到調用該函數的位置0×00401557。在之前有三個指令,
這裏寫圖片描述

在調用GetDlgItemText()之前有三個push指令,

.text:00401549 push 0Ah ; int //字符串最大長度
.text:0040154B lea edx, [ebp+String]
.text:0040154E push edx ; char * //字符串緩存區
.text:0040154F push 3E8h ; int //指向輸入框控件
.text:00401554 mov ecx, [ebp+var_20] ;

注意到剛纔彈框的提示內容“Incorrect try again!!”,可以在IDA字符串窗口中找到,定位到使用該字符串的位置
這裏寫圖片描述

細心的同學已經發現了,在上面loc_401585代碼段處有字符串比較(lstrcmpA),比較完成後有兩個分支,一個提示輸入正確“Correct way to go!!”,另一個提示輸入錯誤 “Incorrect try again!!”,結合上面獲取文本輸入框內容的代碼段信息可以判斷,lpString2和lpString1中有一個存儲正確的驗證碼,另一個存儲輸入的內容,接下來我們用兩種方法讓我們的驗證碼通過驗證。

獲取正確的驗證碼

在0040158D call ds:lstrcmpA處設置斷點,點擊Debugger->Start Process或按F9開始動態調試,在程序輸入框中隨便輸入一串字符,實驗中輸入的是‘1qaz2wsx’,然後點擊“Check”控件,程序停在我們設置的斷點處,然後查看寄存器ecx和edx中的值,所示如下:
這裏寫圖片描述

這裏寫圖片描述

如圖所示,ecx寄存器存放的是lpString2:‘’,edx寄存器存放的是lpString1:‘1qaz2wsx’,獲得正確驗證碼”’”’,接下來在程序中試驗一下:
這裏寫圖片描述

結果正確!

修改二進制代碼

修改PE文件,使輸入的內容顯示正確。在上一小節,程序比較完lpString1和lpString2有兩個分支,一個是正確輸入的提示框,另一個是錯誤輸入提示框。修改代碼跳轉,只要跳轉到彈出“Correct way to go!!”代碼段就可以了,結合代碼,當兩個字符串不同時會執行jnz short loc_4015AD指令,跳轉到loc_4015AD代碼段,將jnz指令改爲jz,可在兩個字符串不同時跳轉到“Correct way to go!!”代碼段。jnz的十六進制碼爲75,jz的十六進制碼爲74,只需將可執行程序中的75改爲74就可以。

通過IDA Pro查看十六進制文件窗口找到該跳轉指令
這裏寫圖片描述

用Hedit打開程序,找到該跳轉指令

這裏寫圖片描述

在二進制的文件中該跳轉指令在0×00001595處,而不是IDA顯示的0×00401595,發生了什麼?這涉及到PE文件內存映射方面的基礎知識,童鞋們可查閱相關資料。

將跳轉指令75修改爲74,保存修改後運行,隨意輸入一段字符串看運行結果:
這裏寫圖片描述
結果正確!那麼,如果輸入原來程序的驗證碼‘’,結果會是什麼?爲什麼會是這樣?


感謝FREEBUF網站

REFERENCE
1. 逆向工廠(一):從hello world開始
2. 逆向工廠(二):靜態分析技術

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章