-상- 편에 이어서 진행한다.
11. PSLIST export는 어떤 행위를 하나요?
답: 운영체제의 버전을 판별하고 그에 따라 프로세스 목록을 가져와 전송하거나 xinstall.dll에 기록한다.
Exports view에서 PSLIST를 찾아 내용을 확인한다.
PSLIST는 sub_100036C3을 호출하고 리턴된 값(eax)에 따라 분기한다. Test로 0인지 확인하고, 0일경우 loc_1000705B로 점프해 함수가 종료되고 0이 아닐 경우 다음 코드를 실행한다.
우선 sub_100036C3 함수를 확인해 본다.
9번 문제에서 보았던 GetVersionExA 함수가 실행되며, dwPlatformId, dwMajorVersion두 값을 비교하여 그 값에 따라 리턴 값이 달라지게 된다.
먼저 dwPlatformId값으로 win32_nt버전인지 확인하고, 해당 버전이 아니라면 jnz에 의해 loc_100036FA로 점프 후 0을 리턴하고 함수를 종료한다.
Win32_nt 버전이라면 다음 코드를 실행하는데, dwMajorVersion의 값을 비교하여 5보다 작을 경우 jb loc_100036FA로 점프 후 0을 리턴하고 함수를 종료한다.
dwMajorVersion의 값이 5일 경우, push 1 / pup eax 로 1을 리턴하고 종료한다.
정리하면, 운영체제 버전이 win32_nt이며, windows server2003/windowsXP /windows2000 이라면 1을 반환하고, 나머지는 모두 0을 반환한다.
eax값이 반환되면 각자 값에 따라 1인경우, sub_1000664C를 호출하고, 0인 경우 sub_10006518 를 호출한다. 두 함수 모두 유사 한 기능을 수행하고 있는데, 먼저 Sub_1000664C을 살펴본다.
Sub_1000664C
CreateToolhelp32Snapshot함수를 호출하는데, 이 함수는 프로세스와 스레드에 대한 정보를 얻기 위해 사용된다.
“\r\n\r\nProcessID ProcessName” 문자열은 가져온 프로세스 목록 데이터를 보기 좋게 형식화하는 것으로 보인다.
EnumProcessModules, GetModuleFileNameExA 함수는 프로세스 모듈 정보를 가져온다.
Process32Next는 프로세스 정보를 반복해서 가져온다.
위 함수들을 사용하여 프로세스 목록들을 가져온 뒤, sub_100038BB를 호출해 소켓을 통해 전송한다.
sub_10006518
sub_10006518의 경우 같은 함수를 호출하여 프로세스목록을 가져오지만, send로 전송하는 부분은 없었다. 대신 xinstall.dll이라는 파일을 열어 프로세스 목록들을 기록한다.
정리하면, PSlist는 운영체제의 버전을 판별하고 그에 따라 프로세스 목록을 가져와 전송하거나 xinstall.dll에 기록 한다.
12. sub_10004E79에 xrefs graph from기능을 사용해보세요. 이 함수에서 호출될 수 있는 API 함수는 어떤 것이 있을까요? API 함수만을 기준으로 이 함수를 어떻게 이름 지을 수 있을까요?
답 : send_SystemLangID
G단축키는 주소뿐만 아니라 함수이름으로도 이동할 수 있다.
함수로 이동해 상호 참조 그래프를 보면 아래와 같이 나온다.
GetSystemDefaultLangID와 send가 호출되는 API함수이다.
GetSystemDefaultLangID는 윈도우 시스템의 기본언어 식별자를 가져오며, send는 데이터를 소켓을통해 전송하는 기능을 갖는다.
그러므로 함수에 이름을 붙인다면, send_SystemLangID라고 할 수 있다.
13. DllMain이 직접적으로 호출하는 Windows API 함수는 몇 개인가요? 깊이 2에서는 몇 개인가요?
* (문제가 약간 이상해서 찾아보니 과거에는 sprint 등 도 win32API에 속해 있었다고 한다. 그래서 이 점을 고려하여 이번 문제는 DLLMain이 직접적으로 호출하는 함수와 깊이 2의 호출함수를 찾고 windowsAPI를 구분한다.)
답: 직접적으로 호출: 4개 / 깊이 2 : 32개
주요 windows API : gethostbyname, sleep, winexec, LoadLibraryA, WSAStartup, send, GetprocAddress
그냥 상호 참조 그래프를 생성하면, 모든 호출함수 관계도가 나와서 DLLMain을 찾기 어려웠다.
그래서 사용자 설정 그래프를 생성한다.
DllMain에 커서를 두고 View – Graphs – User Xrefs chart를 선택한다.
직접 호출하는 함수를 보기위해서는 Depth를 1로 설정한다.
DLL이 직접적으로 호출하는 함수는 strncpy, _strnicmp, CreateThread, strlen 이다.
깊이 2를 확인해 본다.
총 32개의 함수를 호출하는데, 너무 많아서 주요 windowsAPI 만 따로 정리해본다.
gethostbyname, sleep, winexec, LoadLibraryA, WSAStartup, send, GetprocAddress
14. 0x10001358에서 Sleep 함수가 호출되고 있습니다 (이 함수는 밀리초 단위로 지정된 시간 동안 프로그램을 일시 정지합니다). 코드를 리버싱 하면, 이 코드가 실행될 경우 프로그램은 얼마 동안 잠들게 될까요?
답: 30초
G단축키로 0x10001358로 이동하면 이런 그래프를 볼 수 있다.
mov eax, off_10019020 : "[This is CTI]30" Eax에 “[This is CTI]30” 이란 문자열을 넣는다.
add eax, 0Dh : 13(=0dh)바이트만큼 더해준다. “30”이란 값 부터 읽어오게 된다.
call ds:atoi : 문자열을 정수로 바꾼다. 문자열 "30"이 정수 30이 된다.
imul eax,3E5h : eax에 3E5h(=1000) 값을 곱한다. 결과적으로 eax에는 30*1000 = 30000 이 들어가게 된다.
Sleep 함수는 밀리초 단위로 실행되므로 1000밀리초는 1초.
측 30초 동안 잠들게 된다.
15. 0x10001701에 socket이 호출되고 있습니다. 세 개의 매개변수는 무엇인가요?
답 : 6, 1, 2
G단축키로 이동 후 바로 확인할 수 있다.
스택을 사용해 파라미터를 전달하는 경우, 파라미터 순서가 A, B, C라면 C, B, A순서로 전달한다.
16. 소켓의 MSDN 페이지와 IDA Pro의 named symbolic constants 기능을 사용하여 매개변수를 의미 있는 값으로 바꿀 수 있을까요? 변경 후의 매개변수는 무엇인가요?
답: AF_INET / SOCK_STREAM / IPPROTO_TCP
https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket 이곳에서 소켓함수에 대한 설명을 확인한다.
설명에 따르면 이 소켓은 ipv4 TCP로 설정 되어있음을 알 수 있다.
이를 참고해 Use standard symbolic constant 기능으로 값을 바꿔준다.
17. in 명령어 (opcode 0xED)의 사용법을 검색하세요. 이 명령어는 매직 문자열 VMXh와 함께 VMware 탐지를 수행합니다. 이 악성코드에서 해당 명령어를 사용하나요? in 명령어를 실행하는 함수의 상호 참조를 통해 VMware 탐지를 하는지에 대한 추가 증거를 찾을 수 있나요?
답 : 이 악성코드는 in 명령어를 사용하며, “Found Virtual Machine,Install Cancel.” 문자열이 vmware 탐지를 하는 증거이다.
In 명령어는 입력포트에서 데이터를 읽어온다. 이 명령어는 입출력(I/O) 작업에서 주로 사용되며, 특히 하드웨어와 통신하거나 외부장치와의 데이터 교환시에 활용된다.
VMXh는 가상머신 환경을 나타내는 문자열 이라는데, 아마 이를 이용해서 VMware탐지를 할 것으로 추정된다.
가장 낮은 주소에 커서를 두고, alt + B (search Binary)로 0xED를 검색한다. 몇 번 검색한 후 in 명령어를 찾을 수 있었다. 또는 search text를 이용해 in을 찾을 수도 있다.
검색 결과, sub_1006196함수에서 in 명령어가 사용된 것을 확인하였다
“564D5868h” 숫자가 눈에 띄어 문자로 변환해 보니, 매직 문자열인 ‘VMXh’ 이 나왔다.
sub_1006196의 상호 참조를 확인해 어디서 가상머신을 탐지하는 추가적인 증거가 있는지 확인해본다.
Xrefs to에 의하면 세 함수가 sub_1006196을 호출하는데, 각각 함수에 들어가니
“Found Virtual Machine, Install Cancel.” 이라는 문자열이 있었다.
이것이 바로 이 악성코드가 가상머신을 탐지하고 있다는 증거가 될 것이다.
18. 0x1001D988로 커서를 이동하세요. 어떤 내용을 발견하나요?
답: 의미 불명의 문자열들이 저장되어 있다.
19. IDA Python 플러그인이 설치되어 있다면(이 플러그인은 IDA Pro의 상업용 버전에 포함되어 있습니다), malware과 함께 제공된 Lab05-01.py, IDA Pro Python 스크립트를 실행하세요. (커서가 0x1001D988에 위치해 있는지 확인하세요.) 스크립트를 실행한 후에는 어떤 일이 일어나나요?
무작위 문자열이 “xdoor is this backdoor, string decoded for Practical Malware Analysis Lab :)1234.” 로 바뀐다.
파이썬 Pro 버전을 사용하고 있다면, Script file – Lab05-01.py 파일을 로드 해 실행할 수 있다.
커서위치의 무작위 문자열이 “xdoor is this backdoor, string decoded for Practical Malware Analysis Lab :)1234.” 로 바뀐다.
20. 동일한 위치에 커서가 있는 상태에서 이 데이터를 어떻게 하나의 ASCII 문자열로 변환할 수 있나요?
답 : A
A 키를 누르면 ASCII문자열로 변환할 수 있다. 되돌리고 싶다면 U(undefine)를 누르면 된다.
21. 스크립트를 텍스트 편집기로 열어보세요. 이 스크립트는 어떻게 작동하나요?
스크립트는 IDA에서 shift + F2를 눌러도 볼 수 있다
ScreanEA()는 현재 커서 위치를 가져오는 IDA API이다. 이 값을 sea 변수에 저장해 0x00부터 0x50 까지 반복문을 수행한다.
반복문에서는 순차적으로 문자열과 0x55를 XOR(=^)연산하여 decoded_byte에 저장한다. 이 저장한 값을 PatchByte로 패치 한다.
22. 마무리
Lab05은 IDA 프로그램의 전반적인 기능을 익히기 위한 과정이었다.
이번 실습을 통해 어셈블리 분석과 IDA의 방대한 기능에 대해 많은 공부가 되었다.
주의할 점은 이 책은 상용버전의 IDA Pro 기반으로 작성되어 있어 Free 버전으로는 IDA_Python을 사용할 수 없다. 그리고 현재 IDA 최신버전인 8.3버전과 이 악성코드를 빌드한 버전이 많이 차이나 현재는 사용할 수 없는 API들이 있었다. (ScreeanEA(), Byte 등..)