浏览器
小型CMS漏洞复现审计
2024年网鼎杯初赛和半决赛部分题解--PWN
本文档使用 MrDoc 发布
-
+
首页
2024年网鼎杯初赛和半决赛部分题解--PWN
# 2024年网鼎杯初赛和半决赛部分题解--PWN 原创 Undefin3d团队 [Undefin3d安全团队](javascript:void(0);)  Undefin3d安全团队 一切皆有可能 18篇原创内容 _2024年12月30日 14:29_ _江西_ # 2024年网鼎杯青龙组--PWN01 开始有一个登录的函数,然后只要拿到用户名和密码就可以进入 vuln函数存在两个字节的溢出,还将buf的地址给泄露出来了 #  还有给了我们后门函数和/bin/sh字符串   完整exp ``` from pwn import * ``` 2024年网鼎杯青龙组--PWN04 代码审计,发现有一个用户名和密码的验证  发现他是在本地去读取的,所以我们需要爆破用户名和密码,然后我们进入判断函数,发现他是一个一个字符判断的,如果发现字符不一样,我们可以由此当判断依据,爆破用户名  爆破脚本,爆破密码也是同理 ``` password='' ``` 后边就是一个菜单题了,我们继续看  我们进入第一个函数,发现是一个添加堆块的函数,限制了只能申请0xf个堆块,大小要小于0x300,但是他会对我们输入的数据进行加密 我们进入加密函数,发现是一个 RC4 算法(ai告诉我的),我们直接用ai给我什么解密脚本,发现的加密算法就是解密算法  解密算法 ``` def ksa(key): ``` 进入第二函数,是一个打印函数,但是会给我打印出来的东西进行加密 第三个函数,是一个free函数,存在uaf漏洞,会对我们free的内容进行加密  第四个函数edit函数,同样会机密我们的内容  并且还开了沙箱,但是libc是2.27,所以我们直接用setcontext+53进行orw的编写  利用思路: 1、首先通过申请7个堆块,填满teacher bin,然后在申请一个,free掉进入unsortbin,泄露libc 2、,然后就通过uaf劫持free\_hook为setcontext+53,进行orw的编写 首先我们泄露libc,由于我们打印的数据是加密的,所以我们要接受所有的数据进行解密,然后拿到libc的地址,然后我们再通过之前的free掉的堆块泄露,heap的地址 ``` for i in range(8): ``` 劫持free\_hook为setcontext+53,由于我们之前就free掉了很多堆块,我们直接找到6个堆块改为free\_hook,就可劫持了 ``` edit(6,rc4_decrypt(key,p64(libc.sym['__free_hook']))) ``` 最后就可以编写我们orw了,我们这里可以用pwntools提供的frame结构体来控制相应的结构体 ``` 0x7f4b45a35a75 <setcontext+53> mov rsp,qword ptr [rdi Oxa0] ``` ``` pop_rdi=0x000000000002164f+libc.address #: pop rdi ; ret ``` 由于我们劫持的rsp为orw的地址,但是当他push rcx的时候会将rsp-0x8地方修改,所以我们没法将"./flag\\x00\\x00"写在开头  而且还有一个问题就是,当我想在填两个pop rdi进行隔开的时候,就会没法将我们需要的内容填写完整,我猜测他的加密应该是有对齐吧(如有大神知道可以教教我) ``` frame=SigreturnFrame() ```  完整exp ``` from pwn import * ``` # 2024年网鼎杯白虎组--PWN01 # 1、分析伪代码,发现是一个菜单题  add函数,一个堆块的申请  delet函数  edit函数就是漏洞点,他会在任意地址输入0xA2C2A,但是程序是一个64位,所以他会将这个数据填零不存,就是使得任意地址中的数末尾为零  show函数就是打印数据的  利用思路: 1、我们通过unsortbin的遗留的指针泄露libc和heap地址 2、然后我们在将通过edit函数进行任意地址修改 泄露heap地址和libc地址 ``` add(0x410)#0 ``` 然后我们在构建一个可以末尾抹零的地址,将free\_hook链上 ``` add(0x108,'a'*0x+p64(libc.sym['__free_hook']))#6 ``` 我们将a0改为00,这样我们就可以将free\_hook申请出来了  通过edit修改 ``` edit(p64(heap+0xeb0-0x8+0x5)) ```  然后我们就可以申请三次将free\_hook申请出来然后将其修改为system函数 ``` add(0x100) ``` 完整的exp ``` from pwn import * ``` 2024网鼎杯玄武组--PWN2\[进程调试\] 代码审计,我们发现了三个函数,并且去除了符号表  我们进入第一个函数,我们猜测是一个初始化的函数  进入第二函数,我们通过分析将函数名自己填上,发现他开了一个子进程去执行了read函数和puts函数,并且还是要等主进程结束后才会调用  查看第三个函数,发现使用输入的函数调用,但是没有任何的溢出或是其他漏洞,但是他会泄露一个地址,我们测试猜测他泄露的应该是一个canary的值  那我们就进入gdb调试,查看他的整个程序的调用过程,这里我们的得用到gdb中调试子进程的命令,然后在设置断点,主进程和子进程都要设置 ``` set follow-fork-mode child(使程序进入子进程) ```  然后我们直接调试,他会进入第三个函数,调用read函数,进行读入,然后我们在再进入子进程 ``` info inferiors(查询正在调试的进程,gdb会为他们分配唯一的Num号,其中前面带’*'号的就是正在调试的进程) ```  然后我们跟进调试会发现,当我们调用exit的时候会有一个判断然后进行跳转  跳转的判断值使我们之前输入的数值,我们直接发现1进行绕过  ``` ru('gift: ') ```  然后我们就会发现一个隐藏的函数,我们直接通过地址在ida中进行搜索定位函数,查看函数的逻辑。 分析他会先执行完主进程,才会进入子进程,而且还是一直循环操作  我们查看汇编会发现,在执行完子进程的函数后会跳转跳转到一个新的函数,然后判断是个为11111111,如果相同这会调用40191A函数,然后在判断canary之后相等,最后到返回地址  我们直接通过gdb进行调试,我们通过测试,我们一次性发送我们需要的数据,才有可能覆盖到返回的地址 ``` sa("once again?","c"*256+p32(0x11111111)*64+p64(canary)*4) ```  第二次进入子进程然后进行绕过就可以 ``` sa("once again?",'a'*256+p32(0x11111111)*64+p64(canary)*4) ```  然后我们进行shellcode的编写,编写rop链进行getshell ``` #编写read函数,进行/bin/sh\x00的输入 ``` 完整的exp ``` #coding:utf-8 ``` 2024网鼎杯半决赛pwn 码审计,根据题目的描述是模拟了一个扑克牌的洗牌机制  首先进入第一个函数,是一个洗牌初始化的函数,然后将结构体给定义出来   进入第二个函数,我们发现漏洞点realloc函数,因为我们申请的chunk大小是由我们自己定义的  这是我看到一位大神的解释,我感觉解释的很到位 <table><tbody><tr><td data-colwidth="576" valign="top"><section><span leaf="">realloc(realloc_ptr, size)有两个参数,并且在特定参数有特定效果</span></section><p style="margin: 0;padding: 0;min-height: 24px;"><strong><span leaf="">size == 0 ,这个时候等同于free。也就是free(realloc_ptr),并且返回空指针。即没有uaf</span></strong></p><p style="margin: 0;padding: 0;min-height: 24px;"><strong><span leaf="">realloc_ptr == 0 && size > 0 , 这个时候等同于malloc,即malloc(size)</span></strong></p><p style="margin: 0;padding: 0;min-height: 24px;"><strong><span leaf="">malloc_usable_size(realloc_ptr) >= size, 这个时候会把多余的内存释放掉,并返回原来的指针</span></strong></p><p style="margin: 0;padding: 0;min-height: 24px;"><strong><span leaf="">malloc_usable_size(realloc_ptr) < szie, 这个时候才是malloc一块更大的内存,将原来的内容复制过去,再将原来的chunk给free掉</span></strong></p></td></tr></tbody></table> 然后第三个选项就是调用一个结构体,我们通过gdb调入可以看到,就是将我们初始化生成的数据体给打印出来,可以用来泄露我们的libc的地址   后面两个函数感觉没有啥用,主要是我也没有看懂........ 首先我通过申请一个大于0x410的chunk,然后通过realloc进行free,就可以将这个chunk放入unsortbin中,从而泄露libc的地址,然后我们也可以将malloc给消耗掉   然后我们将size的大小改为0,realloc的功能就会像free   之后我们就可以泄露libc了,我们调用第三个函数进行打印 ``` cmd(3) ```  然后我们要进行初始化不然我们没法再申请chunk了,因为main\_aeran链上的是top\_chunk地址,进入realloc函数中会发现,r12相加后会变成一个非法地址   然后我们重新获取一块数据体,然后就是构建teacher bin链,而且由于没有libc是2.27,对teache bin doublefree没有检查 ``` set_info(10,'bbb') ```  然后我们就可以将free\_hook给链上,这边一定要free两个chunk,不然后我们后面初始化的时候就可会把free\_hook给申请掉,从而没法修改 ``` card_set() ```  然后我们就可以将free\_hook给申请出来给为system了,然后我们也可改为one\_gadget   完整exp ``` from pwn import * ```
docadmin
2024年12月30日 17:45
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码