목차



0. 개요

1. AV의 에뮬레이터 탐지

.... 1.1 Human Interaction

.... 1.2 Timing

.... 1.3 외부의 환경을 이용

.... 1.4 Process Introspection

.... 1.5 만들어진 환경 (Environmental Artifacts)

.... 1.6 감당할 수 없는

.... 1.7 API 함수 결과

2. VM (샌드박스) 탐지

.... 2.1 Human Interaction

.... 2.2 Timing

.... 2.3 외부의 환경을 이용

.... 2.4 Process Introspection

.... 2.5 만들어진 환경

.... 2.6 CPU "Red Pills"

3. Pafish

.... 3.1 기본 정보

.... 3.2 Debuggers detection

.... 3.3 CPU information based detections

.... 3.4 Generic sandbox detection

.... 3.5 Hooks detection

.... 3.6 Sandboxie detection

.... 3.7 Wine detection

.... 3.8 VirutalBox detection

.... 3.9 VMware detection

.... 3.10 Qemu detection

.... 3.11 Bochs detection

.... 3.12 Cuckoo detection

4. 기타

5. 참고자료





0. 개요

  Anti-Emulation이나 Anti-VM 같은 기법들은 인터넷에 많은 자료가 있음에도 불구하고 제대로 정리된 것은 찾아보기 힘든 편이다. 종류가 많기도 하고 이렇게 많은 제품들이 업데이트 또한 자주 하기 때문에 정리가 힘든 것이 이유일 수도 있을것 같다. 


  여기서는 이러한 내용들을 전체적인 분류에서 시작해서 Pafish라는 Anti-VM, Anti-Sandbox 전용 프로그램 분석을 통해 직접적인 구현까지 정리하려고 한다. 물론 오래된 것도 있을 것이고 최근의 것도 있겠지만 여기서 모든 것에 대해 완벽하게 정리할 수는 없을 것 같고 말 그대로 정리로서의 의미만 갖게될 것 같다.





1. AV의 에뮬레이터 탐지

  AV에는 대표적으로 바이너리 에뮬레이터와 스크립트 에뮬레이터가 있다. 따로 표시하지 않은 것은 바이너리 에뮬레이터를 의미한다.


1.1 Human Interaction

  먼저 메시지 후킹을 통해 마우스 클릭 여부를 기다린 후 일반적인 환경에서 사용자가 마우스를 클릭하듯이 클릭을 확인하면 이 때 악의적인 기능이 활성화되는 방식이 있다. 또한 대화 상자를 보여주고 버튼이 클릭된 경우라던지, 문서 파일의 경우 스크롤을 어느 정도 이상 내리면 활성화되는 방식도 존재한다.


  생각해보지 못한 방식도 있었는데 웹 브라우저의 히스토리를 확인한다던가 최근에 열린 파일들이 있는지 그 외에도 로그인 시간 검사 등도 여기에 포함될 수 있다. 이러한 방식들은 VM에서도 똑같이 적용된다.



1.2 Timing

  기본적으로 sleep() 함수를 이용해 긴 시간을 기다리게 하는 방식인데 이것은 에뮬레이터나 샌드박스에서 대개 주어진 시간이 있기 때문이다. 또한 특정 날짜나 시간에 활성화되는 방식도 존재한다. 참고로 이 방식은 자주 사용되서인지 시간 관련 함수들에 대한 패치가 많은 것 같다. 에뮬레이터의 경우 반환 값으로, 가상머신의 경우 함수에 대한 후킹을 통해 제어해서 요즘은 간단한 방식은 잘 먹히지 않는다고 한다.



1.3 외부의 환경을 이용

  에뮬레이터는 그렇다고 치더라도 샌드박스 환경에서도 가상 머신들이 가상 네트워크에 연결되어 있는 경향이 있다. 다시 말해서 악성코드를 직접 실행하는 환경이더라도 인터넷의 연결은 허용하지 않는 경우가 대부분이다. 이 경우에는 에뮬레이터처럼 직접 결과를 반환시켜 준다.


  이렇게 에뮬레이터나 가상 환경에서는 인터넷 연결을 허용치 않는 대신 성공했다는 결과를 반환해준다는 것을 악용하여 존재하지 않는 url에 접속한 후 성공한 경우에 가상 환경이라는 것을 탐지하는 방식을 사용할 수 있다. 또는 특정한 사이트의 특정한 파일에 대한 해시값을 가지고 있다가 인터넷을 연결하여 그 파일을 다운로드한 후 그 값을 비교하는 방식도 있다. 보통 에뮬레이터나 샌드박스 환경에서는 이러한 경우에 직접 생성한 파일을 주는 것을 악용한 방식이라고 한다.


  참고로 먼저 앞에서 설명한 Timing 방식에서도 시간을 웹 같은 외부에서 얻는 방식을 사용할 수도 있다.



