L3HCTF-2024-部分复现
day1聚会去了直接摸鱼,结果队里的爹们直接全给干完了,day2跟师傅们一起把reAK了,只能说OIer多少带点傻逼的
babycom
调试可以发现释放了一个dll文件在 C:\Users\Username\AppData\Local\Temp
继续调试到
再 F7 可以进入加密函数
创建函数反编译后发现是一堆 XTEA 加密
key是这个
最后还有一个 advapi32_CryptEncrypt
密文是Buf1
解密即可,参考 CryptEncrypt 函数 (wincrypt.h) - Win32 apps | Microsoft Learn
1 |
|
解出flag L3HCTF{C0M_Th3C0d3_1s_FuN!!!!!!}
babyRust
查个属性,发现是 Tauri Apps,Tauri 是一个开源框架,用于构建轻量级、高性能的桌面应用程序。它是使用 Web 技术(如 HTML、CSS 和 JavaScript)来创建用户界面,同时利用 Rust 语言提供的api功能。Tauri 的目标是提供一种更高效、更安全的方式来开发跨平台的桌面应用程序。
根据 Tauri 框架的静态资源提取方法探究 | yllhwa’s blog,
再IDA里找到 /assets/index-tWBcqYh-.js
先dump下来
1 | import brotli |
格式化JS代码以后,逻辑在最下面
1 | const nl = ve("button", { |
先异或再base64,解密即可
1 | import base64 |
DAG
字节码逆向,chatGPT + 手动修改(func1 GPT生成的缩进错完了痛失三血)
1 | # func1 |
把几个str爆破一下,然后进行连边,看v1能不能通过删除一个字母到达v2,最后跑一个最长路,注意 ans 初始化是 1
1 | import sys |
ez_stack
虚拟机,dispatcher
是 sub_4017A1
, 字节码在 dispatcher
函数调用之前解密出来,sys_mmap
是 Linux 系统调用,开空间用的。
一开始就开辟了三个栈空间 406040, 406050, 406060
,作用分别是:
406040:存储待执行的指令字节码,相当于 IR
406050:存储栈空间中的变量
406060:存储数据,相当于通用寄存器,并用于循环
格式为:
1 | struct stack |
然后进入循环取字节码
sub_40170D
是 pop
操作,该函数的参数也是一个 stack 结构体
sub_4015AE
是 push
操作如果栈空间大小不够,还会用 sys_mmap 函数扩展栈空间
然后对取出来的 opcode 进行一些解析,v15 是对指令的操作次数
然后就是虚拟机分析,取高四位进行 dispatch
0xF0: 退出虚拟机
0xE0: 从 406050 依次 pop opcode_num 个字节,然后 sys_write() 写出来
0xD0: 读入 opcode_num 个字节,push 进栈 50
0xC0: 一坨位移操作
0xB0: or 运算,拿出 406050 顶部的 2 * opcode_num 个元素,前 i 个元素与第 i + opcode_num 个元素 or,再按顺序放回去
0xA0: and 运算,和 or 差不多
0x90: xor 运算,和 or 差不多
0x80: sub 运算,v9 保存借位,其它和 or 差不多;上一个如果是负下一个结果得减 1,先算靠近栈底的那边
0x70: add 运算,v9 保存进位,其它和 or 差不多;上一个如果进位下一个结果得加 1,先算靠近栈底的那边
0x60: 复制 406050 顶部第 opcode_num 个元素,然后把它 push 到栈顶
0x50: 删除 406050 顶部第 opcode_num 个元素
0x40: 把之前 op_big_endian 那仨数据 push 到栈 50
0x30: 控制流指令
jmp
0x20: 从 406060 中取出之前push进去的旧指令,实现向前跳转,循环的功能
0x10: 从解密字节码中解压 z 条指令,并压入 406040 的栈