본문 바로가기

보안/악성코드

Anti-VM 기법이 적용된 악성코드 분석 및 우회 방법 연구

0. 요약


0.1 제목


  Anti-VM 기법이 적용된 프로그램 분석 및 우회 방법 연구


0.2 연구 개발의 목적 및 중요성


  최근 증가되고 있는 악성코드에 의한 사용자의 데이터 유출 및 개인정보 유출, 분산서비스거부(DDoS) 공격 등의 다양한 침해사례가 증가하고 있다. 악성코드를 예방하고 차단하기 위해서는 악성코드의 신속한 분석을 통해 대응책을 찾는 것이 중요하다. 이를 위해 다양한 패턴을 지닌 악성코드를 수집하고 이를 정적 분석, 동적 분석을 통해 분석하는 방법이 있다. 하지만, 대다수의 악성코드들은 자신을 보호하기 위해 실행 압축, 난독화, Anti-VM, Anti-Debugging, 코드 가상화 등의 기술을 사용하며, 특히 Anti-VM 기술을 적용한 악성코드들이 급격히 늘고있어 이를 우회하는 기술의 확보가 시급하다.


0.3 연구 개발의 내용 및 범위


  본 연구의 범위는 대표적인 패킹 프로그램인 더미다를 이용하여 패킹한 프로그램이 가상환경에서의 Anti-VM 기능을 어떻게 구현하는지 확인하고, Anti-VM 기능을 우회하는 기법을 연구하는 것이다. 해당 절에서 Anti-VM 기법, Anti-VM 우회 기법, Anti-VM 우회 테스트를 소개한다.


0.4 연구 결과


  실제 더미다로 Anti-VM 기능이 구현된 계산기를 이용해 실험을 진행하였으며,  레지스트리와 서비스 조회 두 가지를 이용하여 구현된다는 사실을 입증하였다. 


0.5 기대효과


  더미다의 Anti-VM 기능이 적용된 악성코드의 Anti-VM 기능을 우회함으로써, 실제 악성코드가 행하는 행동을 빠르고 정확하게 동적분석하여 대응할 수 있으며, 이로 악성코드의 전파 및 피해를 최소화할 수 있게 된다.



1. 개요


1.1 연구 개발의 목적 및 중요성

  

  최근 증가되고 있는 악성코드에 의한 사용자의 데이터 유출 및 개인정보 유출, 분산서비스거부(DDoS) 공격 등의 다양한 침해사례가 증가하고 있다. 악성코드를 예방하고 차단하기 위해서는 악성코드의 신속한 분석을 통해 대응책을 찾는 것이 중요하다. 이를 위해 다양한 패턴을 지닌 악성코드를 수집하고 이를 정적 분석, 동적 분석을 통해 분석하는 방법이 있다. 하지만, 대다수의 악성코드들은 자신을 보호하기 위해 실행 압축, 난독화, Anti-VM, Anti-Debugging, 코드 가상화 등의 기술을 사용하며, 특히 Anti-VM 기술을 적용한 악성코드들이 급격히 늘고 있어 이를 우회하는 기술의 확보가 시급하다.

  Anti-VM은 악성코드 분석 기법중 하나인 가상환경에서의 악성코드 분석 기술을 우회하는 방식이다. Anti-VM은 가상머신 환경을 구축함으로써 나타나는 특징을 탐색하여 악성코드가 수행할 플랫폼이 가상머신 환경인지 판단 할 수 있다.  

 

  본 연구 2장에서는 Anti-VM에 대한 자세한 기법과 이를 우회하기 위한 방법들을 소개하고, 3장에서는 실제 Anti-VM 우회 테스트를 소개하며 실효성 검증 및 결론 순으로 본 연구를 마무리 짓는다. 

 

2. 연구 범위, 내용 및 방법


2.1 연구 범위


  본 연구의 목표는 대표적인 실행파일 압축 프로그램 더미다가 압축한 프로그램이 가상환경에서의 Anti-VM 기능을 어떻게 구현하는지 확인하고 Anti-VM 기능을 우회하는 기법을 연구하는 것이다. 전통적으로 악성코드들은 본인이 악성행위를 하는 것을 숨기기 위하여 실행파일을 압축하여 자신의 코드를 숨겨 왔다. 따라서 악성코드 분석가들은 코드분석(정적분석) 뿐만 아니라 가상환경에서 악성코드의 행위를 분석하여 악성코드 인지를 파악하는 동적분석 까지 같이 수행하고 있다. 악성코드 제작자는 동적분석을 피하기 위해 가상환경에서 악성행위를 하지 않는 Anti-VM 기법을 구현하여 악성코드를 배포하고 있다. 단 저비용 고효율의 효과를 내기 위해 새로운 Anti-VM기법을 사용하기보다는 단순히 알려져 있는 압축 프로그램을 사용하여 Anti-VM기능을 구현하고 있다. 따라서 우리는 잘 알려져 있는 실행파일 압축 프로그램 더미다에서의 Anti-VM 기법을 분석하고 이를 우회하는 방법은 연구하고 실험하여 진행하였다.


