#include <stdio.h>
int main() {
int a, b, c;
printf("Enter two integers: ");
scanf("%d %d", &a, &b);
c = a ^ b;
return 0;
}
코드는 간단한 xor연산을 하는 코드로 작성하였다.

main 함수를 가상화 난독화 진행하였고

다른 옵션은 전부 해제하였다.

먼저 원본 코드를 IDA로 분석한 결과이다.
basic block을 보면 main 함수 1개인 것을 볼 수 있다.

처음 코드의 시작 부분이다.
push 0F21FD100h
call sub_4B0BD1
시작 부분을 보면 stack에 어떤 값을 push하고 call sub_4B0BD1을 실행하는 것을 볼 수 있다. 해당 위치로 이동해 보자

중요하다고 생각되는 부분은 push edi, pushf, push ecx, push ebp, ... 등 stack에 지속적으로 레지스터랑 flag 등을 push하고 있다.

그 다음 코드인데 esi에 위치한 값을 eax로 가져온다. 가상머신에서 esi는 instruction pointer를 가르킨다.
그리하여 해당 부분은 opcode를 가져오고 핸들러의 위치를 구하는 코드로 생각된다.

ebx를 stack에 push하고 retn하게 된다. 즉, 위에서 구한 주소의 위치로 jmp한다.

정적 분석을 했기 때문에 handler의 정확한 주소 값을 몰라 base주소 부근을 찾아 보았다. 그 중 xor을 사용하는 코드를 발견 하였다. 코드를 보면 처음 보는 명령어들이 난무한다.
004B0906: mov edi, [ebp+0] ; VMContext로부터 어떤 값(레지스터)을 edi에 로드
004B090A: clc ; CF(캐리 플래그) 클리어
004B090B: mov cl, [ebp+4] ; VMContext의 다른 레지스터 값을 cl에 로드
004B090E: xor bx, 0E814h ; 잡음 연산 (무관할 수 있음)
004B0913: lea ebp, [ebp-2] ; VMContext를 살짝 이동 (잡음일 가능성 큼)
004B0919: bt bx, 0A4h ; bx의 특정 비트를 검사 (잡음)
004B091E: rcl bx, cl ; rotate with carry (잡음 가능성)
004B0921: xor bx, di ; bx ^= edi 하위 16비트
004B0924: shl edi, cl ; edi <<= cl
004B0926: movzx bx, ch ; ch zero-extend → bx (잡음)
004B092A: movzx ebx, di ; edi 하위 16비트를 ebx에 로드
004B092D: mov bl, bl ; NOP
004B092F: pushf ; 플래그 저장
004B0930: pop ebx ; 플래그 값을 ebx로 로드
004B0931: jmp loc_4A0CE3 ; 아마도 dispatcher 루프 복귀
코드 해석을 봤을때, 정확히 원본 코드에서 사용한 xor의 handler인지는 잘 모르겠다. 하지만 동작을 보면 VMContext로 부터 어떤 값을 edi로 가져오고, xor, shl연산을 수행한다. 마지막에는 플래그 값을 push한다. 이러한 점을 봤을때, handler가 맞지 않을까 하는 생각을 하였다. 그리하여 handler가 맞는지를 확인하기 위하여 해당 위치부터 분기문을 계속 따라가 보았다.
.Fm$:004B0931 jmp loc_4A0CE3
↓
.Fm$:004A0CE3 mov [ebp+4], edi
.Fm$:004A0CE6 mov [ebp+0], ebx
.Fm$:004A0CEA jmp loc_4AD6FA
↓
.Fm$:004AD6FA jmp loc_4B4181
↓
.Fm$:004B4181 lea edi, [esp+4+arg_78]
.Fm$:004B4188 jmp loc_4A8E30

loc_4B4181이 부분으로 복귀하였고 해당 위치는 처음에 살펴보았던 dispatcher의 앞 부분이다. 이 점을 보아 hander가 맞을 것이라 생각이 든다.
중간에 edi,ebx 값을 스택에 넣는 것을 볼 수 있다. 이 점은 hadler의 연산 결과를 저장하는 로직은 별도로 실행되는 것 같다.
코드르 보니 직접 loop에서 fetch-decode-execute가 실행되는 것이 아닌 hadler에서 복귀를 통해 loop로 동작하는 것을 알았다.