전에 올렸던것과 같지만 다시 후킹을 공부할겸 복습용으로 코드를 좀더 안정적으로 바꾸었다. 코딩 스타일을 통일하고 에러가 날만한 부분에 빠짐없이 리턴값을 확인하여 로깅한 것 뿐이지만 확실히 더 심리적으로 안정감이 느껴진다. 실무에서 로깅을 제대로 안해서 버그 잡기 힘들었던 것을 떠올리면 로깅은 제대로 해야한다는 생각이 들더라.
두 번째 인자로 들어가는 DLL 파일 경로는 notepad.exe와 DLL파일이 같은 경로 내에 있거나 DLL파일이 환경변수 'PATH'에 등록되어있지 않다면 절대 경로를 써 주어야 정상 작동한다. 이유는 후킹 방식이 DLL 인젝션으로 notepad.exe 프로세스에 Thread를 만들어 돌리는 것이라 실행 경로도 notepad.exe 파일이 놓인 곳일 것이기 때문이라고 추론하고 있다. 혹시나 다른 이유라면 댓글로 알려주시길 바란다.
## 2019-06-17 추가 : 이 포스트의 소스코드는 WriteFile함수가 KernelBase.dll로 구현이 옮겨진 후의 환경에서만 동작합니다. (참고 : https://sanseolab.tistory.com/17)
DLL_Injector.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #include <stdio.h> #include <Windows.h> #include <TlHelp32.h> #include <Shlwapi.h> DWORD findPID(LPCTSTR szProcessName); BOOL injectDLL(DWORD dwPID, LPCTSTR szDLLName); int main(int argc, char *argv[]) { if (argc != 3) { printf("[*] Usage : %s [Target] [DLL]\n", argv[0]); return 1; } if (!PathFileExists(argv[2])) { printf("[-] DLL Not Exists : %s\n", argv[2]); return 1; } DWORD pid = findPID(argv[1]); if (pid == 0xFFFFFFFF) { printf("[-] Process not found\n"); return 1; } else { printf("[*] pid : %u\n", pid); } if (!injectDLL(pid, argv[2])) { printf("[-] Injection Failed\n"); return 1; } else { printf("[*] Injection Successed\n"); } return 0; } DWORD findPID(LPCTSTR szProcessName) { DWORD dwPID = 0xFFFFFFFF; HANDLE hSnapshot = INVALID_HANDLE_VALUE; PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); if (hSnapshot == INVALID_HANDLE_VALUE) { printf("[*] CreateToolhelp32Snapshot Error\n"); return 0xFFFFFFFF; } Process32First(hSnapshot, &pe); do { if (!_stricmp(szProcessName, pe.szExeFile)) { dwPID = pe.th32ProcessID; break; } } while (Process32Next(hSnapshot, &pe)); CloseHandle(hSnapshot); return dwPID; } BOOL injectDLL(DWORD dwPID, LPCTSTR szDLLName) { HANDLE hProcess, hThread; HMODULE hMod; LPVOID pRemoteBuf; DWORD dwBufSize = lstrlen(szDLLName) + 1; LPTHREAD_START_ROUTINE pThreadProc; // Get target process handle if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == INVALID_HANDLE_VALUE) { printf("[-] OpenProcess Error\n"); printf("[-] gle : 0x%x\n", GetLastError()); return FALSE; } // Allocate memory to target process if ((pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE)) == INVALID_HANDLE_VALUE) { printf("[-] VirtualAllocEx Error\n"); printf("[-] gle : 0x%x\n", GetLastError()); return FALSE; } // Write DLL name to target process memory if (WriteProcessMemory(hProcess, pRemoteBuf, szDLLName, dwBufSize, NULL) == FALSE) { printf("[-] WriteProcessMemory Error\n"); printf("[-] gle : 0x%x\n", GetLastError()); return FALSE; } // Get handle of "kernel32.dll" if ((hMod = GetModuleHandle("kernel32.dll")) == INVALID_HANDLE_VALUE) { printf("[-] GetModuleHandle Error\n"); printf("[-] gle : 0x%x\n", GetLastError()); return FALSE; } // Get address of "LoadLibraryA" if ((pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryA")) == INVALID_HANDLE_VALUE) { printf("[-] GetProcAddress Error\n"); printf("[-] gle : 0x%x\n", GetLastError()); return FALSE; } // Create and run remote thread in target process if ((hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL)) == INVALID_HANDLE_VALUE) { printf("[-] CreateRemoteThread Error\n"); printf("[-] gle : 0x%x\n", GetLastError()); return FALSE; } WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess); return TRUE; } | cs |
NotepadHook.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | #include <stdio.h> #include <Windows.h> #pragma pack(1) struct IAT_STRUCT { SHORT Opcode; LPVOID lpTarget; }; typedef BOOL WINAPI tWriteFile( _In_ HANDLE hFile, _In_ LPCVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped ); tWriteFile* prevFunction; tWriteFile* newFunction; BOOL WINAPI NewWriteFile( _In_ HANDLE hFile, _In_ LPCVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped ) { if (nNumberOfBytesToWrite > 0) MessageBoxA(NULL, (LPCSTR)lpBuffer, NULL, NULL); return prevFunction(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); } DWORD WINAPI tryHook() { // Get address of target function LPVOID lpOrgFunc = NULL; if ((lpOrgFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile")) == NULL) return -1; // Backup old protect DWORD dwOldProtect; if (VirtualProtect(lpOrgFunc, 6, PAGE_EXECUTE_READWRITE, &dwOldProtect) == NULL) return -1; // Backup old function IAT IAT_STRUCT* lpSavedFunc = (IAT_STRUCT*)VirtualAlloc(NULL, sizeof(IAT_STRUCT), MEM_COMMIT, PAGE_EXECUTE_READWRITE); IAT_STRUCT newFuncObj; memcpy_s(lpSavedFunc, 6, lpOrgFunc, 6); prevFunction = (tWriteFile*)lpSavedFunc; // Absolute Jump newFuncObj.Opcode = 0x25FF; // Set new functon to replace newFunction = &NewWriteFile; newFuncObj.lpTarget = &newFunction; // Replacing memcpy_s(lpOrgFunc, 6, &newFuncObj, 6); // Rollback protection VirtualProtect(lpOrgFunc, 6, dwOldProtect, NULL); return 0; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { HANDLE hThread; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: tryHook(); break; case DLL_PROCESS_DETACH: break; } return TRUE; } | cs |
'Programming' 카테고리의 다른 글
CodeFights - alternatingSums (0) | 2018.01.15 |
---|---|
CodeFights - commonCharacterCount (0) | 2017.12.27 |
리눅스 커널 모듈 프로그래밍 - mychardev (0) | 2017.07.10 |
리눅스 커널 모듈 프로그래밍 - Hello World (0) | 2017.07.04 |
현재 사용중인 Python 라이브러리 (0) | 2017.06.15 |