2.2 연구 내용 및 방법


2.2.1 Anti-VM 기법


  가상머신이란 컴퓨터 환경을 소프트웨어로 구현한 것을 말한다. 가상머신 위의 운영체제는 가상으로 생성된 하드웨어 장치를 실제 장치로 인식하고 가상의 하드웨어 장치는 실제 하드웨어 장치와 다른 성능과 다른 이름을 가진다. 가상 머신에 운영체제가 설치되면 가상의 하드웨어 장치를 사용하기 위해 관련된 드라이버가 설치된다. 이 때문에 가상 시스템에는 가상머신임을 식별할 수 있는 정보가 존재하게 된다. 그리고 악성코드는 이 정보를 이용해 현재 시스템이 가상머신임을 확인하고 실행 흐름을 전환한다.




그림 1 가상머신 구조



  현재 다양한 종류의 가상머신이 상용중이며 대표적으로 VirtualBox, VMware, Virtual PC, Virtual Hive가 존재한다. 본 연구에서는 악성코드 분석을 위해 주로 사용되는 VMware와 VirtualBox를 선정했고 운영체제는 Windows를 사용했다. 본 연구에서는 Windows 운영체제에서 가상머신임을 식별할 수 있는 방법을 크게 “레지스트리, 파일 또는 폴더, 프로세스 및 서비스, 그 외”로 구분한 뒤 조사를 진행했다.


2.2.1.1 레지스트리


  윈도우 레지스트리는 마이크로소프트 윈도 32/64비트 버전과 윈도 모바일 운영 체제의 설정과 선택 항목을 담고 있는 데이터베이스로, 모든 하드웨어, 운영 체제 소프트웨어, 대부분의 비운영 체제 소프트웨어 등에 대한 정보와 설정이 들어 있다. 


2.2.1.1.1 시스템 정보 레지스트리


  시스템 정보는 HKEY_LOCAL_MACHINE\SYSTEM 경로에 존재하며 윈도우에서 사용하는 파일 시스템, 하드웨어 드라이버, 윈도우의 커널이 사용하는 정보 등 윈도우 하부 시스템에 관련된 다양한 설정 내용에 대한 정보가 저장된다. 다음과 같은 하위키에 가상머신을 식별할 수 있는 정보가 남는다. 


ControlSet001, ControlSet001  : 윈도우가 부팅할 때 사용하는 컨트롤 집합이 들어 있는 키로, 최소한 2개 이상 존재한다. 윈도우 XP는 하드웨어의 내용이 변경될 때 마다 새로운 컨트롤 집합을 만들어 순서대로 번호를 붙인다.


CurrentControlSet : 컴퓨터를 부팅하기 위해 사용한 컨트롤 집합이다. 부팅에 사용된 컨트롤 집합은 자동으로 이 키에 그 내용이 복사된다.


CurrentControlSet/Enum : 부팅하는 동안 시스템에서 발견된 하드웨어 장치에 대한 정보가 모두 기록되어있다. 


CurrentControlSet/Services : 윈도우가 사용하는 드라이버와 서비스에 대해 정의되어 있다. 각 하위키는 윈도우에서 실행되는 서비스와 드라이버 이름으로 구성되어 있다. 각 키에는 Start 값이 있는데 이 값의 데이터에 따라 서비스와 드라이버가 언제 어떻게 실행되었는지 알 수 있다.


CurrentControlSet/Control : SYSTEM 키의 구성 요소 중 가장 많은 항목을 포함하고 있는 키로 윈도우와 시스템 파일이 설치된 폴더, 네트워크 이름등이 저장된다.


Virtual Box에는 다음과 같은 레지스트리 정보를 이용해 가상 머신을 식별할 수 있다. 


HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE : 시스템에 설치된 하드디스크에 대한 구성이 기록된다. 이 항목은 시스템에 설치된 하드디스크별로 설정된다.



그림 2  Virtual Box 시스템 정보 레지스트리 흔적



