簡介
實驗的思路來自《0day安全:軟件漏洞技術分析》第一章。這次實驗的內容爲如何破解一個簡單的密碼驗證功能的exe文件。經過這次實驗能夠大致瞭解軟件破解的一些步驟,爲二進制漏洞的學習打下基礎認知。html
環境和工具
1.系統環境:windows 10
2.工具:IDA、OllyDBG、LordPE、uedit64
工具和實驗源碼下載:
連接:https://pan.baidu.com/s/1qh91yRkWP4oWW7QBe-2QGQ
提取碼:rgo7
windows
知識鋪墊
想了一下,仍是以爲把相關的知識點嵌入在實驗環節裏比較好,單獨寫在這翻來翻去也是比較麻煩的。安全
實驗
1.首先編寫一個簡單的密碼驗證的可執行文件。語言爲C++(其餘語言也能夠,只要能生成exe)。markdown
#include <stdio.h> #include <string.h> #define PASSWORD "123456" int verify_password(char *p){ int flag; flag = strcmp(p,PASSWORD); return flag; } int main(){ char password[10]; while(1){ printf("input your password:\n"); scanf("%s",password); if (verify_password(password)==0){ printf("TRUE\n"); }else{ printf("FALSE\n"); } } return 0; }
以後生成pwn.exe文件,點擊運行測試。函數
當輸入123456時返回TRUE表示密碼正確,其餘字符返回FALSE
工具
2.使用IDA對exe文件進行反編譯。File->open->選擇exe。以後點擊肯定,結果以下圖,會看到一串彙編代碼。學習
在左側一欄裏找到_main函數。(由於在本例中,判斷密碼是否正確的條件在main函數中,因此要先找_main,若是判斷語句寫在了verify_password方法中,則先找_verify_password,_verify_password就在_main上面)點擊空格鍵,能夠跳轉到相似流程圖的模式。
測試
即便不懂彙編語言也不影響理解,能夠看到在jnz short loc_4014CD
下面有兩個分支,分別對應着判斷爲true和false的操做。而jnz
的意思爲jump if not zero,非零跳轉,與其相反的是jz
:jumb if zero,零即跳轉。而是0仍是1是由前面的test eax, eax
來計算得出的,後面會討論這個問題。spa
3.咱們使用IDA的目的一是要找到判斷語句的跳轉代碼,二是要找到這個判斷語句所在的虛擬內存地址(VA)。按空格返回彙編代碼模式,能夠看到jnz short loc_4014CD
的虛擬內存爲0x004014BD(以下圖)。
要注意的是,這個地址是虛擬內存內的地址,若是隻是在內存裏將jnz short loc_4014CD
改成jz short loc_4014CD
,則僅僅是運行的進程被更改,存在硬盤的程序是沒有發生變化的。(操做系統知識點:當一個程序運行時,會建立一個進程,並將自身的代碼放進程內而後在內存中運行。)
操作系統
4.接下來就分別演示經過修改內存和修改硬盤內程序兩種方式達到實驗目的。(若是僅僅是想到的密碼的話,直接查看exe內的字符串就能看到123456,但這不是咱們學習的目的。)
先來嘗試內存破解。要使用到OllyDBG工具。打開,file->open->pwn.exe文件。此時也打開了pwn.exe文件控制檯,不要關閉,關閉則pwn.exe進程結束。
按ctrl+G鍵,輸入以前咱們獲得的jnz short loc_4014CD
的VA地址,即0x004014BD。
按F2添加斷點,以後按F9運行,在控制檯輸入錯誤的密碼,回車。此時在右上角一欄能夠看到以下(前提是你的環境和代碼跟本例是同樣的,即便不同其實思路也是同樣):
回到咱們以前提到的test eax, eax
,eax就是一個寄存器,此時它存的值爲00000001,test的意思就是邏輯與操做,並將結果存在ZF(零標誌位)中,即00000001&00000001=1,運算結果爲1,非零,那麼ZF=0,然後面的jnz
是結果不爲0則跳轉,由於ZF=0表示運算結果不爲0,因此跳轉。好吧,我認可寫這篇文章整理思路的時候繞進去了╭(╯^╰)╮,若是隻是爲了好理解能夠理解成test
運算後結果不爲0,因此jnz
跳轉,這樣也是能夠,但總有種歪打正着的感受。(你可能想到了第二層,可是我卻已經第五層了,就是這種感受。)
補充:若是你一步一步執行,會發現 EAX寄存器的值一開始是咱們輸入的‘asd’這個錯誤密碼,後來在_strcmp方法中被置爲了00000001。_strcmp就是代碼裏的 strcmp()方法。
如今咱們已經知道接下來要發生的事情了,jnz
跳轉到FALSE的語句上。其實在OllyDBG已經有相關的提示了。如圖左下角Jump is taken,下面是跳轉的地址,爲pwn進程的0x004014CD的VA地址。
此時咱們繼續按F9放行,查看控制檯。控制檯返回了FALSE,咱們的目的是要返回TRUE。
首先。將jnz
改爲jz
,會發現系統將jz
改爲了je
,可是不影響,由於兩個方法功能上是同樣的。以下圖,要注意前面的74 0E是對應的16進制機器語言。改完以後,在控制檯輸入和以前同樣的密碼即asd,再次按F9放行程序。
結果顯示這次爲TRUE。
5.上面那個是內存修改的方式,此次是直接修改exe文件內的機器語言來實現咱們的目的。在這以前,咱們須要計算jnz
這個操做命令在exe的位置。以前咱們已經獲得了運行時它的進程在內存的虛擬地址,即0x004014CD。下面要補充一些知識點,對PE文件格式在硬盤和內存比較熟悉的同窗能夠直接跳過。
以下圖,windows 10操做系統下,內存塊是以0x00001000爲單位分割的,而硬盤是以0x00000400爲單位進行分割的。並且代碼是存放在exe文件中.text段內,也就是說咱們所須要的 jnz
就存放在.text中。如今已知 jnz
在虛擬內存的地址爲0x004014CD,而exe文件的虛擬地址基址均爲0x00400000,若是要計算出在硬盤的格式,應爲0x004014CD-0x00400000-虛擬內存地址文件頭大小 +硬盤地址文件頭大小
如今咱們須要虛擬內存地址文件頭的大小和硬盤地址文件頭的大小,咱們能夠用LordPE工具來查看。PE Editor -> Sections。如圖能夠看到咱們所須要的兩個數據。第一個是虛擬內存的,第二個是硬盤的。
因而就能夠計算出硬盤內的jnz
地址。
0x004014CD-0x00400000-0x00001000+0x00000400=0x000008BD
得出地址爲0x000008BD,接下來使用uedit64工具進行16進制編輯,按Ctrl+G,輸入剛剛算出的地址。
根據以前的測試,咱們知道jnz short loc_4014CD
的16進制機器語言對應的是75 0E,再看看上圖,說明咱們的計算沒有錯誤,將75改成74(74就是jz
),保存。
測試一下,成功。
總結
1.瞭解了IDA、OllyDBG、LordPE、uedit64工具的簡單實用
2.初步認識了軟解破解技術的思路。
3.掌握了PE文件格式在內存和硬盤的計算方法。