#WASM #Web Assembly #웹어셈블리
웹 브라우저에서 js 가 아닌 코드가 컴파일 되어 실행되는 컨셉이다.
wasm 은 브라우저에서 text format 으로 나타내어 보여준다.
개인 공부용으로 해당 text format 의 명령어나 문법을 간략히 정리해본다.
(module
...
)
(module ... )
안에는 해당 웹어셈 프로그램에 쓰인 요소들이 들어간다.
안에 들어가는 요소는 func
, global
, memory
, table
, 등등이 있다.
(;0;) (;1;)
그리고 위와 같이 각 요소들은 순서에 따라 서수(ordinal)를 갖게된다. (0번 요소, 1번 요소 , ...)
(func $함수변수이름 (;0;) (export "사용할 함수이름") (param $인자로 쓰이는변수 i32) (result i32)
(local $함수내 지역변수들) (local $함수내 지역변수들) ...
// 함수 구문 시작
)
함수 정의 부분이다. 처음엔 낯설어도 꽤 친절한 구조이다.
일단 괄호를 통해 함수 하나를 묶어 준다. 그리고 func 로 선언을 해주는데 해당 함수 이름은 $
표시 뒤에 써주면 된다. export 할 시에는 export
뒤에도 export 할 이름을 써주면 된다.
그리고 param
구문으로 인자를 정의할 수 있는데, 인자가 여러개라면 (param ~~)
구문을 개수만큼 써주면 된다. 대신 $
뒤에 오는 변수이름은 각각 다르게 해야한다. 또한, 인자와 더불어 return
구문으로 반환 값에 대한 형식 i32, i16,...
을 지정해줄 수 있다.
바로 다음에는 해당함수에서 쓰이는 지역변수를 local
구문을 통해 정의해준다. 그 뒤에는 함수 내용이 시작된다.
WASM 은 C/C++ 등을 웹에서 읽도록 효율적으로 변환한 결과라지만, 여전히 stack 을 이용하는 언어이다.
이는 개발자도구에서도 살펴볼 수 있는 기능을 갖고있는데, 예를들어
i32.const 255
local.set $var2
해당 구문이 있다고 하면, 첫 번째 줄 실행 시 스택에는 255 값이 들어간다.
그리고 local.set
을 통해 var2 에 스택의 255 값을 pop 하여 넣어준다.
아무튼 이런 원리.
변수와 스택에 값 왔다갔다 시키기 (set, get)
set
은 변수에 값을 넣는 대입연산자의 느낌이다. 보통 위에 코드처럼 상수 값 뒤에 연달아 나오는 것이 특징.
상수 값을 스택에 넣고, 스택 맨 위에 있는 해당 값을 pop 하여 변수에 집어 넣는다.
get
은 변수에 있는 값을 얻어와서 스택 맨 위에 push 하는 명령어다.
예를 들어, local.get $var1
이라는 구문이 있으면, 현재 $var1 에 있는 값을 스택에 push 하는 것.
메모리와 스택에 값 왔다갔다 시키기(store, load)
store
명령어는 메모리 상에 값을 저장시키는 명령어이다. 스택에 맨 위 부터 차례로 1000, 1 값이 있다면, store
명령어는 $memory + 1 의 위치에 1000 이라는 value 를 저장한다. 비트범위를 고정할 수 있는 store8, store16
등 종류도 다양하다.
load
명령어는 메모리로부터 스택에 값을 가져오는 명령어이다. 스택 맨 위에 1 이란 값이 있다면, load
명령어는 1을 pop 시키고 $memory + 1 위치에서 value 를 가져와서 스택에 push 한다.
조건문 (ne, eq, eqz)
일반 AT&T 나 INTEL 어셈블리의 jne , je 처럼 웹어셈블리도 동일한 역할을 하는 어셈명령어를 갖고있다.
일단 ne
는 스택 맨 위 두 값을 비교하여 두 값이 같지않으면, 두 값을 pop 시킨 후 1을 다시 push 한다. 만약 ne
명령어 직후 스택 맨 위 값이 1이면 같지 않다는 뜻으로 간주한다.
그러면 eq
는 ? 반대로 생각하면 되겠다. 같으면, 1을 push 하고 다르면 0을 push 한다.
그냥 두 값의 boolean 값을 리턴하는데 ne
만 반대로 간다고 생각하면 된다.
eqz
는 위 두 개랑 달리 하나의 스택 값(one operand) 을 갖고 비교한다. 만약 스택 맨 위 값이 0 이랑 같으면 1을 스택에 push 하고 다르다면 0을 push 한다.
이 정도만 정리하고, 분기 명령어는 하나이다.
분기문 (br_if)
br_if
는 스택 맨 위의 값이 1 이면, 분기하고 아니면 그대로 진행한다.
이 밖에도 add, sub 등 여러 명령어가 있지만 디버깅 해보면 다 이해 가능하다.
참고
'<보안 study> > 웹' 카테고리의 다른 글
CSP(Content-Security-Policy) 정리 (0) | 2021.08.23 |
---|---|
DreamHack CTF 문제에서 배우는 NOSQL Injection (0) | 2020.09.30 |
동적 폼(form) 만들기 (0) | 2018.07.24 |