728x90

이번에는 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


728x90

'리버스엔지니어링 > API Hooking' 카테고리의 다른 글

Win32 API Hooking - Trampoline Code Hooking  (0) 2015.05.29
728x90

Trampoline Code Hooking은 후킹할 함수의 첫 5바이트를 수정하여 자신이 원하는 함수를 호출시키는 방법이다.


왜 하필 5바이트인가?

그 이유는 EIP의 흐름(실행 흐름)을 변화시키는 JMP문이 5바이트 이기 때문이다.


ex) JMP 00400000

   E9  xxxxxxxx -> 5byte


보통 이런 API Hooking은 DLL Injection과 함께 사용하여


타 프로세스의 기능을 개선시키거나 혹은 기능을 제거하는 등 폭넓게 사용할 수 있다.

(사용 소프트웨어에 하면 불법이라 한다.)


그러나 이번에는 DLL Injection 없이 API Hooking만 실시하였다.




위 코드에서는 새 바이트값을 WriteProcessMemory 함수를 이용해서 덮어씌웠지만


VirtualProtect 함수를 이용해서 해당 메모리의 속성(읽기, 쓰기 등)을 변경하여


memcpy(pFunction, NewBytes, 5); 이런 식으로도 할 수도 있다.




디버거로 확인해 보면


main 함수에서 HookCode()를 호출하기 전 printf의 바이트 값은


이랬지만 HookCode() 호출 후



이렇게 JMP Project1.00401500

        HookFunc함수로 jump하는 코드로 바뀐것을 확인할 수 있다.



실행 시켜보면


hooking 되어 메시지박스를 호출하는 것을 확인 할 수 있다.


[소스 코드] : 

https://github.com/khycan/API-Hooking/blob/master/API%20hooking%20without%20DLL%20Injection/HookingMain.c

728x90

+ Recent posts