리버싱 핵심원리_ DLL Ejection
리버싱 핵심원리_ DLL Ejection
DLL Ejection
- DLL Injection의 반대 개념으로 프로세스에 강제 삽입한 DLL 제거
- 동작 원리는 CreateRemoteThread API를 이용한 DLL Injection 과 같다.
대상 프로세스로 하여금 LoadLibrary() API를 호출하도록 만드는 인젝션과 같이 FreeLibrary() API를 호출하게 하는 것이다.
1. 프로세스에 로딩된 DLL 정보 구하기
hSnapshot = CreateToolhelp32SnapShot(TH32CS_SNAPMODULE,dwPID)
-> 프로세스에 로딩된 dll 의 정보를 얻을 수 있다
이렇게 구한 hSanpshot 핸들을 Module32First()/Module32Next() 함수에 넘겨주면 MODULEENTRY32 구조체에 해당 모듈 정보 세팅
2. 대상 프로세스 핸들 구하기
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
-> 프로세스 ID를 이용해서 대상 프로세스(notepad)의 프로세스 핸들을 구한다.
추후에 이 프로세스 핸들을 이용해 CreateRemoteThread() API를 호출
3. FreeLibrary() API 주소 구하기
hModule = GetModuleHandle(L "kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule,"FreeLibrary")
-> 시스템이 돌아가는 동안, kernel32.dll 은 모든 프로세스에서 같은 주소로 로딩
API()의 호출을 위해서는 FreeLibrary()의 주소를 알아야 하는데 위에서는 notepad.exe에 로딩된 Kernel32FreeLibrary 주소가 아니라 EjectDll.exe 프로세스에 로딩된 주소를 얻어오고 있다. ---->FreeLibrary 주소는 모든 프로세스에 동일!!
4. 대상 프로세스에 스레드를 실행시키기
hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL);
pThreadProc의 파라미터 -> FreeLibrary() API의 주소,
me.modBaseAddr 파라미터 -> 이젝션하기 원하는 DLL 로딩주소
스레드 함수로 FreeLibrary 함수 지정 후 스레드 파라미터에 DLL 로딩 주소를 넘겨주면 대상프로세스에서 FreeLibrary() API 호출완료
CreateRemoteThread() API의 의도는 외부 프로세스에 스레드 함수(FreeLibrary)실행
#include <Windows.h>#include <TlHelp32.h>#include <tchar.h>#define DEF_PROC_NAME (L"notepad.exe")#define DEF_DLL_NAME (L"k3y6reak.dll")DWORD FindProcessID(LPCTSTR szProcessName){DWORD dwPID = 0xFFFFFFFF;HANDLE hSnapShot = INVALID_HANDLE_VALUE;PROCESSENTRY32 pe;// Get System Snapshotpe.dwSize = sizeof(PROCESSENTRY32);hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);// Searching ProcessProcess32First(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){TOKEN_PRIVILEGES tp;HANDLE hToken;LUID luid;if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken)){_tprintf(L"OpenProcessToken error: %u\n", GetLastError());return FALSE;}if (!LookupPrivilegeValue(NULL, // lookup privilege on local systemlpszPrivilege, // privilege to lookup&luid)) // receives LUID of privilege{_tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError());return FALSE;}tp.PrivilegeCount = 1;tp.Privileges[0].Luid = luid;if (bEnablePrivilege)tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;elsetp.Privileges[0].Attributes = 0;// Enable the privilege or disable all privileges.if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL)){_tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError());return FALSE;}if (GetLastError() == ERROR_NOT_ALL_ASSIGNED){_tprintf(L"The token does not have the specified privilege. \n");return FALSE;}return TRUE;}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.exe's PID// Get DLL_NAME in notepad process with TH32CS_SNAPMODULE ParameterhSnapshot = 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;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);// Chane Privilegeif (!SetPrivilege(SE_DEBUG_NAME, TRUE)){return 1;}// Eject DLLif (EjectDll(dwPID, DEF_DLL_NAME)){_tprintf(L"EjectDll(%d, \"%s\") sucess!!!\n", dwPID, DEF_DLL_NAME);}else{_tprintf(L"EjectDll(%d, \"%s\") failed!!!\n", dwPID, DEF_DLL_NAME);}return 0;}