2-21 – BFnote
这题很秀,我觉得有必要记录下来
简单分析一下程序不难发现程序存在很明显的栈溢出,但是因为开启了canary,得想办法绕过;还有在malloc(size)的时候,size大小不限
不仔细看还发现不了,下方还存在一个下标溢出,v4一开始被初始化后,在循环中只有i被重新赋值,而v4在后面又用到了
这道题就只有这两个漏洞点
1 | sub_80486F7(); |
思路
对于这个canary的绕过,需要用到TLS,不过需要用到malloc(size)大小不限这个地方
canary 这个值是怎么来的呢,在linux 下,有一种线程局部存储(Thread Local Storage)机制,简称为TLS。它主要存储着一个线程的一些局部变量,它的结构体如下
1 | typedef struct |
在汇编中:
1 | mov eax, large gs:14h |
而gs寄存器就指向这个结构体,结构体里的stack_guard值就是canary 的值,所以只要能篡改结构体里stack_guard的值就可以绕过canary了
一、需要确定这个结构体在内存中的位置,在gdb中,search -t dword (canary)
可以搜索到canary 的地址
二、如何修改这个值,上面提到了malloc(size)中对size的大小没有限制,所以可以malloc一个很大的size,这样系统就会调用mmap来分配内存(size >= 0x20000) ,再结合v4的下标溢出,可以精确地修改canary的值
三、栈溢出后的事,再看一下这个程序中用到的输出函数你会发现,用的都是fwrite,fprintf,这样我们很验证找到合适的gadget来控制参数来link地址,所以最后还是决定用dl-runtime-resolve来执行system(“/bin/sh”)
exp:
1 | #-*-coding:utf-8-*- |
2-22 – borrowstack
1 | Arch: amd64-64-little |
没有开canary,且溢出0x10字节,只能覆盖rbp和写一条gadget,后面还有往bss段写入数据 ,很明显是栈迁移了,但是我在最后执行system(“/bin/sh”)却一直报错,最后用的onegadget才成功,不过听说迁移两次就可以了
exp:
1 | #coding:utf-8 |
2-22 – excited
1 | if ( v1 < 0 || v1 > 10 || !ptr[v1] ) |
delete功能中存在uaf,而且程序一开始就把flag读进来了
1 | unsigned __int64 sub_400896() |
所以只需要构造double free,然后把0x6020a8
插进去之后 show 就行了
1 | #coding:utf-8 |
interested
同样的free完没清空指针,但是堆块的大小被限定在fastbin范围
思路,先通过UAF link堆地址,再伪造堆的大小,free后进入unsotredbin link出main_arena,最后UAF到malloc_hook-0x23覆写malloc_hook为onegadget
exp:
1 | #coding:utf-8 |
2-23 – signin
glibc 版本2.29,add,del,edit三个功能,还有一个backdoor
add : addcnt = 7,所以可以申请8个大小的0x80的堆块
1 | unsigned __int64 add() |
del,free后指针未清空,UAF
1 | unsigned __int64 del() |
edit : cnt=0,所以该功能只能用一次
1 | unsigned __int64 edit() |
backdoor : 在判断ptr前调用了calloc(1,0x70),这是关键
1 | void __noreturn backdoor() |
先明确几个问题,calloc虽然跟malloc相似,但是它是不会使用tecache bin 的,所以应该考虑fastbin attack,而且
_int_malloc中,从fastbin bin取下一块后,如果fastbin还有剩余,而且对应的teache 没满的话,就把它放到对应大小的teache
所以如果伪造了fastbin bin,我们就可以往chunk+0x18处写入teache
这时候把teache的一块申请出来再调用calloc,就满足fastbin还剩余,teache未满,调用teache_put
exp:
1 | #coding:utf-8 |