VMware에는 다음과 같은 레지스트리 정보를 이용해 가상 머신을 식별할 수 있다. 


HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SCSI


그림 3 VMware 시스템 정보 레지스트리 흔적 1



HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\disk\Enum-> 0


그림 4 VMware 시스템 정보 레지스트리 흔적 2



HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-08002BE10318}\0000\DriverDesc



그림 5 VMware 시스템 정보 레지스트리 흔적 3




2.2.1.1.2 하드웨어 정보 레지스트리


  하드웨어정보는 HKEY_LOCAL_MACHINE\HARDWARE 경로에 존재하며 시스템에 장착된 하드웨어에 대한 정보가 각 하위키에 저장되어 있다. 시스템이 부팅될 때마다 하드웨어 인식기인 Ntdetect.com이 하드웨어를 인식해 이곳에 새로운 정보를 저장한다. 다음과 같은 하위키에 가상머신을 식별할 수 있는 정보가 남는다. 


ACPI : Advanced Configuration and Power Interface의 약자로 컴퓨터에 연결된 모든 주변기기에 전력을 시스템이 조절할 수 있도록 하는 절전 장치 규격이다. ACPI를 조정하고 지원하는 장치에 대한 정보가 들어 있다.


DESCRIPTION : 부팅시 설치되어 있는 하드웨어를 검사해 이 키에 관련 목록을 저장 한다. 하드웨어 인식기인 Ntdetect.com을 이용해 목록을 만들며 휘발성으로 부팅시 갱신 된다. 각 하위키에는 Identifier라는 값이 있는데, 이 값의 데이터에 장치 이름이 저장 된다.


DEVICEMAP : 각 하드웨어 장치들과 KEY_LOCAL_MACHINE\SYSTEM\ CurrentControlSet\Services에 저장되어 있는 드라이버들을 서로 연결하는 값이 저장되어 있다. 즉 장치를 실행하기 위해 필요한 드라이버 컨트롤 집합의 위치 정보가 저장되어 있다.


Virtual Box에는 다음과 같은 레지스트리 정보를 이용해 가상 머신을 식별할 수 있다. 


HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT

HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT

HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT

 


그림 6 Virtual Box 하드웨어 정보 레지스트리 흔적1



HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\SYSTEM -> VideoBiosVersion


그림 7 Virtual Box 하드웨어 정보 레지스트리 흔적2



  VMware에는 다음과 같은 레지스트리 정보를 이용해 가상 머신을 식별할 수 있다. 


HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port X\Scsi Bus 0\Target Id 0\Logical Unit Id 0 -> Identifier


그림 8 VMware 하드웨어 정보 레지스트리 흔적



2.2.1.1.3 소프트웨어 정보 레지스트리


  소프트웨어 정보 레지스트리는 HKEY_LOCAL_MACHINE\SOFTWARE 경로에 존재하며 윈도우에 설치된 소프트웨어와 디바이스 드라이버에 대한 전반적인 정보가 저장되어있다.


VMware에는 다음과 같은 레지스트리 정보를 이용해 가상 머신을 식별할 수 있다. 


HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet\VMWAREHOSTOPEN.EXE의 하위의 관련 키, 값



그림 9 VMware 소프트웨어 정보 레지스트리 흔적



2.2.1.2 파일


  Windows 운영체제는 장치를 사용하기 위해 드라이버 파일을 C:\Windows\System32\drivers경로에 저장한다. VMware가 설치된 호스트와 호스트에서 실행되는 게스트에서 모두 VMware를 위한 드라이버 파일을 저장한다. 그 중 호스트에는 없지만 게스트에만 존재하는 드라이버 파일이 존재하고 이것의 존재여부로 가상머신을 식별할 수 있다. 다음 그림에서 체크된 파일은 모두 게스트에만 존재하는 드라이버 파일이다.



그림 10 VMware를 위한 드라이버 파일



  VMware에서 VMTools 유틸은 호스트와 게스트 간의 파일 전송을 지원한다. 이때 임시파일들이 게스트에 저장되어있고 이것의 존재여부를 통해 가상머신임을 식별할 수 있다.



그림 11 VMware에서 사용하는 임시파일