1.4 Process Introspection

  프로세스 내부의 여러 상태를 검사하는 방식이다. 예를들어 API 호출 이후 레지스터들의 상태라던지 프로세스 구조체들, 초기화되지 않은 메모리, 로드된 DLL 검사 등이 존재한다. DLL의 경우 로더를 확인하여 실제 로더로 실행되는지를 확인한다. 이 외에도 라이브러리에서 함수들 사이의 패딩의 값을 검사하기도 한다(int 3). 또한 로드된 DLL의 종류를 확인하는 방식도 있다.



1.5 만들어진 환경 (Environmental Artifacts)

  실행되는 환경을 통해 탐지하는 방식으로서 많은 부분들이 사용될 수 있다. 대표적으로 악성코드가 애플리케이션의 취약점을 사용하는 경우 특정한 버전에서만 통하는 경우가 많다. 그러므로 특정한 버전이 아닌 경우에는 실행시키지 않아서 악성코드로 인식하지 못할 수도 있다. 이것은 가상 머신에서도 마찬가지이다.


  또는 argv[0]을 통해 본 프로세스의 이름을 구해서 프로세스나 바이너리의 이름이 자체적으로 변경되어 실행되는 경우를 이용할 수도 있다. 또는 자식 프로세스로 자기 자신의 바이너리를 실행시켜서 자식 프로세스로 실행된 경우에만 악의적인 행위를 수행하게 할 수도 있는데 이것은 가상 환경에서 부모 프로세스만을 스캐닝하는 경우를 악용한 방식이다.


  하지만 이것은 특별한 경우이고 악성코드의 입장에서는 수 많은 부분을 통해 현재 실행되는 환경이 에뮬레이터인지를 파악할 수 있다. 에뮬레이터의 경우에는 여러 환경을 직접 구현해주어야 하는 방식이므로 악성코드와 관련이 없는 부분이지만 일반적인 컴퓨터 환경에서는 존재하는 파일이나 레지스트리 등을 검색하여 없을 경우에 그것을 의심해볼 수 있는 것이다.


  예는 일일이 나열하기도 힘들 정도인데 대표적으로 레지스트리 값이나 시스템 파일들 같이 일반적인 컴퓨터 환경에서는 존재하지만 에뮬레이터에서는 구현하지 않았을 것으로 보이는 내용을 조회하여 그 존재 여부에 따라 판단할 수도 있다. 이 두가지 외에도 프로세스 이름도 잇을 수 있으며 만약 AV가 프로세스 목록에 특정한 프로세스를 보여주게 만들었다고 하더라도 해당 바이너리 또한 조회하여 존재하지 않는 경우가 있을 수도 있다.


  또는 조금 다른 예로 MAC 주소가 특정한 값들의 집합으로 하드코딩되어 있고 그것을 아는 경우에는 MAC 주소를 조회하여 그 주소에서는 활성화되지 않게 함으로써 우회하는 방식도 존재한다.



1.6 감당할 수 없는

  이 방식은 sleep을 이용해 주어진 한계 시간을 초과하여 에뮬레이터나 샌드박스를 우회하는 방식과 비슷하다. 예를들어서 큰 크기의 메모리를 malloc()으로 할당거나 (더 나아가 memset()을 이용해 간단한 내용을 더 추가할 수도 있다) 루프문의 반복을 감당할 수 없을 정도로 설정하는 것이다. 물론 이것은 일반적인 컴퓨팅 환경이나 가상 머신에서는 CPU가 충분히 감당할 수 있어 실질적으로는 사용자가 인식하지는 못할 정도의 범위를 사용한다. 하지만 에뮬레이터의 경우에는 그렇지 않다.



1.7 API 함수 결과

  API 함수를 호출하는 부분이 있다면 OS를 통해 직접 실행하는 대신 에뮬레이터는 이 결과를 대신 반환해 준다. 하지만 제대로된 결과(반환 값 뿐만 아니라 에러 코드도 포함)가 아니라던지 일반적으로 실패해야 하는데 성공한다던지 하는 것을 기반으로 에뮬레이터의 존재를 확인할 수 있다. 예를들어 너무나 방대한 윈도우의 API를 이용한 방식으로서 거의 사용되지는 않지만 에뮬레이터에서는 구현하지 않았을 것으로 여겨지는 함수를 실행하여 성공한 경우에만 활성화시키는 방식이 있다.


  또 다른 예로서 악성코드가 일반 사용자 권한으로 실행된다는 가정 하에 만약 OpenProcess()를 통해 시스템 프로세스의 핸들을 얻는 경우에는 실패할 수 밖에 없다. 하지만 AV의 에뮬레이터가 이러한 권한을 고려하지 않고 성공한 값을 준다면 이것은 우회하는데 사용할 수 있다.





2. VM (샌드박스) 탐지

2.1 Human Interaction



2.2 Timing



2.3 외부의 환경을 이용



2.4 Process Introspection

  VM 환경에서도 일반적인 환경과 프로세스 내의 다른 점을 발견할 수 있다. 유저 모드 API 후킹을 사용하는 경우 후킹 엔진(dll)이 삽입되며 kernel32.dll이나 ntdll.dll 등의 라이브러리에서 후킹 엔진으로 분기하는 부분이 존재하는데 이 경우 원래 라이브러리 코드와 비교하여 차이점을 통해 구별할 수 있다. 또한 후킹 엔진이 인젝션되었으므로 로드된 DLL의 종류를 확인하는 방식도 있다.



