Tigress Virtualize Region

안상준·2025년 11월 29일

Virtualize Deobfuscator

목록 보기
13/14

이번에는 Tigress의 가상화 난독화 옵션 중 구역을 지정할 수 있는 옵션이 있어 해당 옵션을 적용하여 코드를 분석해 보았다.

Function Regions


공식문서를 캡처한 사진이다.
직접 몇가지 코드를 대상으로 테스트한 결과, 구역을 지정한 내부에는 배열, 코드 내에서 선언한 함수 호출 등은 불가능 하였다. 또한, 내부에서 선언한 변수는 가상화 영역 외부에서 사용이 불가능하였다.(반대는 가능)

C Code

#include <stdio.h>
#include "tigress.h"

int main(void){
        
    int n;
    scanf("%d", &n);
    int arr[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    TIGRESS_REGION(Region, {
        int i;
        int j;
        int temp;
        n = 10;
        for (i = 0; i < n - 1; i++) {            
            for (j = 0; j < n - i - 1; j++) {                
                if (arr[j] > arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    });    
    
    if(n < 10) n += 10;
    else n -= 10;
    int sum = 0;
    for(int i=0; i<n; i++) {
        sum += i;
    }
    n = sum;
    printf("%d\n", n);
    return 1;
}

코드는 가상화 영역이 종료된 후 원본 코드 실행 방식을 분석하기 위하여 위와 같이 작성하였다. 반드시 tigress 헤더파일을 추가해 주어야 한다. 가상화 명령어도 조금 다르다.

tigress --Verbosity=0 --Environment=x86_64:Linux:Clang:15.0 \
    -I/usr/local/bin/tigresspkg/4.0.11 \
    --Transform=Virtualize \
    --Functions=main:Region \
    --VirtualizeDispatch=switch \
    --out=switch.c test.c

가상화 난독화 적용은 위와 같이 하였다. 함수 뒤에 위의 C 코드에서 작성한 Region 이름을 명시해 주면 된다.

Virtualized Code (Switch)

이렇게 적용한 코드에서 특징적인 부분만 분석해 보자.

Dispatch


사진을 보면 case문에 goto문이 존재하는 것을 확인할 수 있다. 해당 부분이 가상화 영역 밖으로 분기하는 지점이 된다.

Original


위의 goto문의 label이다. 아래 부터는 위의 C코드에서 봤던 코드들이 존재하는 것을 확인할 수 있다.
#으로 line 번호가 적혀 있는 것은 원본에서 몇 번째 줄에 있었던 코드인지 표기한 것이다.

Virtualized Code (Direct)


direct 디스패치 옵션도 마찬가지다. 핸들러 중 가상화 영역을 벗어나는 핸들러가 존재한다.

Virtualized LLVM IR Code

이번에는 가상화 난독화를 적용한 C 코드를 LLVM IR로 분석해 보자.
중점적인 부분만 분석해 보면 위 C 코드에서 처럼 가상화를 종료하는 지점을 찾아 보았다. 이전에 IR 코드 분석할 때, 핸들러에서 디스패치로 분기하지 않는 블록을 찾았었는데, 동일한 방식으로 찾으면 된다.


363번 블록으로 분기하는 핸들러가 존재하며, 블록을 쭉 따라가면 원본 코드가 존재하는 것을 확인할 수 있다. 위 IR은 switch 디스패치 옵션을 적용한 코드를 분석한 결과이며, 다른 디스패치 옵션에 대해서도 동일하게 분석하면 된다.

정리하면, 함수 전체 가상화 난독화를 적용하면 핸들러 중 ret이 종료 명령어인 핸들러가 가상화 영역을 종료하는 핸들러가 되며, 가상화 구역을 지정할 경우, 핸들러 중 디스패치로 다시 분기하지 않는 핸들러가 가상화를 종료하는 핸들러가 된다.

즉 디스패치로 분기하지 않는 (단일 분기 or ret) 핸들러를 찾으면 된다.

0개의 댓글