2021 BlueHens CTF 2021
Contents
题目
| 标题 | 类型 |
|---|---|
| watman | re |

解题
访问该地址

F12查看源码

可以看到页面代码较为简单,主要为一张图片一个whtml还有一个wasm文件,所以这题主要考验wasm逆向
首先我们从html代码中,可以看出,flagChecker是由checker.wasm导出的方法,点击按钮后,执行该方法
flagChecker接收三个参数,分别是由输入框内容经encode变换后的数组、128、257
WebAssembly(缩写为Wasm)是基于堆栈的虚拟机的二进制指令格式。Wasm被设计为可编程C / C ++ / Rust等高级语言的可移植目标,可在Web上部署客户端和服务器应用程序。
wasm是基于堆栈的虚拟机的二进制指令格式。与x86架构的汇编又很大的区别。
进一步的说明后续补充
我们可以从开发者工具中看到cheker.wasm的相关指令,下图为flagChecker的代码
| |
动态调试时可通过Chrome的调试功能,下断点进行调试。
相关指令集
可参考以下指令集
基本指令
这里简单介绍一下大量用到的基本指令:
local.get(get_local)
从函数的参数中读取内容,示例和下一条一起(
local.set(set_local)
基本的用途是向本地变量中写入值,如下例:
| |
local.tee
它同样是用来向本地变量写入值的,但它写入之后原值仍然保留在栈中,相当于省了一步 local.get。
i32.const
这个之前也提到过了,向站内压入一个数字,对应的还有其他三种类型的 .const,这里就不再重复了。
i32.add 等
这里的等指的是一系列算术运算,我们只是单独拿出 add 来举例。它弹出栈顶的两个元素并将其相加,最终将结果压入栈中。
其中包括i32.mul(乘)、i32.rem_s(取余)
i32.load 和 i32.store
顾名思义,从 Memory 中取出/向 Memory 存入数据的指令。
load 接受一个参数,就是地址;store 接收两个参数:先弹出需要存入的值,再弹出存入的地址。
这二者还经常带有特殊的属性:offset 表示 n 位的偏移,align 表示 2^n 位的偏移。
控制指令 – 分支
分支最常使用是 if,如下例:
| |
这里需要注意的是,if 的判断过程都是在 if 之前进行的,if 本身只能从栈中弹出一个元素,并且判断其是否为 0,非 0 则成立。
这里需要介绍的一条指令是 if_br,它可以跳出当前的块。if_br 1 就相当于跳出当前的 if,回到 if 开头重新判断。
还有一种判断指令:select。select 接收三个参数:a、b 和 condition。在判断时,condition 位于栈顶被首先弹出,当 condition 成立时,向栈中压入 a,否则就压入 b。
控制指令 – 循环
循环使用的是 loop,和 if 一样,它也并没有实际的意义,跳转需要通过 br 进行。
基于以上指令和动态调试的结果
可以还原flag验证脚本
| |

Author Zhe
LastMod 2021-03-30