2.2.1.3 프로세스 및 서비스


  VMware는 가상 시스템의 성능을 향상시키고 다양한 기능들을 사용하기 위해 VMTools라는 유틸을 설치한다. 이 유틸은 가상 시스템의 애플리케이션이 다른 애플리케이션 창처럼 호스트 데스크톱에 나타날 수 있도록 해주고 가상 시스템과 호스트 또는 클라이언트 데스크톱 간에 텍스트, 그래픽 및 파일의 복사 및 붙여넣기 등의 기능을 제공한다. VMTools가 실행중일 경우 프로세스와 서비스를 통해 가상머신임을 식별할 수 있다. 다음은 VMTools가 실행중인 컴퓨터에서 작동중인 프로세스와 서비스를 캡처한 것이다.

 

그림 12 VMTools가 실행중인 프로세스



그림 13 VMTools가 실행중인 서비스



2.2.1.4 특정 명령어


  본래 인텔의 IN명령과 OUT명령은 커널 레벨에서만 실행 가능하다. 하지만 VMware의 경우 Host와 Guest 간의 통신채널 제공을 위해 응용프로그램에서도 실행이 가능하다. 다음은 특정 명령어를 실행하여 VMware를 탐지하는 프로그램의 코드이다. 


VMware backdoor I/O function call


#define   VMWARE_MAGIC            0x564D5868        // Backdoor magic number

#define   VMWARE_PORT             0x5658            // Backdoor port number

#define   VMCMD_GET_VERSION       0x0a              // Get version number

int   VMBackDoor(unsigned long *reg_a, unsigned long *reg_b, unsigned long *reg_c,   unsigned long *reg_d) {

          unsigned long a, b, c, d;

          b=reg_b?*reg_b:0;

          c=reg_c?*reg_c:0;

          xtry {

                  __asm {

                          push   eax

                          push   ebx

                          push   ecx

                          push   edx

                          mov   eax, VMWARE_MAGIC

                          mov   ebx, b

                          mov   ecx, c

                          mov   edx, VMWARE_PORT

                          in eax,   dx

                          mov a,   eax

                          mov b,   ebx

                          mov c,   ecx

                          mov d,   edx

                          pop edx

                          pop ecx

                          pop ebx

                          pop eax

                  }

          } xcatch(...) {}

          if(reg_a) *reg_a=a; if(reg_b) *reg_b=b; if(reg_c) *reg_c=c;   if(reg_d) *reg_d=d;

          return a; 

}


Check VMware version only


int   VMGetVersion() {

          unsigned long version, magic, command;

          command=VMCMD_GET_VERSION;

          VMBackDoor(&version, &magic, &command,   NULL);

          if(magic==VMWARE_MAGIC) return version;

          else return 0; 

}


Check if running inside VMWare


int IsVMWare() {

          int version=VMGetVersion();

          if(version) return true; else return false; 

}




  위의 코드는 IN명령어를 사용해 VMware의 버전을 알아내는 프로그램이다. 만약 호스트 OS라면 에러 발생 후 예외처리 구문으로 이동하지만 VMware일 경우 정상적으로 버전을 출력할 것이다. 이 밖에도 메모리 크기를 출력하는 방법도 존재한다.


2.2.1.5 그 외


2.2.1.5.1 사용자 이름


  가상 머신에서 최초 운영체제를 설치할 때 사용자의 이름을 등록한다. 대다수의 사용자는 가상머신에서 디폴트로 사용하는 이름이나 가상머신의 이름을 사용한다. 주로 사용되는 이름은 currentuser, sandbox, honey, vmware, nepenthes,  snort, andy, roo 이 있다.


2.2.1.5.2 MAC 주소


  MAC 주소의 상위 3 바이트는 특정 제조사를 나타내는 고유번호를 사용한다. VMware 또한 VMware임을 나타내는 특정 MAC주소를 사용한다. 그 예는 다음과 같다.



  Prefix        Vendor

00:05:69    VMWARE, Inc.

00:0C:29    VMware, Inc.

00:1C:14    VMware,   Inc. 

00:50:56    vmware, inc.

00:05:69    VMWARE,   Inc. 

00:0C:29    VMware, Inc.

00:1C:14    VMware, Inc.

00:50:56    vmware, inc.




그림 14 VMware임을 나타내는 특정 MAC 주소 확인(00:0C:29)



