我們以調用printf函數爲例子
找printf地址
#include "stdio.h"
int main()
{
printf("begin\n");
char *str="a=%d\n";
__asm{
mov eax,5
push eax
push str
call printf
add esp,8
}
return 0;
}
運行,看能不能輸出來
反彙編,找到printf的地址,將上面的程序更換爲:
#include "stdio.h"
int main()
{
printf("begin\n");
char *str="a=%d\n";
__asm{
mov eax,5
push eax
push str
mov eax,0x00401070
call eax
add esp,8
ret
}
return 0;
}
0x00401070 是我機子上printf的地址,將自己機子上的printf更換一下就行,還要在最後加一個ret,因爲執行完shellcode還要回到複製shellcode的代碼執行,接下來把上面彙編轉成shellcode形式,將上面的程序換成
#include "stdio.h"
char shellcode[]="\xB8\x05\x00\x00\x00\x50\xFF\x75\xFC\xB8\x70\x10\x40\x00\xFF\xD0\x83\xC4\x08\xc3";
int main()
{
printf("begin\n");
char *str="a=%d\n";
__asm{
lea eax,shellcode
push eax
call eax
pop eax
xor edx,edx
insect:mov bl,byte ptr ds:[eax+edx]
mov byte ptr ds:[eax+edx+20],bl
mov byte ptr ds:[eax+edx],0x90
inc edx
cmp edx,20
je ee
jmp insect
ee: add eax,20
push eax
call eax
pop eax
xor edx,edx
jmp insect
}
return 0;
}
shellcode就是上面彙編的機器碼,
shellcode長度是20,假設數據的地址是s,我們把數據複製到地址爲s+20處,原來的數據變爲0x90,表示數據曾經來過這裏,insect段是用來複制數據用到,複製了20次,剛剛好把shellcode複製完。
因爲shellcode相當於向下移動20位,所以我們要把eax加上20,還要把edx恢復成0,方便下次接着複製,然後去執行我們的shellcode,接着跳轉到insect段繼續執行,這是ee段乾的事。
inscet和ee段加起來是複製我們的shellcode到其他地方,然後去執行shellcode,然後再複製,循環下去
調試的時候找到shellcode位置,一步步調試能看見shellcode被複制,原來的轉成0x90
思路
- 把我們要執行的程序寫出來,轉成shellcode形式
- 計算出shellcode的長度
- 計算好shellcode每次移動的位置是多少,然後寫出複製程序(insect)
- 執行復制後的shellcode,接着在複製再執行,循環下去