
此篇参考合天网安实验室的这篇文章
IDA安装keypatch插件
下载地址:https://github.com/keystone-engine/keypatch
1 | pip install keystone-engine |

将keypatch.py文件复制到 IDA的plugins文件夹下,重启IDA

安装成功
跳转指令
无符号跳转
| 汇编指令 | 描述 |
|---|---|
| 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-整数 溢出

scanf以long int长整形读取输入到unsigned int变量v2中, 然后将v2强制转化为int再与int 48比较
但从scanf读入一个负数时, 最高位为1, 从unsigned int强制转换为int结果是负数, 必定比48小, 在后面read读入会造成栈溢出
方法
将第九行的if跳转汇编指令patch为无符号的跳转指令, 具体参考跳转指令表
使用keypatch进行修改
jle-->jbe

patch-栈溢出
对于栈溢出加固,x64 更容易一些,因为是使用寄存器传参,而x86 使用栈传参,需要用 nop 等保持加固前后的空间不变
x64

方法
100是第三个参数, 存储寄存器是rdx, 找到给rdx传参的汇编指令进行patch
使用ida默认修改插件修改(Edit-Patch Program-Change word), 也可以使用keypatch
0x64 是长度
0xBA 是操作符

1 | 0x64->0x20 |

x86
不需要对齐

找到压栈的指令, 修改压入的数值

- 修改数值需要补上
0x - 这里修改前 size 为 2 ,修改后 size 也为 2 ,所以这题 patch 不需要用 nop 保持 size
需要对齐

找到压栈的指令, 修改压入的数值

直接修改0x20后, size 长度不对齐, 会引起栈空间变化, 需要用nop进行对齐

更方便快捷的方法是勾选NOPs padding until next instruction boundary进行自动填充
patch-格式化字符串

修改函数
将printf改为puts, 将call的地址改为puts plt地址:

这个方法局限性在于: puts会在原字符串多加\n, 主办方check可能因此而不通过
修改printf参数
将printf(format)修改为`printf(“%s”,format)
修改printf前面的传参指令:

1 | mov edi, offset 0x400c01; |

patch-UAF

修改逻辑是劫持call指令跳转到.eh_frame段上写入的自定义汇编程序
先在.eh_frame段上写入代码, 首先是call free完成释放, 然后对chunk_list进行置零. 取chunk_list地址的汇编可以从call free前面抄过来
1 | call 0x900; #调用free函数(plt地址) |

patch-if范围
假设需要将图上第二个if放到if结构内, 修改跳转的地址即可:

原始跳转代码:

1 | js 0x40081C --> js 0x400845 |

patch-更换危险函数
类似与 uaf 一样写汇编实现功能调用,将危险函数替换为其他函数,如果程序中没有目标函数,就通过系统调用方式调用。
将 gets 替换为 read 输入

.eh_frame写入汇编,将 rdi 的写入地址移动到 rsi ,把其他寄存器也传参之后进行系统调用:



pwn通防小工具
注意: 这里由于编译方式不同的原因, 作者写的工具目前仅适配Ubuntu16;18;20
基于pwntools和seccomp-tools的awd pwn通防小工具, 原创在这
GitHub地址: https://github.com/TTY-flag/evilPatcher
环境需要
运行需要依赖seccomps-tools和pwntools
pwntools安装
这里要在python2下安装,因为工具是基于python2的
1 | sudo apt install python2 |
seccomps-tools安装
1 | sudo gem install seccomp-tools |
test
结束后我们可以随便找一个pwn题试一下
1 | python2 exp1.py |

然后
1 | python2 evilPatcher.py pwn1 sandboxs/mini_sandbox.asm 1 |
试一下通防脚本

生成后的pwn1.patch修改为pwn1, 再运行一下exp
1 | python2 exp1.py |
成功!

- Post title: Pwn_patch
- Create time: 2023-06-21 21:49:29
- Post link: 2023/06/21/pwn_patch/
- Copyright notice: All articles in this blog are licensed under BY-NC-SA unless stating additionally.