2.2.1.5.3 Interrupt Descriptor Table(IDT) 의 메모리 위치


  프로세서에게 인터럽트 혹은 exception 이 걸렸을 경우에 수행해야 할 핸들러의 주소를 저장해 놓은 것을 인터럽트 혹은 exception vector 라고 한다. 인텔의 프로세서에서는 이러한 인터럽트 혹은 exception 핸들러들의 벡터와 벡터의 정보 등을 저장해 두는 구조체를 IDT(Interrupt Descriptor Table) 라고 부른다. Joaana Rutkowska에 따르면 IDT의 위치는 VMWare의 경우 전형적으로 0xffxxxxxx에 위치하고, VirtualPC는 0xe8ffffff에 위치해있다. 그리고 Host OS의 IDT는 Guest OS보다 낮은 메모리 주소에 위치하며 전형적으로 0x80ffffff(Windows), 0xc0ffffff(Linux)에 위치 한다. 탐지 기준은 IDT 주소가 0xd0000000보다 크면 가상머신으로, 작거나 같으면 호스트 머신이라 판단한다. 단 이 방법은 코어가 여러 개일 경우 정확하지 않다. 다음 그림은 실제 코드를 작성하고 가성머신 상에서 테스트를 해본 결과를 나타낸 그림이다. 

 

그림 15 코드 및 테스트 결과



2.2.1.5.4 메모리 문자열 검색


  가상 머신의 메모리에는 실행중인 프로세스에 의해 가상 머신의 이름이 존재할 수 있다. 확인 하기 위해 램 2GB의 Windows 환경에서 FDPro를 이용해 메모리를 덤프했고 String.exe 를 이용해 문자열 추출했다. “VMware” 검색한 결과 관련 문자열이 9160개 발견되었다. 하지만 이 방법의 경우 Host에도 가상 머신과 관련된 문자열이 존재할 수 있으므로 정확하다고 말할 수 없다.


2.2.2 Anti-VM 우회 기법


  본 절에서는 앞 절에서 기술한 Anti-VM 기법에 대해 우회할 수 있는 방법을 설명한다. 


2.2.2.1 레지스트리


  Anti-VM 기법 중 가장 간단한 방법은 레지스트리에서 가상머신 관련 키워드를 찾아내는 것이었다. 이에 대한 대응으로는 Anti-VM이 찾아내려는 가상머신 키워드를 다른 문자열로 변경하면 간단히 해결할 수 있다. [그림 1]은 VirtualBox에서 Windows 7을 실행하여 레지스트리에서 ’VBOX’라는 키워드를 ’@BOX’라고 바꾼 결과이다. 바뀐 레지스트리는 Guest OS 재부팅 시마다 원래의 값으로 다시 변경되므로, 모든 치환이 완료되면 스냅샷을 저장하도록 한다. 

 

그림 16 VirtualBox 상의 레지스트리 변경 전(상), 후(하)


  직접 레지스트리를 변경하는 방법이 아닌, 검색 자체를 무력화하도록 API를 후킹하는 방법도 있다. 레지스트리를 검색하기 위해선 RegOpenKeyExA()를 호출하는데, 이를 후킹하도록 한다. 하지만 이 방법은 너무 많은 자원을 소비하여 비효율적이다. 


2.2.2.2 프로세스 및 서비스


  VMware의 vmtoolsd.exe처럼 Host OS와 달리 Guest OS에서만 확인 가능한 프로세스가 존재한다. Anti-VM 기법 중 하나는 그 프로세스의 존재 여부를 확인하여 가상머신임을 식별할 수 있는 것이었다. 이에 대응하기 위해선 가상머신 프로세스를 은닉하면 된다. 유저모드에서 프로세스를 확인하기 위해 사용하는 API는 CreateToolhelp32Snapshot(), EnumProcesses()가 있다. 이 두 API는 공통적으로 ZwQuerySystemInformation() API를 호출하므로, Guest OS에서 생성되는 모든 프로세스에 대해 이를 후킹도록 한다. 

  프로세스뿐만 아니라 Guest OS에는 가상머신만의 서비스가 존재하는데, 서비스 조회에는 OpenService()를 이용하므로 이를 후킹한다. 원시적인 방법으로는 가상머신 서비스를 삭제하거나, 가상머신 설정에서 해당 서비스를 사용하지 않도록 설정한다. 하지만 이는 분석자에게 다소 불편을 줄 수 있다. VMware의 경우 vmx에서 다음과 같이 설정을 추가한다.

 

isolation.tools.getVersion.disable = "TRUE"

isolation.tools.getPtrLocation.disable = "TRUE"

isolation.tools.setPtrLocation.disable = "TRUE"

isolation.tools.setVersion.disable = "TRUE"

isolation.tools.getVersion.disable = "TRUE“

monitor_control.disable_directexec = "TRUE"

monitor_control.disable_chksimd = "TRUE"

monitor_control.disable_ntreloc = "TRUE"

monitor_control.disable_selfmod = "TRUE"

monitor_control.disable_reloc = "TRUE"