2.5 만들어진 환경

  취약점 부분이라던지 프로세스 이름 관련 부분은 에뮬레이터와 마찬가지일 것이다. 하지만 다른 환경의 경우에는 에뮬레이터와는 정 반대인데 위에서 설명했듯이 에뮬레이터를 우회하기 위해서는 에뮬레이터가 모든 것을 구현하지 못했을 것이라는 가정 하에, 있어야 할 것이 없는 것을 통해 판단했었다. 하지만 가상 머신의 경우에는 일반적인 컴퓨터 환경과 비교하여 없는 부분을 찾는 것은 그다지 의미가 없을 것이다. 대신 반대로 가상 머신에서만 존재하는 것 또는 가상 머신에서만 가질 수 있는 환경을 비교하는 방식을 사용한다. 이 부분은 아래에 구체적인 대상을 가지고 설명하도록 하겠다.



2.6 CPU "Red Pills"

  어떤 명령어의 경우 실제 환경의 CPU에서 실행될 때 동작하는 것과 가상 환경에서의 행위가 다르다. 이 경우 이 명령어를 사용하여 결과를 통해 구별한다.





3. Pafish

  Paranoid Fish는 샌드박스나 가상 머신 같은 가상 환경을 검사해주는 툴이다. 내용도 간단하고 소스 코드도 잘 정리되어 있기 때문에 직접 확인할 수도 있겠지만 여기에서 정리하는 의미로 검사 방식들을 정리하고자 한다.


  사실 여기에 포함되지 않지만 인터넷에는 여러 자료들이 존재한다. 이러한 것들을 모두 테스트해 볼 여력이 되지 않기 때문에 pafish의 내용을 공식적인 내용 쯤으로 가정하고 인터넷의 내용들은 추가적인 설명으로 덧붙이기로 하겠다.



3.1 기본 정보

3.1.1 윈도우 버전


3.1.2  CPU Vendor

  "GenuineIntel" 같은 결과가 나온다.


3.1.3 CPU Hyperviser Vendor

  "VBoxVBoxVBox" 같은 결과가 나온다.


3.1.4 CPU Brand

  "Intel<R> Core<TM> i5-5200U CPU @ 2.20GHz" 같은 결과가 나온다.



3.2 Debuggers detection

3.2.1 Using IsDebuggerPresent()

  현재 프로세스가 디버깅 중인지를 판단하는 방식이므로 가상 환경 탐지와는 관련이 없어보인다.


3.2.2 Using OutputDebugString()

  이 방식은 윈도우 비스타 이전의 경우에만 사용된다. 위와 같이 디버거 탐지에 사용되는 방식으로서 Last Error Value를 설정한 후 OutputDebugString()을 호출하는데 만약 디버거가 붙어있다면 해당 값은 변화가 없을 것이며 디버거가 붙어있지 않아서 실패한다면 거기에 해당하는 에러 코드가 Last Error Value에 설정되어 이전 값과 차이가 발생할 것이다. 안티 디버깅으로서 전과 후의 값을 비교하여 변화가 없을 때 디버깅 중으로 판단한다.


  참고로 SetLastError()와 GetLastError()로 Last Error Value를 설정/확인하거나 아니면 직접 FS:[0x34]를 이용할 수도 있다.



3.3 CPU information based detections

3.3.1 Checking the difference between CPU timestamp counters (rdtsc)

  rdtsc 명령어를 이용한 전형적인 안티 VM 방식이다. 두 rdtsc 명령어를 연속으로 사용한 후 그 값의 차이를 구하는데 가상 머신에서 실행되는 경우에는 일반적인 실제 머신에서 실행되는 환경보다 그 값의 차이가 크다는 (즉 더 많은 시간을 요구한다는) 특징을 이용한다. 지정한 값보다 큰 경우에는 가상 머신 환경에서 실행 중인 것으로 탐지한다.


3.3.2 Checking the difference between CPU timestamp counters (rdtsc) forcing VM exit

  앞과 비슷하지만 rdtsc 명령어 사이에 cpuid 명령어가 추가되어 있다. (물론 명령어가 하나 더 추가되었으므로 앞의 방식보다는 비교할 값이 조금은 더 크다) cpuid는 VM과 Hypervisor 사이에 문맥을 전환시켜주는 명령어로써 이것을 실행하면 trap이 유발되며 더 많은 딜레이 즉 시간이 요구된다.


  참고로 cpuid는 인자를 받을 때 eax를 사용한다. 여기서는 eax에 0을 넣고 cpuid 명령어를 실행하여 CPU Vendor ID String을 받았다. 물론 이 값을 구하려는 목적 보다는 단지 cpuid 명령어를 실행시키려는 목적을 가지고 있었기 때문에 반환된 값들은 사용되지 않았다.


