下面我們以Release版本為例,解剖程序。
將exe反匯編得到關(guān)鍵代碼如下:
函數(shù)ShowComputerName:
主函數(shù)main:
我們知道函數(shù)調(diào)用是采用堆棧方式,那么CPU是怎么工作的呢?
在WindowsXP/2000操作系統(tǒng)下,通過大量的匯編代碼我們可以看到,函數(shù)調(diào)用的參數(shù)傳遞是采用堆棧進行。
何故?
原因是我們使用的個人計算機一般都是采用x86系列CPU,由于可用通用寄存器非常少的緣故,只能采用堆棧進行。而作者工作使用的PowerPC系列CPU,由于有32個通用寄存器,所以函數(shù)調(diào)用的參數(shù)都采用寄存器R3、R4……來完成。據(jù)說蘋果機采用PowerPC應(yīng)該就屬于按照寄存器傳遞的方式,但作者沒有蘋果機,有大家可以自己看看。
下面還是回歸正題,這個代碼怎么跑呢?
假定代碼運行到00401080處,ESP指針為00130000
那么堆棧將如何發(fā)展呢?
| ………… | 低地址
+------------------------------+
| |
+------------------------------+ 高地址 ESP 00130000
完成push 405030h后,405030h被壓棧,ESP指針上移。
| ………… |
+------------------------------+ ESP 0012FFFC
| 00405030h |
+------------------------------+
完成call 00401030后,也就是開始調(diào)用函數(shù)ShowComputerName。
函數(shù)調(diào)用后,返回main主函數(shù)的 EIP地址0040108A被壓棧,同時ESP指針上移。這個壓棧數(shù)值就是我們要利用的溢出攻擊目的。
| ………… |
+------------------------------+ ESP 0012FFF8
| 0040108Ah |
+------------------------------+
| 00405030h |
+------------------------------+
下面我們就來到溢出函數(shù)部分,我們可以知道現(xiàn)在ESP是0012FFF8,所以mov ecx,dword ptr [esp+4]就是將壓棧的數(shù)組首地址取出來放置到寄存器ecx。
接下來sub esp,0Ch,是預(yù)留局部變量pucComputerName的空間,剛好12個字節(jié)。ESP上移12個字節(jié),就是pucComputerName首地址。
| ………… |
+------------------------------+ ESP 0012FFEC
| pucComputerName |
| 的空間 |
| |
+------------------------------+
| 0040108Ah |
+------------------------------+
| 00405030h |
+------------------------------+
再后lea eax,[esp],將esp的值賦值給eax,現(xiàn)在eax指向pucComputerName的首地址,exc指向全局變量g_aucName的首地址
0040103B: 50 push eax
0040103C: 51 push ecx
eax和ecx被壓棧給函數(shù)GetName調(diào)用時候使用,這樣棧空間圖演變?yōu)椋?/font>
| ………… |
+------------------------------+ ESP 0012FFE4
| 00405030h |
+------------------------------+
| 0012FFECh |
+------------------------------+
| pucComputerName |
| 的空間 |
| |
+------------------------------+
| 0040108Ah |
+------------------------------+
| 00405030h |
+------------------------------+
接下來調(diào)用函數(shù)GetName,返回函數(shù)ShowComputerName的EIP指針00401042已經(jīng)被壓棧,ESP再次上移,??臻g圖演變?yōu)椋?br>
| ………… |
+------------------------------+ ESP 0012FFE0
| 00401042h |
+------------------------------+
| 00405030h |
+------------------------------+
| 0012FFECh |
+------------------------------+
| pucComputerName |
| 的空間 |
| |
+------------------------------+
| 0040108Ah |
+------------------------------+
| 00405030h |
+------------------------------+
接下來在函數(shù)GetName就是復(fù)制拷貝了,也就是將g_aucName的內(nèi)容如實全部拷貝到局部變量pucComputerName所在地址,由于局部變量使用的是??臻g,這樣我們main函數(shù)返回的EIP就被我們無情改寫得面目全非了,欺騙了CPU,目的達到。
拷貝完成暫未返回函數(shù)ShowComputerName的??臻g狀態(tài)。
| ………… |
+------------------------------+ ESP 0012FFE0
| 00401042h |
+------------------------------+
| 00405030h |
+------------------------------+
| 0012FFECh |
+------------------------------+
| 'H','e','l','l' |
| 'o','W','o','r' |
| 'l','d','!','\0' |
+------------------------------+
| 00401072h |
+------------------------------+
| 0x6A,0x00,0x68,0x30, |
+------------------------------+
| 0x50,0x40,0x00,0x68, |
+------------------------------+
| 0x30,0x50,0x40,0x00, |
+------------------------------+
| 0x6A,0x00,0xFF,0x15, |
+------------------------------+
| 0x90,0x40,0x40,0x00, |
+------------------------------+
| 0x6A,0x00,0xFF,0x15, |
+------------------------------+
| 0x48,0x40,0x40,0x00, |
+------------------------------+
由于GetName調(diào)用關(guān)系的保留的EIP指針和ESP現(xiàn)在指針都未被破壞,因此ret能正常返回,執(zhí)行過后。
EIP被置為00401042h,ESP下移為0012FFE4
接下來我們要執(zhí)行00401042所在指令了,也就是add esp,14h,為什么是14h呢,原因是我們不是push了2個函數(shù)參數(shù)么?此處也需要“彈出”,此處非pop彈出,是編譯器優(yōu)化結(jié)果,直接該esp最快、最直接。14h=0Ch+08h
這樣我們的ESP指針就下移到0012FFF8,此時你看看此處返回地址是什么?已經(jīng)被我們改寫為jmp esp指令所在地址,這樣執(zhí)行ret后,EIP被置為00401072h,ESP下移為0012FFFC。
EIP即將執(zhí)行的指令是jmp esp,而ESP 所在地址就是我們溢出攻擊指令。下面發(fā)生了什么相信大家都明白了,那就是我們攻擊自己溢出漏洞的程序部分被激活。
由于時間太晚了,就寫到這里了。
編寫該攻擊程序心得體會,請看下篇。^_^
聯(lián)系客服