KOROMOON

착한 사마리아인이 되고 싶습니다.

9/12/2020

악성코드에서 활용되는 VM 체크 및 감지 기술


해당 글은 닉 호프만(Nick Hoffman)님께서 2014년 12월 03일에 작성한 글을 번역함.

링크 : 

https://securitykitten.github.io/2014/12/03/vm-checking-and-detecting.html


2014년에 공개된 안티 VM 기능이 있는 악성코드를 조사하여 해당 VM 체크 및 감지하는 루틴만 알아보고자 함.

첨부 파일에 악성코드 샘플을 첨부함.


파일명 : ozohrr.exe

종류 : 백도어

증상 : 

파일 타입 : Win32 EXE

파일 사이즈 : 63.00 KB (64,512 bytes)

MD5 : de1af0e97e94859d372be7fcf3a5daa5

SHA1 : 6b0c9722abf07f2ebdeb5363021593ba9bde7a17

SHA-256 : 

a924ac85724c695f2ae8f06f7a52bb34d5a518894e01cab39566793b6cfd6003

VirusTotal 결과값 : 

https://www.virustotal.com/gui/file/a924ac85724c695f2ae8f06f7a52bb34d5a518894e01cab39566793b6cfd6003/summary

샘플 다운로드 링크(암호 : koromoon1004) : 

https://drive.google.com/file/d/17MpqBMtLfIuwCU_ih9wUJUBKz9mise3G/view?usp=sharing




( 01 ) Sleep 확인


GetTickCount() 함수를 호출한 다음 500 밀리초 동안 Sleep 후 다시 GetTickCount() 함수를 호출함.

만약 두 카운트 차이가 450 밀리초보다 클 경우 테스트를 통과함.

이 검사는 RETN 4 또는 Sleep() 함수 후킹으로 부터 패치를 방지할 수 있음.




( 02 ) 디버거 확인


IsDebuggerPresent() 함수를 사용하여 디버거를 확인함.

IsDebuggerPresent() 함수는 파라미터는 필요 없고 현재 프로세스가 유저 모드 디버거에 의해 호출된 것이면 0 이 아닌 값을 반환함.


다음으로 CheckRemoteDebuggerPresent() 함수를 사용하여 디버거를 확인함.

CheckRemoteDebuggerPresent() 함수는 인자로 주어진 해당 프로세스가 디버깅되고 있는지를 결정하는 함수임.

함수의 첫 번째 인자는 확인할 프로세스의 핸들, 두 번째 인자는 결과값을 저장할 버퍼임.




( 03 ) 사용자 이름 확인


GetUserNameA() 함수를 호출하여 사용자 이름을 확인하는 작업을 수행함.

그런 다음 toupper() 함수를 대문자로 변환함.


대문자로 변환 후 결과 문자열을 가지고 다음과 같은 이름에 대해서 확인함.

MALTEST

TEQUILABOOMBOOM

SANDBOX

VIRUS

MALWARE




( 04 ) 파일 경로 확인


위 사용자 이름을 확인하는 작업과 비슷한 루틴임.

여기서는 파일 경로를 확인하는 GetModuleFileNameA() 함수를 호출함.

그런 다음 toupper() 함수를 대문자로 변환함.


대문자로 변환 후 결과 문자열을 가지고 다음과 같은 이름에 대해서 확인함.

\SAMPLE

\VIRUS

SANDBOX




( 05 ) Wine 실행 확인


KERNEL32.DLL 에서 서비스되는 wine_get_unix_file_name 이 포함되어 있는지 여부를 검사함.




( 06 ) 가상화 프로그램 DLL 로딩 확인


GetModuleHandleA() 함수를 호출하여 가상화 프로그램 DLL 목록들을 검사함.

sbiedll.dll (Sandboxie)

dbghelp.dll (vmware)

api_log.dll (SunBelt SandBox)

dir_watch.dll (SunBelt SandBox)

pstorec.dll (SunBelt Sandbox)

vmcheck.dll (Virtual PC)

wpespy.dll (WPE Pro)




( 07 ) VMware 확인



레지스트리 키 "HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0" 에서 식별자 값과 VMware 데이터를 찾음.


또한, 레지스트리 키 "SOFTWARE\VMware, Inc.\VMware Tools" 에서 VMware Tools 존재 여부를 확인함.




( 08 ) VirtualBox 확인



레지스트리 키 "HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0" 에서 식별자 값과 VBOX 데이터를 찾음.




그리고 레지스트리 키 "HARDWARE\Description\System" 에서 SystemBiosVersion 값과 VBOX 데이터를 찾음.

"SOFTWARE\Oracle\VirtualBox Guest Additions" 항목을 통해 GuestAdditions 값을 체크함.



VirtualBox 비디오 드라이버와 관련된 레지스트리 키 "HARDWARE\Description\System" 에서 VideoBiosVersion 값과 VIRTUALBOX 데이터를 찾음.




( 09 ) QEMU 확인



레지스트리 키 "HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0" 에서 식별자 값과 QEMU 데이터를 찾음.


그리고 레지스트리 키 "HARDWARE\Description\System" 에서 SystemBiosVersion 값과 QEMU 데이터를 찾음.




( 10 ) 드라이브 크기 확인


최종적으로 드라이브 크기를 확인함.

CreateFileA() 함수를 이용하여 PhysicalDrive0 에 대한 핸들을 얻음.


그런 다음 반환된 핸들을 사용하여 DeviceIoControl() 함수의 매개변수 dwIoControlCode 값 7405C 를 전달함.

(IOCTL_DISK_GET_LENGTH_INFO)


위 함수의 출력을 받아 기가바이트 크기로 표시된 드라이브 크기를 1073741824 로 분할함.

하드 드라이브의 사이즈가 10 보다 작을 경우 악성코드 실행을 중지함.


댓글 없음:

댓글 쓰기