0x01coolcode
解法一
16的一道pwn题,开了sandbox:
禁用open,但fstat函数系统调用号为5,想到利用retf控制cs修改运行模式为32位汇编(open在32位下调用号正好为5)
同时看到堆可执行:
0x1607000 0x1628000 rwxp 21000 0 [heap]
于是可以在堆上部shellcode,但输入堆的时候有check只能是数字和大写字母,且长度为0x20,因此一般的shellcode转化工具因太长无法使用,只能手撸。
能用的只能是部分xor和pop/push这样的指令,可以先构造执行read,之后的输入就没check的限制。
1 | sc = asm(''' |
利用xor和’M2WND’构造出syscall执行read(0,堆地址,size)
ruan师傅
哦对了,跳到堆上执行的方法是利用idx为负数(-24)改write的got为堆地址,利用show()函数触发到堆上执行,之后执行了一次read会便可持续往下部署sellcode但要把控好距离。具体看脚本+调试:
read(用于之后的shellcode写入)->mmap(申请映射空间用于读入flag)->open(利用retfq控制程序跳到映射空间执行32为汇编)->read->write
exp:
1 | from pwn import * |
解法二:
这次我们先覆盖exit的got表为ret来绕过check,这样我们就可以直接在堆上写shellcode,然后覆盖free的got表,利用dele触发shellcode。
shellcode的编写过程就是先执行read将之后的shellcode读到bss段,之后retfq切换32位汇编并跳到bss上继续执行open_x86的操作,最后read and write读出flag。
要注意的几点:
open函数的参数传递:
eax = 0x05 系统调用号、ebx = filename 文件名、ecx = flags 置零即可、edx = mode 置零即可。
然后就是再构造文件名’flag’的时候由于是32的模式,要注意错位的问题。
还有就是注意理解retfq执行的操作为pop rip,pop cs(cs = 0x23代表32位模式,cs = 0x33代表64位模式),所以要注意栈中的参数位置。retfq跳转过去的时候程序已经切换成了32位模式,要注意平衡好esp的地址
最后还得回到64位模式下调用,再调用一次retfq。
1 | from pwn import * |
0x02 snake
程序是是一个贪吃蛇,当蛇死后的leave words存在堆溢出,正好可以伪造下一个堆的size。
利用思路:
首先既然可以伪造size就想办法构造overlap,先将存放name的chunk0删除,申请新的chunk0大小为0x68(为之后的fastbin attack)准备。
之后利用scanf输入很长的字符串触发malloc_consolidate()作用为:
1、检查fastbin是否初始化,如果未初始化,则进行初始化。
2、如果fastbin初始化,则按照一定的顺序合并fastbin中的chunk放入unsorted bin中
这样一来放入unsorted bin的堆内就存在执行main_arena的指针,然后将它申请回来利用get_name+restart泄露libc
之后再leave words时候修改chunk1(也就是最开始的chunk0)的size为0x91,造成chunk0和chunk1的overlop。
最后fastbin attack改malloc_hook到one_gadget拿shell。
exp:
1 | from pwn import * |