AWDP-PWN 赛前速成
awdp-pwn赛前速成
小记
没打过AWDP,因为第一次打线下赛,所以准备写个笔记记录一下,完事之后在准备在补点笔记。
Web我还没有学,只记录了pwn
AWDP一般分为两个板块,Break(自己的payload打通)和Fix(让主办方的payload打不通)
patch:指防御。
checker:指在部署题目的时候,检查选手提交的补丁(patch文件)是否符合预设条件的专门脚本。常见的非常规防御的例子就是把二进制文件直接删除、把关键漏洞语句直接删除、在堆利用的题目中将free语句直接删除等,checker就是用于检查选手是否存在这些非常规补丁的。它主要是通过和提交的二进制文件通信来判断这个二进制文件是否有异常。
打补丁有下面2个基本原则:
1.不改变程序的正常运行流程。
2.能够防御想要防御的攻击
漏洞加固技巧
在AWDP中每个选手会收到一个附件,类似两个ctf题,只是一个修一个打,不同队伍不互通,有的赛制修是累加得分,有的就是固定分数,根据不同的赛制来得分,但本质上还是ctf赛题
patch-PWN
使用:
patch就是通过修改漏洞程序的漏洞汇编代码从而防止其他选手进行漏洞利用,不同的awd平台检查机制各不相同,原则上是只能针对漏洞点进行 patch 加固
链接:https://github.com/keystone-engine/keypatch
方法:直接下载py文件,放到ida目录\plugins文件夹下,然后重启ida即可


保存导出:
若要保存修改,则需要点击Edit – patch program – apply patches to input file

通用sh脚本:
如果目标目录非/home/ctf/可以自行修改。
update.sh
1 | #!/bin/sh |
资料:
跳转指令
无符号跳转
| 汇编指令 | 描述 |
|---|---|
| JA | 无符号大于则跳转 |
| JNA | 无符号不大于则跳转 |
| JAE | 无符号大于等于则跳转(同JNB) |
| JNAE | 无符号不大于等于则跳转(同JB) |
| JB | 无符号小于则跳转 |
| JNB | 无符号不小于则跳转 |
| JBE | 无符号小于等于则跳转(同JNA) |
| JBNE | 无符号不小于等于则跳转(同JA) |
有符号跳转
| 汇编指令 | 描述 |
|---|---|
| JG | 有符号大于则跳转 |
| JNG | 有符号不大于则跳转 |
| JGE | 有符号大于等于则跳转(同JNL) |
| JNGE | 有符号不大于等于则跳转(同JL) |
| JL | 有符号小于则跳转 |
| JNL | 有符号不小于则跳转 |
| JLE | 有符号小于等于则跳转(同JNG) |
| JNLE | 有符号不小于等于则跳转(同JG) |
简单漏洞:
整数溢出:
整数溢出漏洞是由于程序对于有无符号数的判断出现了问题,所以修复整数溢出便是针对于汇编中的跳转指令进行patch
atoi(),C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个int型整数。get_n(int a1, unsigned int a2),对长度的接收(第二个参数)是无符号整型,所以第一个get_n()输入-1,可以通过>32的判断,但是在第二个get_n(),-1变成4294967295,造成整数溢出,使得我们能够进行缓冲区溢出攻击。

下面开始修复,通过上面知道这里造成整数溢出修复是将跳转指令换成无条件跳转指令即可

可以发现这里jle是有符号小于等于跳转

将jle修成jb即可,保存导出
栈溢出:

这里有一个栈溢出漏洞,我们可以看到这里有一个buf大小0x20,但是读入0x64的栈溢出漏洞

**lea rax, [rbp+buf]**意味着读入的大小是0x20加8就是0x28
patch 64h的位置,右键找到keypatcher

这里只patcher一下,然后点cancel,修复结果如下

保存导出
格式化字符串:
该题有一个经典的格式化字符串漏洞

一
第一种,也是最简单的方法,直接将printf改成puts,很显然这道题提供了puts函数,但是注意puts的地址是plt表的地址


二
第二种方法,改成安全格式输出,本质上把:printf(format)改成printf(“%s”, format)
原漏洞处

修改后


保存导出即可
uaf:
该题存在典型的 Use-After-Free 漏洞。问题出在 del_note 函数中:程序在删除指定 note 时,先释放了 note->content,再释放了 note 结构本身,但没有将全局数组 notelist[idx] 置空。这样一来,notelist[idx] 仍然保存着一个指向已释放堆块的悬挂指针。随后在 print_note 函数中,程序仅判断 notelist[idx] 是否为非空,就继续把它当作有效的 note 结构使用,取出其中的函数指针并进行调用。攻击者可以通过重新申请并覆盖这块已经释放的堆内存,伪造 note 结构或篡改函数指针,从而控制程序执行流程。
因此,修复的核心不是单纯“删除第二个 free”,而是消除悬挂指针。最小修复方式是在 del_note 中保留对 note->content 的释放,但将原本释放 note 结构本身的那段逻辑改为把 notelist[idx] 清零,即用 notelist[idx] = NULL 替代第二次 free(note)。这样print_note 后续再访问该槽位时会因为指针为空而终止使用,从而阻断 UAF 利用链。这个修复属于最小改动方案,代价是会引入note 结构本身的少量内存泄漏,但可以在不重构整体逻辑的前提下直接消除漏洞。


原汇编
1 | mov eax, ds:notelist |
修改完的汇编
1 | mov eax, ds:notelist |
修复完


保存导出