monitor_control.disable_btinout = "TRUE"

monitor_control.disable_btmemspace = "TRUE"

monitor_control.disable_btseg = "TRUE"

monitor_control.restrict_backdoor = "TRUE"

disable_acceleration = "TRUE"

monitor_control.vt32 = "TRUE"

monitor_control.enable_svm = "TRUE“



2.2.2.3 가상머신 파일


  Guest OS에는 가상머신만의 특정 파일들이 존재하므로, 이를 확인하여 가상머신을 우회하는 방법이 있었다. 파일 존재 여부를 확인하는 GetFileAttributesA()와 CreateFile()를 후킹하고, 가상머신용 파일을 찾을 경우 다른 값을 반환하도록 후킹한다. 


2.2.2.4 특정 명령어


  Guest OS에는 Host OS와 통신하기 위한 가상머신만의 명령어가 있는데, Anti-VM은 이 명령어를 시도하여 가상머신 여부를 확인할 수 있었다. 이에 대해 상시로 메모리를 스캔하면서 가상머신만의 특정 명령어의 시도가 탐지되면 명령어에 브레이크 포인트를 걸고 반환할 레지스터의 값을 Host OS처럼 동적으로 변경하는 방법이 있다. VM 버전을 확인하거나, 메모리 크기를 확인하는 명령에도 이와 같은 방법을 적용할 수 있다. [그림 2]는 VMware I/O 통신 때 필요한 시그니처인 ’VMXh (0x564D5868)‘을 ebx와 비교하려는 시도가 탐지되어, ebx를 0으로 바꾼 것을 보여준다. 하지만 이 방법을 제안한 사람은 IDA를 연동하여 구현하였으며, 그럴 경우 Anti-debugger 기능이 있는 프로그램 자동 분석 시 사용할 수 없을 것이다. 또 다른 대응안은 2.2.2.2절과 같이 가상머신 서비스를 비활성화하는 방법이 있다.


그림 17 ‘VMXh’ 시그니처 확인 무력화를 위한 레지스터 변경


 

2.2.2.5 기타


  앞서 살펴본 방법 이외에도 가상머신임을 유추하지 못하도록 추가적인 설정을 해주어 스냅샷을 저장하도록 한다. Guest OS의 사용자 이름을 가상머신과 관련된 이름으로 설정하지 않도록 하고, MAC 주소를 변경해주도록 한다. 또한, 자동 분석을 우회하기 위한 마우스 클릭 감지 기법을 무력화하도록 지속적인 마우스 클릭 이벤트를 발생시킨다. 더불어, 자동 분석으로부터 의심을 피하기 위해 악성 행위의 실행 시간을 지연하는 악성코드에 대해서는, Sleep()을 후킹하여 몇 초만에 실행하도록 바꾼다. 


2.2.3 Anti-VM 우회 테스트


  본 절에서는 실제로 더미다에서 어떠한 방법으로 Anti-VM을 구현하는지를 확인하는 과정을 거쳤다. 더미다는 OREANS Techonologies의 대표적인 패커상품으로써 코드를 역분석에 보호화하기 위해 상용적으로 사용되는 패커 패키지를 이야기한다. 많은 상용 패커 중 가장 많은 기능을 가지고 있다. 장난 섞인 진담으로는 ‘더미다 패킹이 되어있으면 포기하는게 마음이 편하다.’ 라고 할 정도로 역분석 방지에 강력한 패커이다. 상용 패커 이기는 하지만 보통 악성코드를 제작하는 입장에서는 certification 되어있지 않아도 상관 없기에 제작자들이 많이 사용한다. 더미다 패커에 메인 화면에는 아래 그림과 같이 여러 가지 기능이 있다.


그림 18 더미다 실행 프로그램



  우리는 더미다의 Anti-VM 기능을 분석하기 전 하나의 가정을 세웠다. 더미다로 패킹된 파일은 VMware 에서도 Virtual PC 에서도 모두 Anti-VM을 제공해 주었다. 따라서 Anti-VM 기법중에서 모든 가상머신에서 공통적으로 적용될 수 있는 방법이 사용되었을 것이라고 가정을 세웠다. 그 가정에 의하여 우리는 다음과 같은 순서로 조사를 진행하였다. 패킹된 파일은 윈도우 기본 프로그램 계산기 (calc.exe)를 패킹하여 진행하였다.


1순위 - 레지스트리

2순위 - 프로세스 및 서비스 조회

3순위 - 명령어 조회

