跳转至

简介

前言

WebAssembly(缩写为Wasm)是基于堆栈的虚拟机的二进制指令格式。Wasm被设计为可编程C / C ++ / Rust等高级语言的可移植目标,可在Web上部署客户端和服务器应用程序。

随着wasm的逐渐流行,在最近的ctf比赛中出现了很多wasm类型的逆向题。没接触过wasm的人会比较苦手。即使对wasm有一定的了解,由于wasm的汇编语言可读性十分差,逆向起来会非常的痛苦。

wasm汇编简介

wasm是基于堆栈的虚拟机的二进制指令格式。与x86架构的汇编又很大的区别。反倒更加类似python的opcode

下面分别是C++,wat,以及由用g++编译的x86 assembly代码,让我们首先对wasm汇编有个初步印象。

WebAssembly Explorer可以在线编译wasm

C++代码:

1
2
3
4
5
6
7
int testFunction(int* input, int length) {
  int sum = 0;
  for (int i = 0; i < length; ++i) {
    sum += input[i];
  }
  return sum;
}

wat代码:

 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
(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "_Z12testFunctionPii" (func $_Z12testFunctionPii))
 (func $_Z12testFunctionPii (; 0 ;) (param $0 i32) (param $1 i32) (result i32)
  (local $2 i32)
  (set_local $2
   (i32.const 0)
  )
  (block $label$0
   (br_if $label$0
    (i32.lt_s
     (get_local $1)
     (i32.const 1)
    )
   )
   (loop $label$1
    (set_local $2
     (i32.add
      (i32.load
       (get_local $0)
      )
      (get_local $2)
     )
    )
    (set_local $0
     (i32.add
      (get_local $0)
      (i32.const 4)
     )
    )
    (br_if $label$1
     (tee_local $1
      (i32.add
       (get_local $1)
       (i32.const -1)
      )
     )
    )
   )
  )
  (get_local $2)
 )
)

使用gcc编译的x86汇编:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
         push    rbp
         mov     rbp, rsp
         mov     [rbp-18h], rdi
         mov     [rbp-1Ch], esi
         mov     dword ptr [rbp-8], 0
         mov     dword ptr [rbp-4], 0
         mov     eax, [rbp-4]
         cmp     eax, [rbp-1Ch]
         jge     short loc_400766
         mov     eax, [rbp-4]
         cdqe
         lea     rdx, ds:0[rax*4]
         mov     rax, [rbp-18h]
         add     rax, rdx
         mov     eax, [rax]
         add     [rbp-8], eax
         add     dword ptr [rbp-4], 1
         jmp     short loc_01
loc_01:
         mov     eax, [rbp-8]
         pop     rbp
         retn

可以看到,不同于x86使用的寄存器加栈的架构,wasm主要基于栈。局部变量被保存在local内,全局变量保存在global中,对变量的操作则使用get_local入栈,操作完再使用set_local设置局部变量。

参考资料

官方文档:https://webassembly.org/(英文) http://webassembly.org.cn/(中文)

Mozilla:https://developer.mozilla.org/zh-CN/docs/WebAssembly(中文)

评论