#include <stdio.h>
int main() {
int a, b;
scanf("%d %d", &a, &b);
printf("%d\n", a + b);
printf("%d\n", a - b);
printf("%d\n", a * b);
printf("%d\n", a / b);
return 0;
}
코드는 이렇게 사용하였고, gcc로 컴파일 하여 vmprotect를 적용하였다.

먼저 원본 코드를 IDA로 분석한 결과이다. 이를 통해 main함수의 주소를 확인하였다.

함수 보호는 main함수만 진행 하였고, option은 virtualization만 적용하였고 그 외에는 전부 적용하지 않았다.

가상화 난독화를 적용하고 IDA로 열었을때의 시작 부분이다. 값을 stack에 push하고 loc_14017A33A를 호출한다.
해당 위치로 이동하면

이러한 CFG를 볼 수 있다.


확인해 보면 굉장히 많은 잡음 명령어들이 존재하고 stack에 값을 저장하는 코드들을 보면
push rcx
push rax
push rbx
push r11
push r14
push r13
push rdx
push rbp
push r9
push r10
push rsi
이렇게 레지스터 값들을 push하는 것을 볼 수 있다.
loc_14017AA64:
push r8
mov r11b, dil
movsx rsi, cx
cwd
pushfq
mov r10, 0
mov [rsp+arg_20], r10
mov esi, dword ptr [rsp+arg_78]
adc r9b, 93h
movsx rcx, r10w
sbb r9w, 9A4h
add esi, 482F2D86h
cqo
bswap esi
cwd
cmovbe rdx, rsi
inc esi
adc bpl, dl
test esp, 0F215CBBh
or ch, 84h
neg esi
bswap esi
dec esi
movzx r11, r8w
rol dh, 2
ror esi, 1
shl bpl, 0Eh
lea rsi, [rsi+r10]
cwd
rol cl, cl
sets ch
mov r9, 100000000h
lea rsi, [rsi+r9]
adc ebp, esp
movsx ebp, r15w
shld rcx, rax, 0BFh
mov [rsp+arg_70], r15
clc
cmovg bp, di
neg r11b
mov [rsp+arg_78], rdi
and bp, 0D8Fh
sar bpl, 31h
mov rbp, rsp
lea rcx, [rbp-200h]
or edx, 10076B87h
and r8b, r10b
shrd dx, r10w, 7
and cl, 0F0h
xchg r11b, dl
jmp loc_14017D001
해당 위치에는 r8, flags를 stack에 push하는 것을 볼 수 있다.
중요하게 볼 부분이

rsi레지스터는 instruction pointer로 사용하기 때문에 중요하게 봐야할 부분이라고 생각한다.
가장 처음에 movsx rsi, cx를 수행한다. 중간에 의미없는 연산들이 존재하며 lea rsi, [rsi + r10] 을 수행하는데 처음 cx가 base주소를 나타내는 것이 아닌가 하는 생각이 든다. 그 다음 다시 lea rsi, [rsi+r9]를 실행한다. 명령어 실행을 위해 offset을 더해준 것으로 생각이 든다.
mov rbp, rsp
lea rcx, [rbp-200h]
또 다른 중요한 부분이라 생각드는 곳인데, 정적 분석을 하고 있기 때문에 정확히 어떤 값이 stack에 들어가 있는지는 알 수 없지만 흐름상 rcx가 VMContext를 가리키는 것으로 예측한다.

그 다음 부분을 보면 rsp에 rcx의 값을 넣고 연산을 수행한다.

r11에 주소값을 저장하고

코드의 마지막 부분인 해당 위치로 이동하게 된다.
r8d(r8의 하위 32비트) -> rsir11 -> handler table 시작주소movsxd rdx, dword ptr [r11 + r8*4] -> r8에 저장된 값을 사용하여, handler 주소를 rdx에 저장push rdx, retn -> rdx에 저장된 주소로 분기실제로 "Inside VMProtect" 블로그를 보면 rsi는 instruction pointer를 가르킨다고 명시돼 있다.

방금 분석한 블럭의 집합점이다. 다른 블럭들에서 VMloop를 통해 fetch 하고 decode 하는 부분이 존재하지 않을까 싶다.
위 분석을 통해 r11이 handler table이라는 것을 알았다. 그리하여 해당 부분을 분석해 보았다.

보면 엄청나게 많은 값들이 있는 것을 볼 수 있는데 여기 있는 offset값을 이용해여 handler로 이동하게 된다.