이번에는 DLL도 Injection 하여 코드 후킹을 해보았다.
아래 코드는 DLL의 일부이다.
void HookCode(void)
{
HMODULE hMod;
HANDLE hProc = NULL;
//Destination Function Address
LPVOID pDestFuncAddr;
DWORD pGapOfAddress;
DWORD dwOldProtect;
BYTE NewBytes[5]={0xE9,0,};
// dll의 handle을 구한 뒤 목적함수의 주소를 구함
hMod = GetModuleHandle("KERNEL32.dll");
pDestFuncAddr = (LPVOID)GetProcAddress(hMod,"CreateFileW");
/*
JMP 주소 계산 = (이동할 주소) - (현재 주소) - 5(명령어 길이)
*/
pGapOfAddress = (DWORD)&MyHookFunc - (DWORD)pDestFuncAddr - 5;
// 목적지 주소의 원래 5바이트값을 백업
memcpy(g_pOrgBytes, pDestFuncAddr, 5);
// 새로 덮어씌울 5바이트값
memcpy(&NewBytes[1], &pGapOfAddress, 4);
// 목적지 주소의 가상메모리 권한 변경
/*
VirtualProtect(변경할 시작 주소, 변경할 크기(BYTE), 새로 부여할 권한, 기존 권한을 저장할 공간)
*/
VirtualProtect(pDestFuncAddr, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
// 새 Opcode 덮어씌움
memcpy(pDestFuncAddr, NewBytes, 5);
// 가상메모리 권한 복원
VirtualProtect(pDestFuncAddr, 5, dwOldProtect, &dwOldProtect);
}
void MyHookFunc(void)
{
UnHookCode();
MessageBox(NULL,"you are hacked!","알림",MB_OK);
}
VirtualProtect() 함수를 이용하여 후킹할 함수의 시작주소로부터 5바이트의 영역을 쓰기권한을 주어
원하는 코드를 삽입할 수 있게 했다.
이번에 후킹한 함수는 CreateFileW()함수로 파일을 저장하기위해 주로 이 함수를 이용한다.
아래 코드는 위 DLL을 원하는 프로세스로 삽입시키는 Injector의 일부이다.
DWORD dwPID = 0xFFFFFFFF;
if(argc != 2)
{
printf("Injector.exe [ProcessName]");
return 1;
}
//find process
dwPID = FindProcessID(argv[1]);
if(dwPID == 0xFFFFFFFF)
{
printf("There is no <%s> process!\n",argv[1]);
return 1;
}
//nject dll
InjectDll(dwPID, DEF_DLL_PATH);
매개변수로 프로세스의 이름을 받아서 PID를 구한 후 InjectDll을 호출한다.
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName)
{
int ForError=0;
HANDLE hProcess, hThread;
HMODULE hMod;
LPVOID pRemoteBuf;
DWORD dwBufSize = lstrlen(szDllName) + 1;
LPTHREAD_START_ROUTINE pThreadProc;
// dwPID 를 이용하여 대상 프로세스의 HANDLE을 구함
if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ) //실패시 NULL 성공시 프로세스핸들
return FALSE;
// 대상 프로세스메모리에 szDllName(dwBufSize) 크기만큼 메모리를 할당
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); //성공시 할당된 메모리 주소(대상 프로세스 가상메모리)
// 할당 받은 메모리에 myhack.dll 경로를 씀
ForError = WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL);
if( !ForError )
return FALSE;
// LoadLibraryA() API 주소를 구함
hMod = GetModuleHandle("kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"LoadLibraryA");
// 대상프로세스에 스레드를 실행
hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
printf("모두 끝남");
return TRUE;
}
PID값을 이용하여 대상 프로세스에 대한 HANDLE을 구함
VirtualAllocEx() 함수를 이용하여 대상 프로세스의 가상메모리에 메모리를 할당
WriteProcessMemory() 함수를 이용하여 dll의 경로를 할당 받은 메모리에 씀
CreateRemoteThread() 함수를 이용하여 대상프로세스에 스레드 실행
이것을 이용하여 메모장을 후킹해 보았다.
먼저 Injector를 실행했다.
ProcessExplorer로 확인해 보니 삽입이 잘 되어 있다.
이제 "저장"버튼을 눌러서 CreateFileW()을 호출할 수 있게끔 했다.
버튼을 누르자
메시지박스를 띄우며 종료된다.
[소스 코드] :
https://github.com/khycan/API-Hooking/blob/master/API%20Hooking%20+%20DLL%20Injection/Injector/InjectorMain.cpp
https://github.com/khycan/API-Hooking/blob/master/API%20Hooking%20%2B%20DLL%20Injection/dll/DllMain.cpp