pwn
imgstore
1 | unsigned __int64 sell_book() |
程序中存在格式化字符串漏洞,和一个栈溢出漏洞,泄露地址后 直接改printf函数的返回地址然后打 rop就好了,就不需要任意地址写两次满足上面的约束,任意地址写的话,直接清空两个位置好像也行,/dev/urandom是真随机数,直接清空的话甚至不需要泄露
exp
1 | from pwn import * |
ropity
1 | .text:0000000000401136 ; int __cdecl main(int argc, const char **argv, const char **envp) |
真的是很巧妙的构造,main函数中存在一个栈溢出,是fgets函数,然后有一个printfile函数,通过open 和 sendfile将一个文件的内容打印出来,printfile在使用前必须控制rdi寄存器才能printfile成功,由于高版本glibc csu函数变成了动态链接,所以以ret结尾能控制寄存器的gadget寥寥无几,能控制rdi寄存器为我想要的值的gadget基本上没有
1 | lhj@lhj-virtual-machine:~/Desktop/ImaginaryCTF/pwn/ropity$ ROPgadget --binary vuln |
但是,细看会发现 fgets的rdi是可控的 因为取栈上的变量这个过程,实际上是通过 rbp - 一个正整数偏移去取的,如果能控制rbp,那 rdi的值就是可控的,如果将fgets的got修改成printfile,然后保证 rbp - 0x8的值是 ./flag字符串的地址,gadget这个问题不就解决了吗。
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
首先需要栈迁移把栈迁移到已知 的地址上面的条件才能满足,第一次fgets 将rbp覆盖成 fgets_got + 0x8,然后调用 fgets,由于s的计算是通过rbp - 0x8,所以能直接将fgets_got覆盖,覆盖成printfile,然后再控制rbp,保证rbp - 0x8的值是flag最后调用fgets就好了
1 | from pwn import * |
onewrite
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
有一次任意地址写大量数据的原语,还有libc的地址,看官方wp发现有个叫setcontent32的项目,只需要一次任意地址写的原语和知道libc的基地址,就可以通过这个项目生成payload去getshell https://hackmd.io/@pepsipu/SyqPbk94a
exp
1 | from pwn import * |
fermat
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
有一个栈溢出,可以通过格式化字符串去泄露libc地址,然后再配合libc start main的magic gadget重启main函数,然后用libc中的gadget打rop
exp
1 | from pwn import * |
ictf-band
1 | __int64 sub_2151() |
程序的逻辑很简单,在ext函数中存在一个溢出,不过程序有pie,细看 ext会发现在输出的时候%s可以用来泄露栈上的数据,所以思路是泄露elf基地址后,利用残留的rdi寄存器 puts泄露libc地址,然后再打system binsh
exp
1 | from pwn import * |
bopity
和ropity逻辑一样
hopper
1 | int __cdecl __noreturn main(int argc, const char **argv, const char **envp) |
第一次做stl迭代器安全相关的题
漏洞出在clean函数这边,这里的逻辑其实是 在循环chunklist.earse(chunklist.being() + i) sizelist.earse(list.being() + i) ,如果存在连续的size == -1的堆块,第一次earse的时候 容器的大小发生了变化,所以earse后的i就不是 earse前的 i了。是 i + 1,然后alloc的时候,输入size -1是能正常的push_back到sizelist里面的,所以可以通过这个漏洞去构造出uaf
1 | unsigned __int64 __fastcall clean(__int64 a1, __int64 a2) |
首先是glibc 2.35 构造任意地址写的原语需要泄露堆地址去绕开safe link, 泄露堆地址和 libc的地址,通过unsortedbin泄露libc的地址,可以直接申请一个很大的chunk然后free掉,这样就直接进unsortedbin了,不用填满tcache.
因为cout是读到换行就不读了,所以不能通过fastbin double free直接去泄露environ的值,但?直接写vector成员指针的值也可以?覆盖vector[0] 为 environ的地址然后show就能泄露栈地址了,泄露栈地址后再fastbin double free一次写返回地址然后打rop去getshell
exp
1 | from pwn import * |