반응형
#WinAPI #프로세스 탐색
1. EnumProcesses(DWORD *lpidProcess, DWORD cb, LPDWORD lpcbNeeded);
#include <Psapi.h>
로 불러와서 실행가능하다. 현재 실행 중인 프로세스들의 PID 를 불러와서 배열에 저장한다.
[인자설명]
- lpidProcess : 실행 중인 프로세스들의 PID 를 저장할 DWORD 배열이다.
- cb : 첫 번째 인자 배열의 사이즈이다.
- lpcbNeeded : 전체 프로세스 PID 들의 총 바이트를 저장할 DWORD 변수이다. ( DWORD(4) * 프로세스들의 수 ) = ( 총 바이트 )
2. HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
PID 에 따라 프로세스 핸들을 리턴한다.
[인자설명]
- dwDesiredAccess : 프로세스를 불러올 권한이다. process_access_right 에 상세 권한 설명이 되어있다.
PROCESS_ALL_ACCESS
는 IDA 에서 확인하면0x1F0FFF
이니 유의. 만약 함수 caller 가SeDebugPrivilege
권한이 허용된 상태라면, 보안 설정에 상관없이 모든 권한을 갖는다. - bInheritHandle : TRUE 값을 가지고있을 경우에 return 된 프로세스 핸들이 본 프로세스의 자식프로세스에 상속된다. 대부분은 FALSE 이다.
- dwProcessId : 핸들을 생성할 프로세스의 PID 이다.
3. BOOL EnumProcessModulesEx( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded, DWORD dwFilterFlag);
핸들로 받은 프로세스가 실행하고(갖고있고) 있는 모듈들을 lphModule 배열에 저장한다. 해당 배열의 0 번째 인덱스에는 프로세스 정보가 그대로 박혀있다. 이것으로 순회 하면서 현재 탐색 중인 프로세스가 어떤 건지 구분 가능하다. (다음 인덱스 부터는 프로세스에서 사용하는 여러가지 DLL 들이 박혀있다. 예를 들면, KERNEL32.DLL 이라던지...)
[인자설명]
- hProcess : OpenProcess 에서 나온 핸들
- lphModule : 모듈 목록을 받아올 HMODULE 배열
- cb : lphModule 배열의 사이즈
- lpcbNeeded : 총 모듈의 바이트를 받아올 DWORD 변수
- dwFilterFlag : 32비트용 함수인 EnumProcessModulesEx 에서 인자가 하나 추가 되었는데, dwFilterFlag 는 어떤 비트의 모듈만 불러올지 필터를 정하는 인자인 듯하다. 아래 4개 중 하나는 무조건 있어야한다.
4. DWORD GetModuleBaseNameA( HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize);
3 번 함수에서 얻어낸 모듈정보에서 해당 모듈들의 이름을 가져오는 간단한 함수이다.
[인자설명]
- hProcess : 프로세스 핸들
- hModule : 3번에서 얻어낸 모듈 배열 중에서 모듈 하나의 값
- lpBaseName : 모듈이름이 저장될 문자열 변수
- nSize : lpBaseName 사이즈
용례
typedef BOOL(__stdcall *EnumProcessModulesEx)(HANDLE, HMODULE *, DWORD, DWORD *, DWORD);
typedef DWORD(__stdcall *GetModuleBaseNames)(HANDLE, HMODULE, TCHAR *, DWORD);
typedef BOOL(__stdcall *EnumProcesses)(DWORD *, DWORD, LPDWORD);
int main(){
HINSTANCE hModule = LoadLibrary(L"psapi.dll");
EnumProcessModulesEx EnumProcessModule = (EnumProcessModulesEx)GetProcAddress(hModule, "EnumProcessModulesEx");
GetModuleBaseNames GetModuleBaseName = (GetModuleBaseNames)GetProcAddress(hModule, "GetModuleBaseNameA");
EnumProcesses EnumProcess = (EnumProcesses)GetProcAddress(hModule, "EnumProcesses");
// main 함수 이어서...
}
우선 #include <Psapi.h>
으로 함수들을 불러올 수도 있지만, 대부분의 악성코드는 LoadLibrary
을 통해 동적으로 dll 을 가져온다.
그리고 typedef 로 함수 원형을 선언해놓고 GetProcAddress
함수로 원하는 함수를 dll 모듈에서 불러온다.
// main 함수 이어서...
DWORD myProcs[100000], countBytes;
int numOfProcs;
EnumProcess(myProcs, sizeof(myProcs), &countBytes);
numOfProcs = countBytes / sizeof(DWORD);
printf("전체프로세스 수는 %d 개\n", numOfProcs);
for (int i = 0; i < numOfProcs; i++) {
TCHAR modName[1024] = { 0, };
if (myProcs[i]) {
winlogon = OpenProcess(0x410, FALSE, myProcs[i]);
if (winlogon && EnumProcessModule(winlogon, hMods, sizeof(hMods), &cb,0x2)) {
// winlogon.exe in Windows 10.
// So, Use EnumProcessModulesEx function and Build Malware to 64 bit env.
// 성공 시, return value is not 0. 실패 시, return value is 0.
GetModuleBaseName(winlogon, hMods[0], modName, 1024);
if(!strcmp((const char*)modName,"winlogon.exe")|| !strcmp((const char*)modName, "WinLogon.exe")){
// printf("%s\n", modName);
printf("WinLogon.exe PID: %d\n", winlogon_pid);
winlogon_pid = myProcs[i];
CloseHandle(winlogon);
break;
}
}
}
}
EnumProcesses
함수에서 얻어온 countBytes 를 DWORD 로 나누어서 프로세스 개수를 얻어온다. 그리고 프로세스 하나씩 OpenProcess
로 열면서 winlogon.exe 프로세스를 탐색한다. 그게 전부이다. critical 한 system 프로세스를 찾는 경우가 많다.
참고
반응형
'<악성코드 분석공부> > <WinAPIs>' 카테고리의 다른 글
[WinAPI] 리소스를 분석, 해체 해보자 (0) | 2021.08.22 |
---|