4순위 -기타 방법들


  이후엔 실제로 레지스트리 및 프로세스 탐지를 위한 코드를 직접 작성하여 테스트를 해보았다.


2.2.3.1 레지스트리 탐지 코드 (Python)



  레지스트리 존재 여부를 위해 간단한 파이썬 코드를 작성하였다.


그림 19 레지스트리 존재 여부 코드 




  실제 API 후킹 코드는 그림20과 같다. RegOpenKeyEx API를 Hooking 하여 VM 관련 레지스트리를 체크할 경우 1로 리턴된다.


그림 20 실제 API 후킹 코드




  실험환경은 VMware에서 Windows XP Ver3 와 같고, 실제 테스트 결과, 글로벌 API 후킹을 이용하여 레지스트리 탐지를 우회하였다.


그림 21 레지스트리 탐지 결과


2.2.3.2 프로세스 탐지 코드 (C++)


  프로세스를 탐지하기 위해 관련 코드를 작성하였다.


그림 22 프로세스 탐지 관련 코드




  실제 API 후킹 코드는 리버싱 핵심원리 책을 그대로 이용하여 구현하였다. exe 관련코드는 그림22와 동일하고 dll 관련 코드만 다르다.


  테스트 결과, 프로세스는 분명 은닉되었지만 탐지는 실패하였다. 탐지 방법에 대한 이해가 조금 부족하여 제대로 된 코드를 작성하지 못한 것 같다.


그림 23 테스트 결과 화면



3. 연구 결과


3.1 Themida의 Anti-VM 기능이 적용된 계산기 우회 실험


  Anti-VM 기법 중 레지스트리 관련된 경로는 다음과 같다.


○ HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet\Enum\SCSI

○ HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet\disk \Enum

○ HKEY_LOCAL_MACHINE \SYSTEM \ControlSet001 \Control \Class \ {4D36E968-E325-11CE-BFC1-08002BE10318 } \0000

○ HKEY_LOCAL_MACHINE \HARDWARE \DEVICEMAP \Scsi\Scsi Port #\ScsiBus0 \Target Id 0 \Logical Unit Id 0


   위 레지스트리에 있는 경로에 VM에 관련되어 있는 키워드가 있는지를 확인하


그림 24 VMware 관련 레지스트리 경로


였으며, 다음과 같은 경로에서 키워드를 찾을 수 있었다.

  HKEY_LOCAL_MACHINE \SYSTEM \ControlSet001 \Control \Class \ {4D36E968-E325-11CE-BFC1-08002BE10318 } \0000의 DriverDesc 값에서 찾을 수 있었다. 이 값을 지우게 되면 참조 값을 찾을 수 없어 정상적으로 코드가 돌아가지 않는다. 따라서 키 값을 지우기보다는 수정하여 VM이라는 키워드가 아닌 다른 키워드로 수정해주면 정상적으로 Anti-VM을 우회할 수 있었다.

  레지스트리를 수정하고 나서 계산기 프로그램을 실행을 해 본 결과, 계산기는 아직 Anti-VM 기능이 계속 구현되어 있어 실행을 할 수 없었다. 이에 레지스트리 외에도 다른 기법으로 Anti-VM을 구현하였을 것으로 볼 수 있었다. 따라서 가정에 의해서 다음 순위인 프로세스 및 서비스를 조회하여 방법을 우회하였다.


그림 25 Vmware Tools 서비스 관련 코드



그림 25와 같은 코드로 VM 설정에 추가하여 VMware tools 서비스를 종료시키고 다시 프로그램을 실행시킨 결과, 그림 26과 같이 성공적으로 계산기가 켜졌으며, 이로 더미다로 패킹된 Anti-VM 프로그램을 우회하였음을 확인할 수 있다.


그림 26 Anti-VM 우회 후 결과 화면



결론: 더미다가 사용하는 Anti-VM 기능은 레지스트리와 서비스 조회 두 가지를 이용하여 구현한다는 사실을 입증하였다. 


