├── InjectDll.cpp ├── LICENSE ├── MemoryScanInjector.cpp ├── QueueUserAPC.cpp └── README.md /InjectDll.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define PROC_NAME L"" 4 | #define DLL_NAME L"" 5 | 6 | int main() { 7 | STARTUPINFO si; 8 | PROCESS_INFORMATION pi; 9 | 10 | memset(&si, 0, sizeof(si)); 11 | memset(&pi, 0, sizeof(pi)); 12 | 13 | CreateProcessW(PROC_NAME, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); 14 | 15 | HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); 16 | LPTHREAD_START_ROUTINE pLoadLibraryW = 17 | (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW"); 18 | 19 | SIZE_T dwLength = (wcslen(DLL_NAME) + 1) * 2; 20 | LPVOID lpLibName = VirtualAllocEx(pi.hProcess, NULL, dwLength, MEM_COMMIT, PAGE_READWRITE); 21 | 22 | SIZE_T written = 0; 23 | WriteProcessMemory(pi.hProcess, lpLibName, DLL_NAME, dwLength, &written); 24 | 25 | HANDLE hThread = CreateRemoteThread(pi.hProcess, NULL, NULL, pLoadLibraryW, lpLibName, NULL, NULL); 26 | WaitForSingleObject(hThread, INFINITE); 27 | 28 | CloseHandle(hThread); 29 | ResumeThread(pi.hThread); 30 | 31 | VirtualFreeEx(pi.hProcess, lpLibName, dwLength, MEM_RELEASE); 32 | 33 | CloseHandle(pi.hProcess); 34 | CloseHandle(pi.hThread); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 YoungJoong Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MemoryScanInjector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #define PROC_NAME L"Examples.exe" 11 | 12 | DWORD GetPidByProcessName(WCHAR* wName) { 13 | PROCESSENTRY32W entry; 14 | memset(&entry, 0, sizeof(entry)); 15 | entry.dwSize = sizeof(entry); 16 | 17 | DWORD dwPid = -1; 18 | HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 19 | if (Process32FirstW(hSnapShot, &entry)) { 20 | do { 21 | if (!_wcsicmp(wName, entry.szExeFile)) { 22 | dwPid = entry.th32ProcessID; 23 | break; 24 | } 25 | } while (Process32NextW(hSnapShot, &entry)); 26 | } 27 | 28 | CloseHandle(hSnapShot); 29 | return dwPid; 30 | } 31 | 32 | bool ScanMemory(HANDLE hProcess, BYTE *pattern, SIZE_T length, std::vector& list) { 33 | SYSTEM_INFO sysinfo; 34 | GetSystemInfo(&sysinfo); 35 | 36 | LPVOID lpStartAddress = (LPVOID)sysinfo.lpMinimumApplicationAddress; 37 | LPVOID lpEndAddress = (LPVOID)sysinfo.lpMaximumApplicationAddress; 38 | 39 | std::string strPattern(pattern, pattern + length); 40 | 41 | while (lpStartAddress < lpEndAddress) { 42 | MEMORY_BASIC_INFORMATION mbi = { 0, }; 43 | if (!VirtualQueryEx(hProcess, lpStartAddress, &mbi, sizeof(mbi))) { 44 | return false; 45 | } 46 | 47 | if (mbi.State == MEM_COMMIT && !(mbi.Protect & PAGE_GUARD) && mbi.Protect != PAGE_NOACCESS) { 48 | if ((mbi.Protect & PAGE_EXECUTE_READ) || (mbi.Protect & PAGE_EXECUTE_READWRITE)) { 49 | BYTE *dump = new BYTE[mbi.RegionSize]; 50 | ReadProcessMemory(hProcess, lpStartAddress, dump, mbi.RegionSize, NULL); 51 | std::string mem(dump, dump + mbi.RegionSize); 52 | 53 | size_t n = -1; 54 | while (true) { 55 | n = mem.find(strPattern, n + 1); 56 | if (n == std::string::npos) { 57 | break; 58 | } 59 | 60 | list.push_back((LPVOID)((SIZE_T)lpStartAddress + n)); 61 | } 62 | 63 | delete[] dump; 64 | } 65 | } 66 | 67 | lpStartAddress = (LPVOID)((SIZE_T)lpStartAddress + mbi.RegionSize); 68 | } 69 | 70 | return true; 71 | } 72 | 73 | int main() { 74 | DWORD pid = GetPidByProcessName(PROC_NAME); 75 | HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); 76 | 77 | //sample 78 | 79 | //movsxd rcx, dword ptr ss:[rbp-40] 80 | //mov dword ptr ds:[rax], ecx 81 | //movsxd rax, dword ptr ds:[r15+50] 82 | 83 | std::vector list; 84 | BYTE pattern[] = { 0x48, 0x63, 0x4D, 0xC8, 0x89, 0x08, 0x49, 0x63, 0x47, 0x50 }; //target opcode 85 | ScanMemory(hProcess, pattern, sizeof(pattern), list); 86 | 87 | BYTE code[] = { 0xC7, 0x00, 0x04, 0x00, 0x00, 0x00 }; // patch opcode 88 | 89 | // target opcode is fourth memory point 90 | if (list.size() == 4) { 91 | DWORD oldProtect = 0; 92 | VirtualProtectEx(hProcess, list.back(), sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtect); 93 | WriteProcessMemory(hProcess, list.back(), code, sizeof(code), NULL); 94 | VirtualProtectEx(hProcess, list.back(), sizeof(code), oldProtect, NULL); 95 | 96 | printf("[*] success\n"); 97 | } 98 | else { 99 | printf("[*] fail\n"); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /QueueUserAPC.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #define PROC_NAME L"" 8 | #define DLL_NAME L"" 9 | 10 | DWORD GetPidByProcessName(WCHAR *wProcName) { 11 | DWORD dwPid = -1; 12 | PROCESSENTRY32W entry; 13 | memset(&entry, 0, sizeof(entry)); 14 | entry.dwSize = sizeof(entry); 15 | 16 | HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 17 | if (Process32FirstW(hSnapshot, &entry)) { 18 | do { 19 | if (!_wcsicmp(PROC_NAME, entry.szExeFile)) { 20 | dwPid = entry.th32ProcessID; 21 | break; 22 | } 23 | } while (Process32NextW(hSnapshot, &entry)); 24 | } 25 | 26 | CloseHandle(hSnapshot); 27 | 28 | return dwPid; 29 | } 30 | 31 | DWORD GetTidsByPid(DWORD dwPid, std::vector& tids) { 32 | THREADENTRY32 entry; 33 | memset(&entry, 0, sizeof(entry)); 34 | entry.dwSize = sizeof(entry); 35 | 36 | HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, NULL); 37 | if (Thread32First(hSnapshot, &entry)) { 38 | do { 39 | if (dwPid == entry.th32OwnerProcessID) { 40 | tids.push_back(entry.th32ThreadID); 41 | } 42 | } while (Thread32Next(hSnapshot, &entry)); 43 | } 44 | 45 | CloseHandle(hSnapshot); 46 | 47 | if (tids.size() > 0) { 48 | return 0; 49 | } 50 | 51 | return -1; 52 | } 53 | 54 | int main() { 55 | std::vector tids; 56 | DWORD dwPid = GetPidByProcessName(PROC_NAME); 57 | DWORD result = GetTidsByPid(dwPid, tids); 58 | 59 | HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); 60 | PAPCFUNC pLoadLibrary = (PAPCFUNC)GetProcAddress(hKernel32, "LoadLibraryW"); 61 | 62 | SIZE_T dwSize = (wcslen(DLL_NAME) + 1) * 2; 63 | HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwPid); 64 | 65 | SIZE_T written = 0; 66 | LPVOID lpAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); 67 | WriteProcessMemory(hProcess, lpAddress, DLL_NAME, dwSize, &written); 68 | 69 | for (auto dwTid : tids) { 70 | HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, dwTid); 71 | if (hThread) { 72 | QueueUserAPC(pLoadLibrary, hThread, (ULONG_PTR)lpAddress); 73 | CloseHandle(hThread); 74 | } 75 | } 76 | 77 | VirtualFreeEx(hProcess, lpAddress, dwSize, MEM_COMMIT); 78 | CloseHandle(hProcess); 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code Injection 2 | 3 | Inject code with certain technique written in cpp. 4 | 5 | - DLL Injection : [InjectDll.cpp](./InjectDll.cpp) 6 | - Memory Scanning : [MemoryScanInjector.cpp](./MemoryScanInjector.cpp) 7 | - DLL Injection with User APC : [QueueUserAPC.cpp](./QueueUserAPC.cpp) 8 | 9 | ## DLL Injection 10 | 11 | Inject dll with `CreateRemoteThread` and `LoadLibrary`. 12 | 13 | ```cpp 14 | VirtualAllocEx(pi.hProcess, NULL, dwLength, MEM_COMMIT, PAGE_READWRITE); 15 | WriteProcessMemory(pi.hProcess, lpLibName, DLL_NAME, dwLength, &written); 16 | 17 | HANDLE hThread = CreateRemoteThread(pi.hProcess, NULL, NULL, pLoadLibraryW, lpLibName, NULL, NULL); 18 | WaitForSingleObject(hThread, INFINITE); 19 | ``` 20 | 21 | ## Memory Scanning 22 | 23 | Scan certain instructions and overwrite it. 24 | 25 | `ScanMemory` inspects executable area, finds pattern and store the address to std::vector. 26 | 27 | ```cpp 28 | std::vector list; 29 | BYTE pattern[] = { 0x48, 0x63, 0x4D, 0xC8, 0x89, 0x08, 0x49, 0x63, 0x47, 0x50 }; //target opcode 30 | ScanMemory(hProcess, pattern, sizeof(pattern), list); 31 | 32 | BYTE code[] = { 0xC7, 0x00, 0x04, 0x00, 0x00, 0x00 }; // patch opcode 33 | WriteProcessMemory(hProcess, list.back(), code, sizeof(code), NULL); 34 | ``` 35 | 36 | ## Queue User APC 37 | 38 | [QueueUserAPC](https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms684954) adds user-mode Asynchronous Procedure Call (APC). 39 | 40 | Many anti-debugging agents watch `CreateRemoteThread`. In order to bypass this scenario, we can use APC to inject dll. 41 | 42 | ```cpp 43 | for (auto dwTid : tids) { 44 | HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, dwTid); 45 | if (hThread) { 46 | QueueUserAPC(pLoadLibrary, hThread, (ULONG_PTR)lpAddress); 47 | CloseHandle(hThread); 48 | } 49 | } 50 | ``` 51 | --------------------------------------------------------------------------------