3.3.3 Checking hypervisor bit in cpuid feature bits

  eax에 1(CPUID_GETFEATURES)을 넣고 cpuid를 호출한다. 실행 후 ecx의 31번째 비트가 1로 설정되어 있는지 검사한다. Hypervisor와 Physical CPU들은 이 비트를 0으로 설정하지만 게스트 운영 체제는 1로 설정되어 있다. 이 값이 1인 경우 가상 머신 환경으로 탐지한다.


3.3.4 Checking cpuid hypervisor vendor for known VM vendors

  "3.1.3 CPU Hyperviser Vendor"의 결과가 알려진 VM 벤더들인지를 검사한다. 다음의 표로 정리한다. 예를들면 KVM을 사용하는 경우에는 문자열 "KVMKVMKVM"을 얻게되고 이를 통해 가상 환경인지 여부를 판단할 수 있는 것이다.


벤더 이름 : 출력 결과

KVM : KVMKVMKVM

Microsoft Hyper-V or Windows Virtual PC : Microsoft Hv

VMware : VMwareVMware

Xen : XenVMMXenVMM

Parallels : prl hyperv

VirtualBox : VBoxVBoxVBox



3.4 Generic sandbox detection

3.4.1 Using mouse activity

  GetCursorPos() API 함수를 호출하여 마우스 커서의 위치를 구한 후 Sleep()하고 다시 마우스 커서 위치를 구하여 차이가 있는지를 비교한다. 없다면 샌드박스 환경으로 탐지한다.


3.4.2 Checking username

  GetUserName() API 함수를 통해 사용자 이름 문자열을 얻은 후 다음의 문자열과 비교한다.


SANDBOX

VIRUS

MALWARE


3.4.3 Checking file path

  GetModuleFileName() API 함수로 이 파일이 위치하는 경로를 구한 후 다음의 경로와 비교한다.


\SAMPLE

\VIRUS

\SANDBOX


3.4.4 Checking common sample names in drives root

  C:\ 같은 drive root에 "sample.exe", "malware.exe"라는 일반적인 샘플 이름을 갖는 파일이 존재하는지 검사한다.


3.4.5 Checking if disk size <= 60GB via DeviceIoControl()

  DeviceIoControl() API 함수를 이용하여 디스크의 크기가 60GB 이하인지 검사한다. 일반적으로 요즘 60GB 보다 적은 용량을 갖는 컴퓨터들이 잘 없으며 샌드박스 환경에서는 어느 정도 이상의 용량을 할당하지 않는다는 특징을 이용하는 것으로 보인다.


3.4.6 Checking if disk size <= 60GB via GetDiskFreeSpaceExA()

  GetDiskFreeSpaceExA() API 함수를 이용하여 디스크의 크기를 검사한다.


3.4.7 Checking if Sleep() is patched using GetTickCount()

  sleep() 함수를 이용하여 샌드박스를 우회하는 방식이 존재한다. 악의적인 행위 없이 오랫동안 대기하게 하여 이를 분석하는 샌드박스가 지정된 시간 동안 악성 행위를 탐지하지 못하게 하는 방식이다. 이를 보완하기 위해 요즘 샌드박스는 sleep() 함수를 후킹하여 오랜 시간 동안 대기하지 못하게 하는데 이렇게 sleep() 함수가 패치되었는지 여부를 GetTickCount()를 이용하여 검사한다.


  두 GetTickCount() 사이에 sleep() 함수를 호출하는데 만약 두 GetTickCount()의 차이가 sleep()에 인자로 넣은 시간과 비교해서 주어진 정도보다 크다면 sleep() 함수가 패치되었다고 판단하는 것이다.