3.2 실효성 검증 및 결론


  Host와 Guest의 가장 큰 차이는 가상 장치의 사용이다. 가상 장치를 사용하기 위해 드라이버나 특정 프로그램을 설치하면 레지스트리와 파일시스템에는 가상머신임을 식별할 수 있는 특정한 값이나 파일이 존재할 수 있다. 이 중에 범용적이고 확실한 정보는 레지스트리, 파일, 프로세스 및 서비스에서 찾을 수 있다.  

  레지스트리를 확인하여 동작하지 않는 Anti VM 프로그램을 우회하기 위해 레지스트리를 탐지하는 API를 수정하였고 그 실효성을 검증하였다. 사용한 방법은 DLL 코드 인젝션을 이용한 글로벌 API 후킹 방식을 사용했고 테스트 결과 조금 느려지는 현상이 나타났다. 디버깅을 이용해 프로세스의 레지스트리 확인 관련 API를 호출을 확인해본 결과 많은 프로세스에서 레지스트리 확인 관련 API를 호출했다. 이 때문에 컴퓨터가 다소 느려졌고 따라서 레지스트리 탐지를 우회하기 위해선 API를 후킹하는 방법보단 실제 레지스트리 값을 바꿔주는 방식이 좀 더 효율적이라고 생각되었다. 

  또는 API 후킹을 적절히 하기 위해 모든 프로세스를 후킹하는 방법이 아닌 프로세스를 실행 시키는 부모 프로세스만 작성한 DLL을 인젝션 시키는 방식 또한 적절할 것으로 생각된다. 또한 지금 사용한 방법은 API 호출 시 들어온 인자 값을 확인해 리턴값을 1로 바꿔주는 방식인데 이 방식의 가장 큰 문제점은 들어오는 인자값이 실제 호스트에도 존재할 경우 문제가 된다는 점이다. 리턴값이 1일 경우 해당 키는 존재하지 않음을 뜻하게 되는데, 실제 문제 없는 프로세스에도 영향을 주므로 적절하지 않은 방법이다. 따라서 리턴 값을 1로 리턴시키는 것이 아닌 호스트와 동일한 값으로 리턴시켜주면 괜찮을 것으로 생각된다.

  루트킷을 이용하는 방법은 VM tools 프로세스를 감출 수 있도록 스텔스 프로세스를 작성하였다. 모든 프로세스의 DLL을 인젝션하여 ZwQuerySystemInformation API를 코드패치를 하였고 VM tools 프로세스를 은폐시켰다. 프로세스 익스플로러를 통해 지금 감춰진 것을 확인할 수 있었지만 VM tools 프로세스를 탐지하는 프로그램을 실행시킨 결과 탐지는 되는 것으로 출력이 되었다. 이 결과는 말씀하신 방법을 저희가 잘못 이해했거나 또는 이 방법으로는 프로세스 탐지를 우회할 수 없음을 보여준다.

  따라서 서비스를 탐지하는 API를 후킹하거나 프로세스 자체를 종료시키는 방법이 효율적으로 생각된다. VM을 실행시키기 전 VM의 설정값을 바꾸어줄 수 있는데, 이를 적용하면 VMtools 프로세스와 서비스가 실행이 되지 않는다. 비록 사용자 입장에선 불편하지만 악성코드 탐지를 위해선 방법 이 간단하고 API를 우회하지 않아도 되므로 컴퓨터 성능 또한 유지시킬 수 있다는 장점이 있다.



4. 참고 문헌


[1] 위키피디아, 윈도 레지스트리, https://ko.wikipedia.org/wiki/윈도_레지스트리

[2] 위키피디아, 프로세스, https://ko.wikipedia.org/wiki/프로세스

[3] VMware, VMware Tools 설치 및 구성, http://www.vmware.com/files/ kr/pdf/vmware-tools-installation-configuration.pdf

[4] Coffer, MAC_Find,  http://www.coffer.com/mac_find/?string=VMware

[5] 커피닉스, Interrupt Descriptor Table, http://coffeenix.net/doc/develop/ ia-interrupt/ch1-1.html

[6] GhostShell, VME 탐지 방법, http://ghostshell.tistory.com/m/post/293

[7] Themida, http://www.oreans.com/Themida.php

[8] An automatic anti-anti-VMware technique applicable for multi-stage packed malware (IEEE, 2008)

[9] 실제 악성코드가 사용하는 VM 탐지 방법, https://www.alienvault.com/ open-threat-exchange/blog/your-malware-shall-not-fool-us-with-those-anti-analysis-tricks

[10] 쿠쿠샌드박스 (Cuckoo sandbox)가 VM탐지하는 악성코드를 우회하는 방법, https://github.com/jaimeblasco/AlienvaultLabs/blob/master/cuckoomon_hardened/cuckoomon_vbox_hardened.patch

[11] 이외의 다양한 종류의 가상머신을 탐지하는 방법, http://artemonsecurity .com/ vmde.pdf



-----------------------------------------------------------------

사용된 소스 코드는 다음과 같다.


AntiAntiVM.zip


'보안 > 악성코드' 카테고리의 다른 글