awdp学习记录
zach0ry

AWDP一般分为两个板块,Break(自己的payload打通)和Fix(让主办方的payload打不通)

patch:指防御。

checker:指在部署题目的时候,检查选手提交的补丁(patch文件)是否符合预设条件的专门脚本。常见的非常规防御的例子就是把二进制文件直接删除、把关键漏洞语句直接删除、在堆利用的题目中将free语句直接删除等,checker就是用于检查选手是否存在这些非常规补丁的。它主要是通过和提交的二进制文件通信来判断这个二进制文件是否有异常。

打补丁有下面2个基本原则:

❑不改变程序的正常运行流程。

❑能够防御想要防御的攻击

keypatch下载

patch实例

image-20260203161146779

这个题的漏洞主要是get函数的无限制读入

1
2
3
4
5
6
text:00000000004009CC                 call    _puts
.text:00000000004009D1 lea rax, [rbp+s]
.text:00000000004009D5 mov rdi, rax
.text:00000000004009D8 mov eax, 0
.text:00000000004009DD call _gets
.text:00000000004009E2 jmp loc_400AB4

要patch就要把它改为有限制的输入

改为read(0, s, 0x20);或者fgets(s, 0x20, stdin);

但问题来了:❌ 原地改不了

gets(s) 只需要:一个参数:s

read(0, s, 0x20) 需要:3 个参数:fdbufsize

所以要从call gets

变化为(修改为read类型)

1
2
3
4
5
6
mov rax,0
mov rsi, rdi
mov rdi,0
mov rdx,0x30h
syscall
ret

原来的位置放不下,所以要让程序跳转到其他位置去执行

在很多 CTF / AWDP 程序中:

  • .eh_frame 段往往是:
  • R--R-X
  • 并且内容不会真的被程序用到
  • 里面经常有:
  • 一大段固定格式数据
  • 或填充字节

在比赛中大家就把它当成:现成的“可执行空地”

所以选择 .eh_frame 的本质原因是:👉 它往往是“能执行”的段

“填补 NOP 指令直到下一条指令边界”

作用:
当用一条新指令替换原来的多条指令、或长度更短时,用 NOP剩余空间补齐,避免留下半条旧指令的字节。

在代码段(.text)里 patch 指令,且新指令比原指令短:
原来:

1
2
>mov rax, rbx   ; 3字节
>add rax, rcx ; 3字节

改成:

1
>xor eax, eax   ; 2字节

→ 剩下 4 字节会残留旧机器码
→ 必须用 NOP 填满
👉 需要勾

你现在这种情况:在 .eh_frame 写 read

  • .eh_frame 原本是 db xx(纯数据)
  • 不是指令流
  • 没有“下一条指令边界”的概念

👉 不需要勾(勾不勾都不影响)

在_eh_frame上放read函数

image-20260203173819783

patch call get过去到jmp_addr

image-20260203173543916

之后应用就可以了

image-20260203174951575

参考链接

pwn patch ciscn_2019_c_1 - 叶际参差 - 博客园