3.4.8 Checking if NumberOfProcessors is < 2 via raw access

  PEB의 "0x064 DWORD NumberOfProcessors;" 멤버를 이용하여 프로세서의 수를 구한다. 프로세서의 수가 2개 미만이면 샌드박스 환경으로 탐지한다. 대부분 컴퓨터가 듀얼 코어 환경이라서 그런것 같으며 샌드박스 환경 구성 시에 가상 머신에서 프로세서를 하나로 설정하는 것이 일반적인가 보다.


  32비트 환경에서 FS 레지스터를 이용하여 PEB의 NumberOfProcessors 인자를 구하는 루틴은 다음과 같다. FS 레지스터 관련 내용은 다음을 참고한다. [ http://sanseolab.tistory.com/47 ]


MOV EAX, DWORD PTR FS:[18]

MOV EAX, DWORD PTR DS:[EAX+30]

MOV EAX, DWORD PTR DS:[EAX+64]


3.4.9 Checking if NumberOfProcessors is < 2 via GetSystemInfo()

  위와 같지만 직접 FS 레지스터를 이용하는 것이 아니라 GetSystemInfo() API 함수를 통해 SYSTEM_INFO 구조체를 구하고 이후 dwNumberOfProcessors 멤버를 통해 프로세서의 수를 구한다.


3.4.10 Checking if pysical memory is < 1Gb

  GlobalMemoryStatusEx() API 함수를 이용해 MEMORYSTATUSEX 구조체를 구한 후 이 구조체의 ullTotalPhys 멤버를 통해 물리 메모리를 구한다. 이후 물리 메모리의 크기가 1Gb보다 적은지 비교한 후 적다면 샌드박스 환경으로 탐지한다.


3.4.11 Checking operating system uptime using GetTickCount()

  GetTickCount() API 함수는 시스템이 부팅된 이후부터 지금까지의 시간을 반환해준다. 그 값을 구한 후에 12분보다 적은지를 비교한다. 만약 부팅 이후 12분 이상이 흐르지 않았다면 샌드박스 환경으로 탐지한다.


3.4.12 Checking if operating system IsNativeVhdBoot()

  IsNativeVhdBoot() API 함수를 이용해 VHD(Virtual Hard Disk)를 탐지한다. 일반적인 가상 머신의 경우 VHD 메커니즘을 이용해 하드 디스크를 제공하기 때문인 것으로 보인다. 이 함수는 VHD를 통해 부팅된 경우에는 1을 반환하며 아니라면 0을 반환한다. 만약 1을 반환 즉 VHD를 통해 부팅된 경우에는 샌드박스 환경으로 탐지한다.


  참고로 그냥 호출하는 것은 아니고 직접 GetModuleHandleA()와 GetProcAddress()를 이용하여 IsNativeVhdBoot() 함수를 구한 후 호출한다. 아마도 이 함수가 후킹되었거나 에뮬레이터에서 이 함수 호출 시에 0을 반환하도록 만들어졌을 수도 있으므로 그것을 우회하기 위함으로 보인다.



3.5 Hooks detection

3.5.1 Checking function ShellExecuteExW method 1

  ShellExecuteExW() 함수가 후킹되었는지 여부를 판단하여 후킹되었을 시 샌드박스 환경으로 인식한다.


  MS 윈도우에서 제공하는 라이브러리에 존재하는 각 API 함수들은 처음에 "MOV EDI, EDI" 명령어로 시작된다. 이것은 MS가 재부팅 과정 없이 패치를 수행하기 위해 즉 핫패칭을 위해 인라인 후킹이 더욱 쉬워질 수 있게 제공하였다고 한다. 즉 "mov edi, edi", "push ebp", "mov ebp, esp" 명령어가 5바이트인데 인라인 후킹 시 이 5바이트를 jmp 명령어로 바꾸어 후킹을 쉽게 할 수 있도록 만들어준 것이다. 사실 목적까지 자세히 찾아보지는 않았으므로 확실하지는 않다.


  어쨌든 가장 처음 즉 "mov edi, edi"는 0x8b, 0xff이다. 올리디버거로 보면 이 부분의 옵코드가 8BFF인 것을 볼 수 있다. pafish는 이렇게 "mov edi, edi" 부분이 그대로 존재하는지 즉 ShellExecuteExW() API 함수의 첫 부분이 후킹되지 않고 그대로 8BFF로 존재하는지를 검사한다. 만약 후킹되어서 다른 값을 갖는다면 샌드박스 환경으로 탐지한다.


3.5.2 Checking function CreateProcessA method 1

  CreateProcessA() API 함수라는 대상만 다르고 메커니즘은 위와 같다. 



3.6 Sandboxie detection

3.6.1 Using GetModuleHandle(sbiedll.dll)

  GetModuleHandle() API 함수를 이용해 sbiedll.dll을 구한다. 만약 이 DLL이 메모리에 로드되어 있다면 구하는데 성공할 것이고 샌드박스 환경으로 탐지한다. 이것은 Sandboxie라는 샌드박스가 사용하는 라이브러리로서 일반적인 환경에서는 프로세스에 로드될 일이 없다. Sandboxie는 특정한 목적을 위해 프로세스에 이 DLL을 인젝션한다.


  이 DLL은 많은 기능을 제공하는것 같은데 사용해보지는 않았지만 대표적인 것이 유저 모드 함수에 대한 후킹 기능으로 보인다. AV나 HIPS 등에서 API 후킹을 위해 DLL을 인젝션하는 것은 여러 글에서 이미 적어 놓았다.


[ http://sanseolab.tistory.com/33 ] 4.2 참고

[ http://sanseolab.tistory.com/35 ]

[ http://sanseolab.tistory.com/39 ]


  Sandboxie의 sbiedll.dll 외에도 비슷한 많은 것들이 존재한다고 한다. pafish에는 없는 내용이며 모두 확인해보지는 않았지만 적어보도록 하겠다. VMware는 dbghelp.dll을, SunBelt SandBox는 api_log.dll, dir_watch.dll, pstorec.dll을, Virtual PC는 wmcheck.dll을 마지막으로 WPE Pro는 wpespy.dll이 인젝션된다고 한다.



3.7 Wine detection

3.7.1 Using GetProcAddress(wine_get_unix_file_name) from kernel32.dll

  WINE은 오픈소스 윈도우 API 호환 계층이다. 즉 윈도우 API에 대한 호환을 지원하기 위해 DLL들도 오픈소스로 개발할 수 밖에 없는데 당연히 가장 중요한 라이브러리 중 하나인 kernel32.dll도 거기에 포함될 것이다. 와인에서 실행 중일 경우 구현한 kernel32.dll이 로드될 것이고 GetProcAddress() API 함수를 호출하여 wine_get_unix_file_name()라는 함수를 구한다. 일반적인 윈도우 환경이라면 kernel32.dll에 이 함수는 존재하지 않을 것이기 때문에 해당 호출은 실패하게 되지만 와인에서 제공되는 kernel32.dll에서는 어떤 이유에서인지 이 함수가 구현되어 있어서 호출이 성공한다. 만약 호출이 성공한다면 샌드박스 환경으로 탐지한다.


3.7.2 Reg key (HKCU\\SOFTWARE\\Wine)

  와인이 설치된 경우 레지스트리에 "HKCU\\SOFTWARE\\Wine" 키가 등록되는 것으로 보인다. 해당 레지스트리 키가 존재하는 경우에는 샌드박스 환경으로 탐지한다.



3.8 VirutalBox detection

3.8.1 Scsi port->bus->target id->logical unit id-> 0 identifier

  레지스트리 키 "HKLM<\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical> Unit Id 0"에서 값(이름)이 "Identifier"이며 데이터가 "VBOX"인 것을 찾으면 VirtualBox로 탐지한다.


3.8.2 Reg key (HKLM\\HARDWARE\\Description\\System \"SystemBiosVersion\)

  레지스트리 키 "HKLM\\HARDWARE\\Description\\System"에서 값이 "SystemBiosVersion"이며 데이터가 "VBOX"인 것을 찾으면 VirtualBox로 탐지한다.


3.8.3 Reg key (HKLM\\SOFTWARE\\Oracle\\VirtualBox Guest Additions)

  레지스트리 키 "HKLM\\SOFTWARE\\Oracle\\VirtualBox Guest Additions"를 찾으면 VirtualBox로 탐지한다.


3.8.4 Reg key (HKLM\\HARDWARE\\Description\\System \"VideoBiosVersion\")

  레지스트리 키 "HKLM\\HARDWARE\\Description\\System"에서 값이 "VideoBiosVersion"이며 데이터가 "VIRTUALBOX"인 것을 찾으면 VirtualBox로 탐지한다.


3.8.5 Reg key (HKLM\\HARDWARE\\ACPI\\DSDT\\VBOX__)

  레지스트리 키 "HKLM\\HARDWARE\\ACPI\\DSDT\\VBOX__"를 찾으면 VirtualBox로 탐지한다.


3.8.6 Reg key (HKLM\\HARDWARE\\ACPI\\FADT\\VBOX__)

  레지스트리 키 "HKLM\\HARDWARE\\ACPI\\FADT\\VBOX__"를 찾으면 VirtualBox로 탐지한다.


3.8.7 Reg key (HKLM\\HARDWARE\\ACPI\\RSDT\\VBOX__)

  레지스트리 키 "HKLM\\HARDWARE\\ACPI\\RSDT\\VBOX__"를 찾으면 VirtualBox로 탐지한다.


3.8.8 Reg key (HKLM\\SYSTEM\\ControlSet001\\Services\\VBox*)

  다음의 레지스트리 키 중 하나 이상을 찾으면 VirtualBox로 탐지한다.

"HKLM\\SYSTEM\\ControlSet001\\Services\\VBoxGuest"

"HKLM\\SYSTEM\\ControlSet001\\Services\\VBoxMouse"

"HKLM\\SYSTEM\\ControlSet001\\Services\\VBoxService"

"HKLM\\SYSTEM\\ControlSet001\\Services\\VBoxSF"

"HKLM\\SYSTEM\\ControlSet001\\Services\\VBoxVideo"


3.8.9 Reg key (HKLM\\HARDWARE\\DESCRIPTION\\System \"SystemBiosDate\")

  레지스트리 키 "HKLM\\HARDWARE\\DESCRIPTION\\System"에서 값이 "SystemBiosDate"이며 데이터가 "06/23/99"인 것을 찾으면 VirtualBox로 탐지한다.


3.8.10 Driver files in C:\\WINDOWS\\system32\\drivers\\VBox*

  다음의 파일 중 하나 이상을 찾으면 VirtualBox로 탐지한다.

"C:\\WINDOWS\\system32\\drivers\\VBoxMouse.sys"

"C:\\WINDOWS\\system32\\drivers\\VBoxGuest.sys"

"C:\\WINDOWS\\system32\\drivers\\VBoxSF.sys"

"C:\\WINDOWS\\system32\\drivers\\VBoxVideo.sys"


3.8.11 Additional system files

  다음의 파일 중 하나 이상을 찾으면 VirtualBox로 탐지한다.

"C:\\WINDOWS\\system32\\vboxdisp.dll"

"C:\\WINDOWS\\system32\\vboxhook.dll"

"C:\\WINDOWS\\system32\\vboxmrxnp.dll"

"C:\\WINDOWS\\system32\\vboxogl.dll"

"C:\\WINDOWS\\system32\\vboxoglarrayspu.dll"

"C:\\WINDOWS\\system32\\vboxoglcrutil.dll"

"C:\\WINDOWS\\system32\\vboxoglerrorspu.dll"

"C:\\WINDOWS\\system32\\vboxoglfeedbackspu.dll"

"C:\\WINDOWS\\system32\\vboxoglpackspu.dll"

"C:\\WINDOWS\\system32\\vboxoglpassthroughspu.dll"

"C:\\WINDOWS\\system32\\vboxservice.exe"

"C:\\WINDOWS\\system32\\vboxtray.exe"

"C:\\WINDOWS\\system32\\VBoxControl.exe"

"C:<\\program files\\oracle\\virtualbox guest additions\\>"


3.8.12 Looking for a MAC address starting with 08:00:27

  08:00:27로 시작하는 MAC 주소를 찾으면 VirtualBox로 탐지한다.


3.8.13 Looking for pseudo devices

  다음의 pseudo 디바이스들 중 하나 이상을 찾으면 VirtualBox로 탐지한다.

"\\\\.\\VBoxMiniRdrDN"

"\\\\.\\pipe\\VBoxMiniRdDN"

"\\\\.\\VBoxTrayIPC"

"\\\\.\\pipe\\VBoxTrayIPC"


3.8.14 Looking for VBoxTray windows

  FindWindow() API 함수로 다음의 두 VBoxTray 윈도우 중 하나 이상을 찾으면 VirtualBox로 탐지한다.

"VBoxTrayToolWndClass"

"VBoxTrayToolWnd"


3.8.15 Looking for VBox network share

  WNetGetProviderName() API 함수에 WNNC_NET_RDR2SAMPLE를 인자로 넣고 호출하여 provider가 "VirtualBox Shared Folders"이면 VirtualBox로 탐지한다. 공유 네트워크를 검사한다고 하는데 자세한 내용은 모르겠다.


3.8.16 Looking for VBox processes (vboxservice.exe, vboxtray.exe)

  다음의 프로세스를 검사하여 찾을 시 VirtualBox로 탐지한다.

"vboxservice.exe"

"vboxtray.exe"


3.8.17 Looking for VBox devices using WMI

  WMI도 SQL과 비슷한 WQL(WMI Query Language)가 지원된다. "SELECT DeviceId FROM Win32_PnPEntity" 쿼리문으로 조회한 "DeviceId""PCI\\VEN_80EE&DEV_CAFE"라면 VirtualBox로 탐지한다.

  



3.9 VMware detection

3.9.1 Scsi port 0,1,2 ->bus->target id->logical unit id-> 0 identifier

  각각 다음의 레지스트리 키, 값 그리고 데이터가 존재하는 경우 VMware로 탐지한다.

"HKLM<\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical> Unit Id 0"      "Identifier"      "VMWARE"

"HKLM<\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical> Unit Id 0"      "Identifier"      "VMWARE"

"HKLM<\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical> Unit Id 0"      "Identifier"      "VMWARE"


3.9.2 Reg key (HKLM\\SOFTWARE\\VMware, Inc.\\VMware Tools)

  레지스트리 키 "HKLM\\SOFTWARE\\VMware, Inc.\\VMware Tools"를 찾으면 VMware로 탐지한다.


3.9.3 Looking for C:\\WINDOWS\\system32\\drivers\\vmmouse.sys

  파일 "C:\\WINDOWS\\system32\\drivers\\vmmouse.sys"를 찾으면 VMware로 탐지한다.


3.9.4 Looking for C:\\WINDOWS\\system32\\drivers\\vmhgfs.sys

  파일 "C:\\WINDOWS\\system32\\drivers\\vmhgfs.sys"를 찾으면 VMware로 탐지한다.


3.9.5 Looking for a MAC address starting with 00:05:69, 00:0C:29, 00:1C:14 or 00:50:56

  MAC 주소가 다음의 주소들 중 하나로 시작하면 VMware로 탐지한다.

"00:05:69"

"00:0C:29"

"00:1C:14"

"00:50:56"


3.9.6 Looking for network adapter name

  네트워크 어댑터 이름이 "VMware"이면 VMware로 탐지한다.


3.9.7 Looking for pseudo devices

  다음의 pseudo 디바이스들 중 하나 이상을 찾으면 VMware로 탐지한다.

"\\\\.\\HGFS"

"\\\\.\\vmci"


3.9.8 Looking for VMware serial number

  "SELECT SerialNumber FROM Win32_Bios" 쿼리문으로 조회한 후 "SerialNumber""VMware"라면 VMware로 탐지한다.



3.10 Qemu detection

3.10.1 Scsi port->bus->target id->logical unit id-> 0 identifier

  레지스트리 키 "HKLM<\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical> Unit Id 0"에서 값이 "Identifier"이며 데이터가 "QEMU"인 것을 찾으면 QEMU로 탐지한다.


3.10.2 Reg key (HKLM\\HARDWARE\\Description\\System \"SystemBiosVersion\")

  레지스트리 키 "HKLM\\HARDWARE\\Description\\System"에서 값이 "SystemBiosVersion"이며 데이터가 "QEMU"인 것을 찾으면 QEMU로 탐지한다.


3.10.3 cpuid CPU brand string 'QEMU Virtual CPU'

  CPU Brand가 "QEMU Virtual CPU"라면 QEMU로 탐지한다.



3.11 Bochs detection

3.11.1 Reg key (HKLM\\HARDWARE\\Description\\System \"SystemBiosVersion\")

  레지스트리 키 "HKLM\\HARDWARE\\Description\\System"에서 값이 "SystemBiosVersion"이며 데이터가 "BOCHS"인 것을 찾으면 Bochs로 탐지한다.


3.11.2 cpuid AMD wrong value for processor name

  CPU Brand가 "AMD Athlon(tm) processor"라면 Bochs로 탐지한다.


3.11.3 cpuid Intel wrong value for processor name

  CPU Brand가 "              Intel(R) Pentium(R) 4 CPU        "라면 Bochs로 탐지한다.



3.12 Cuckoo detection

3.12.1 Looking in the TLS for the hooks information structure

  Cockoo 샌드박스에서 구현한 후킹 관련된 내용을 탐지하는 기법이다. 관련 내용을 완벽히 이해하지 못해서 자세한 글은 쓰지 못하지만 나중에 공부한 후에 추가하도록 하겠다.





4. 기타

  IDT(Interrupt Descriptor Table), LDT(Local Descriptor Table), GDT(Global Descriptor Table)을 이용한 방식은 대표적이지만 최신 버전의 VM에서는 통하지 않는 경향이 있다고 하여 정리를 하지 않았다. 이것과 관련된 어셈블리 명렁어는 각각 sidt, sldt, sgt 이다. 


  VMware와 관련해서는 x86의 STR 어셈블리 명령어도 사용되는데 이것은 Task Register로부터 Segment Selector를 저장하는 명령어로서 VMware에서는 첫 번째와 두 번째 비트가 각각 0x00과 0x40이라고 한다. 


  마지막으로 어셈블리 in 명령어도 있는데 VMware의 게스트 OS에서는 이 명령어를 사용할 시에 예외가 발생되지 않고 ebx에 "VMXh"라는 고유한 문자열이 저장되는 것을 이용한 방식이라고 한다. 참고로 이 명령어는 I/O 포트 (호스트 OS와 게스트 OS 간 데이터를 주고 받을 수 있는 채널)를 지원하기 위한 명령어라고 한다.

http://kali-km.tistory.com/search/anti%20virtual%20machine ]


  Parallels는 macOS의 가상화 프로그램이다. 이것은 "prl_cc.exe", "prl_tools.exe"라는 패러렐즈 전용 프로세스 이름을 검사하여 탐지할 수 있다. VirtualPC의 경우도 마찬가지로서 "VMSrvc.exe", "VMUSrvc.exe"를 검사한다. 마지막으로 Xen은 "xenservice.exe"를 검사한다.


  추가적으로 해야할 사항으로서 VMware에서 다음과 같은 기능을 제공하여 Anti-VM 기법에 대응하는 것 같은데 아직 제대로 찾아보고 직접 테스트해보지 않아서 이후에 정리하려고 한다.


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_btpriv = "TRUE"

monitor_control.disable_btseg = "TRUE"


  마지막으로 지금까지 살펴본 내용이 아닌 여러 다른 방식들도 생겨나고 있다.

http://blog.trendmicro.com/trendlabs-security-intelligence/new-emotet-hijacks-windows-api-evades-sandbox-analysis/ ]

https://www.zscaler.com/blogs/research/malicious-documents-leveraging-new-anti-vm-anti-sandbox-techniques ]





5. 참고자료

i. FireEye

영어 ]  HOT KNIVES THROUGH BUTTER: Evading File-based Sandboxes -  Abhishek Singh and Zheng Bu [ https://www.fireeye.com/content/dam/fireeye-www/current-threats/pdfs/pf/file/fireeye-hot-knives-through-butter.pdf ]

한글 ]  파일 기반의 샌드박스를 쉽게 회피하는 악성코드 [ https://www.fireeye.kr/content/dam/fireeye-www/regional/ko_KR/current-threats/pdfs/fireeye-hot-knives-through-butter.pdf ]


ii. [ https://www.usenix.org/system/files/conference/woot16/woot16-paper-blackthorne_update.pdf ]


iii. [ https://wikileaks.org/ciav7p1/cms/files/BypassAVDynamics.pdf ]


iv. Detecting & Evading Automated Malware Analysis - Alexei Bulazel


v. Pafish [ https://github.com/a0rtega/pafish ]


Posted by SanseoLab

블로그 이미지
Malware Analyst
SanseoLab

태그목록

공지사항

Yesterday
Today
Total

달력

 « |  » 2024.4
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

최근에 올라온 글

최근에 달린 댓글

글 보관함