引言:
第八届浙江省大学生网络与信息安全竞赛技能赛预赛Pwn方向题解,也是两个小时ak了预赛的三道Pwn赛题,感谢carry@ZJUCSA师傅的rop题解
pwn
rop @carry
观察代码,刚开始没发现问题,不存在栈溢出,但是题目又说了是ROP,肯定跟返回地址有关 在观察output的代码时,发现

jle是有符号是比较,所以我尝试了一下output(-1)会怎么样,结果打印出返回地址后就segment default,看到是output会将打印出来的清零,所以我们可以通过output去打印出一些栈信息来泄露libc,经过尝试,output(-15)会打印出libc地址 ,即_IO_2_1_stdout_的地址,于是通过这个来泄露libc,随后发现,-1是返回地址的位置,而input会根据目前有的来写入,所以我们写一个正常的返回地址回去,因为没开pie所以返回地址好找,随后就可以写 binsh_addr system_addr了,最后通过无意义的3个output将a1+72的值拉回去,

最后修改返回地址为pop_rdi_ret的返回地址,结果炸了,随后想到是栈指针没对齐,所以改成返回地址为ret_addr,后续的链子是pop_rdi_ret,binsh_addr,system_addr,拿下

payload如下
1 | from pwn import * |
bad_heap @Winegee
拿了个一血QwQ
glibc 2.35
一个常规增删改查,在add里有对申请出的堆块的限制

也就是申请出来的堆块不能在libc段,最开始想打tls_dtor_list劫持exit,但是试了试发现这个地址每次不固定,很难打
之后看了下这个lib段限制:

试了一下__environ在不在这个段内,发现不在,也就是这玩应根本没限制全,lib段没这么小,所以我们可以申请到__environ去泄露栈地址,最后打一个栈上的rop。
看一眼程序,有add,delete,show没有edit,而且free里面有一个uaf

申请八个堆块,free 七个,再free第八个,第八个就会掉入unsorted bin ,泄露libc。
常规打法house of botcake
先申请九个堆块,把1-7堆块free掉填满一条tcache bin链子,接着把8,9 free掉,8,9堆块就会都掉入unsorted bin并且发生合并,这时候9号堆块里面的指针什么的就会被清空,此时再申请一个堆块,tcache bin链子上就会出一个空位,再把9号堆块free掉,就会造成9号堆块同时在unsorted bin和tcache bin中,此时再申请一个稍微大一点的堆块就会发生unsorted bin的切割,就可以覆盖到9号堆块的fd指针,造成任意地址申请。
2.35下还需要提前泄露heap addr,这个free再add回来就可以泄露了。
本题exp如下:
1 | from pwn import * |
获取flag截图

one @Winegee
在edit里有一个off by one

我们可以利用这个off by one来修改下一个chunk的size位
程序没有给libc,先抓一下字符串看一下是用什么操作系统编译的

18.04的ubuntu猜测是2.27的libc,从glibc all in one当中抓出对应版本lib,开始打
本题思路如下:
- 先申请三个相同大小的堆块,接着edit堆块0,off by one到堆块1的size,使其堆块1的size可以包含堆块2
- 接着把堆块2 free掉,此时堆块2掉入tcachebin,再将堆块1 free掉,此时造成了chunk overlap
- 再次申请刚刚off by one的size大小的堆块,就可以修改到堆块2的fd指针,修改为tcache_pthread_struct结构体的地址
- 申请堆块2 size大小的堆块,劫持tcache_pthread_struct,接着伪造对应位置堆块的count,再将对应size的堆块free掉,使其掉入unsorted bin泄露libc
- 伪造对应size大小堆块的指针,使其指向free hook,申请出来劫持free hook为system,完成利用
本题exp如下:
1 | from pwn import * |
获取flag截图
