標籤:
1.下面這段代碼啟動並執行結果是什嗎?
#include <stdio.h>
#include <Windows.h>
DWORD dz=0;
DWORD dz1=0;
void fun1()
{
__asm
{
mov eax, dz
push eax
ret
}
}
void main()
{
HMODULE h = GetModuleHandle(NULL);
dz1= dz =(DWORD)h;
dz+=0x1062;//0x1062為 printf("2222\n")相對於程式碼片段基址的位移
dz1+=0x0;
__asm
{
call fun1
}
printf("1111\n");
printf("2222\n");
}
不仔細思考,運行結果為:
2222
實際運行結果:
2222
1111
2222
為什麼會這樣,分析下原因:
1. call fun1語句執行後: printf("1111\n") 的地址壓入棧.
2. fun1函數執行後: ret指令改變了eip, eip = dz, 轉到main函數裡面執行 printf("2222\n")
3. main函數執行ret後: 取出printf("1111\n")地址賦給了eip, 導致程式又跳到了printf("1111\n")處執行
2.把fun1函數改進下,使運行結果為:
2222
實現代碼:
#include <stdio.h>
#include <Windows.h>
DWORD dz=0;
DWORD dz1=0;
void fun1()
{
__asm
{
add esp,8 //前面預設執行了push eip, push ebp, 儲存main ret的地址記憶體就在esp+8的位置
mov eax, dz1
push eax //把printf("1111\n")的地址替換為 main 的‘}‘
sub esp,4 //還原棧指標
mov eax, dz
push eax
ret
}
}
void main()
{
HMODULE h = GetModuleHandle(NULL);
dz1= dz =(DWORD)h;
dz+=0x1077; //0x1062為 printf("2222\n")相對於程式碼片段基址的位移
dz1+=0x1085;//0x1085為 main函數的‘}‘ 相對於程式碼片段基址的位移
__asm
{
call fun1
}
printf("1111\n");
printf("2222\n");
}
這樣 main函數執行ret後: eip= ‘}‘ 地方的地址, 程式結束,運行結果為:
2222
組合語言11堆棧修改