利用函數調用棧平衡原理實現溢出調用(有點類似於棧溢出,只不過這裡是直接修改,也可以命使用溢出方式實現)============================================================================================#include <stdio.h>#include <string.h>unsigned int oldEbpAddress = 0;unsigned int oldRetAddress = 0;typedef void (*pf)();//這裡只能修複到繼續返回main執行,但是在main函數結束時棧被破壞,報異常void fun2(){//記錄老EBP地址__asm mov [oldEbpAddress],ebp//通過老EBP找出函數返回地址,並給它設定原函數返回地址*((unsigned int*)(oldEbpAddress + 4)) = oldRetAddress;printf("fun2\n");}//這裡採用naked模式編寫fun2完美實現棧修複,可以與上面的進行比較看效果char *str = "fun2\n";void __declspec(naked) fun2(){__asm {//壓入函數返回地址push oldRetAddress//調用printf函數push offset strcall dword ptr printf//注意這裡的dword ptradd esp, 4//自己維護棧平衡ret//函數返回}}void fun(){//記錄老EBP地址__asm mov [oldEbpAddress],ebp//通過老EBP記錄下函數返回地址,在fun2中再使用oldRetAddress = *((unsigned int*)(oldEbpAddress + 4));//通過老EBP修改函數返回地址為fun2函數首地址*((unsigned int*)(oldEbpAddress + 4)) = (unsigned int)(pf)fun2;printf("fun\n");}//說明:這裡我們沒能調用函數fun2,但是由於我們在fun函數中對返回地址做了一系列修改讓fun2也得到了執行機會,//同時在fun2中對棧也做了一個簡單處理能返回main函數繼續執行int main(){printf("main\n");fun();printf("main next\n");getchar();}=====================================================利用函數調用棧平衡原理實現棧回溯=====================================================#include <stdio.h>#include <Windows.h>int fun3(){unsigned int ebpAddress;unsigned int ebpPreviousAddress;printf("----------------fun3------------------\n");__asm mov [ebpAddress],ebp //得到當前函數EBPebpPreviousAddress = *((unsigned int*)ebpAddress); //EBP地址中儲存的值為來自調用函數的EBP值printf("0x%08X\n", ebpPreviousAddress);//迴圈執行上面的步驟while(1){__try{ebpAddress = ebpPreviousAddress;ebpPreviousAddress = *((unsigned int*)ebpAddress);printf("0x%08X\n", ebpPreviousAddress);}__except(EXCEPTION_EXECUTE_HANDLER){//這裡一直回溯到無法回溯時產生異常退出回溯break;}}return 0;}int fun2(){printf("----------------fun2------------------\n");fun3();return 0;}int fun1(){printf("----------------fun1------------------\n");fun2();return 0;}int _tmain(int argc, _TCHAR* argv[]){fun1();getchar();return 0;}