-
[리버싱 핵심원리 study] 24장 DLL 이젝션Reverse Engineering 2021. 1. 8. 03:49
DLL 이젝션은 앞에서 다룬 DLL 인젝션과는 반대되는 개념으로, 특정 프로세스에 로딩된 DLL을 빼내는 방법이다. DLL 인젝션에서는 대상 process로 하여금 LoadLibrary API를 호출하도록 하는 반면, 이젝션에서는 FreeLibrary API를 호출하게끔 하는 방식으로 이루어져 있다.
1. DLL 이젝션 구현
책에 나와있는 실습 코드를 분석해보자.
#include "Windows.h" #include "tlhelp32.h" #include "tchar.h" #define DEF_PROC_NAME (L"notepad.exe") #define DEF_DLL_NAME (L"myhack.dll") DWORD FindProcessID(LPCTSTR szProcessName) { DWORD dwPID = 0xFFFFFFFF; HANDLE hSnapshot = INVALID_HANDLE_VALUE; PROCESSENTRY32 pe; //시스템의 스냅샷 가져오기 pe.dwSize = sizeof(PROCESSENTRY32); hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); //프로세스 찾기 Process32First(hSnapshot, &pe); do { if (!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile)) { dwPID = pe.th32ProcessID; break; } } while (Process32Next(hSnapshot, &pe)); CloseHandle(hSnapshot); return dwPID; } BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { /*......*/ } BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName) { BOOL bMore = FALSE, bFound = FALSE; HANDLE hSnapshot, hProcess, hThread; HMODULE hModule = NULL; MODULEENTRY32 me = { sizeof(me) }; LPTHREAD_START_ROUTINE pThreadProc; //dwPID = notepad 프로세스 ID //TH32CS_SNAPMODULE 파라미터를 이용해 notepad 프로세스에 로딩된 DLL 이름을 얻는다. hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); bMore = Module32First(hSnapshot, &me); for (; bMore; bMore = Module32Next(hSnapshot, &me)) { if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) || !_tcsicmp((LPCTSTR)me.szExePath, szDllName)) { bFound = TRUE; break; } } if (!bFound) { CloseHandle(hSnapshot); return FALSE; } if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))) { _tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError()); return FALSE; } hModule = GetModuleHandle(L"kernel32.dll"); pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess); CloseHandle(hSnapshot); return TRUE; } int _tmain(int argc, TCHAR* argv[]) { DWORD dwPID = 0xFFFFFFFF; //process 찾기 dwPID = FindProcessID(DEF_PROC_NAME); if (dwPID == 0xFFFFFFFF) { _tprintf(L"There is no %s process!\n", DEF_PROC_NAME); return 1; } _tprintf(L"PID of \"%s\" is %d\n", DEF_PROC_NAME, dwPID); //privilege 바꾸기 if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) return 1; //eject dll if (EjectDll(dwPID, DEF_DLL_NAME)) _tprintf(L"EjectDll(%d, \"%s\") success!!!\n", dwPID, DEF_DLL_NAME); else _tprintf(L"EjectDll(%d, \"%s\") failed!!!\n", dwPID, DEF_DLL_NAME); return 0; }
크게는 FindProcessID, SetPrivilege, EjectDll, main함수 이렇게 네 가지 함수로 구성되어 있다. (SetPrivilege 함수는 토큰 권한 관련하여 설정을 변경하는 함수인데, 정확한 원리는 파악하지 못하여 일단 주석 처리만 해놓았다.)
- FindProcessID : 프로세스 이름 문자열을 받아 그에 대응되는 PID를 구하여 반환한다.
- SetPrivilege : 토큰 권한 설정 함수
- EjectDll : PID와 eject할 DLL이름을 매개변수로 갖는 함수로, 대상 프로세스에서 해당 DLL을 eject 한다.
2. DLL 이젝션 실습
이전에 실습한 DLL 인젝션 환경에서(notepad.exe에 myhack.dll이 인젝션 된 상황) myhack.dll을 eject 해보자. 먼저 이전 실습과 같이 동일한 환경을 구성해보자.
myhack.dll이 인젝션된 상황 cmd창에서 다음과 같이 명령어를 입력하여 EjectDll.exe를 실행한다.
EjectDll.exe 실행 myhack.dll eject 위와 같이 myhack.dll이 notepad.exe에서 사라진 것을 확인할 수 있다.
반응형'Reverse Engineering' 카테고리의 다른 글
[리버싱 핵심원리 study] 27장 Code 인젝션 (0) 2021.01.14 [리버싱 핵심원리 study] 25장 PE 패치를 이용한 DLL 로딩 (0) 2021.01.10 [리버싱 핵심원리 study] 23장 DLL 인젝션 (0) 2021.01.06 [리버싱 핵심원리 study] 21장 Windows 메세지 후킹 (0) 2021.01.04 [리버싱 핵심원리 study] 20장 인라인 패치 실습 (2) 2021.01.01