crashinject.cpp (3351B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 * Given a PID, this program attempts to inject a DLL into the process 7 * with that PID. The DLL it attempts to inject, "crashinjectdll.dll", 8 * must exist alongside this exe. The DLL will then crash the process. 9 */ 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <windows.h> 14 15 int main(int argc, char** argv) { 16 if (argc != 2) { 17 fprintf(stderr, "Usage: crashinject <PID>\n"); 18 return 1; 19 } 20 21 int pid = atoi(argv[1]); 22 if (pid <= 0) { 23 fprintf(stderr, "Usage: crashinject <PID>\n"); 24 return 1; 25 } 26 27 // find our DLL to inject 28 wchar_t filename[_MAX_PATH]; 29 if (GetModuleFileNameW(nullptr, filename, 30 sizeof(filename) / sizeof(wchar_t)) == 0) 31 return 1; 32 33 wchar_t* slash = wcsrchr(filename, L'\\'); 34 if (slash == nullptr) return 1; 35 36 slash++; 37 wcscpy(slash, L"crashinjectdll.dll"); 38 39 // now find our target process 40 HANDLE targetProc = 41 OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | 42 PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION, 43 FALSE, pid); 44 if (targetProc == nullptr) { 45 fprintf(stderr, "Error %lu opening target process\n", GetLastError()); 46 return 1; 47 } 48 49 /* 50 * This is sort of insane, but we're implementing a technique described here: 51 * http://www.codeproject.com/KB/threads/winspy.aspx#section_2 52 * 53 * The gist is to use CreateRemoteThread to create a thread in the other 54 * process, but cheat and make the thread function kernel32!LoadLibrary, 55 * so that the only remote data we have to pass to the other process 56 * is the path to the library we want to load. The library we're loading 57 * will then do its dirty work inside the other process. 58 */ 59 HMODULE hKernel32 = GetModuleHandleW(L"Kernel32"); 60 // allocate some memory to hold the path in the remote process 61 void* pLibRemote = VirtualAllocEx(targetProc, nullptr, sizeof(filename), 62 MEM_COMMIT, PAGE_READWRITE); 63 if (pLibRemote == nullptr) { 64 fprintf(stderr, "Error %lu in VirtualAllocEx\n", GetLastError()); 65 CloseHandle(targetProc); 66 return 1; 67 } 68 69 if (!WriteProcessMemory(targetProc, pLibRemote, (void*)filename, 70 sizeof(filename), nullptr)) { 71 fprintf(stderr, "Error %lu in WriteProcessMemory\n", GetLastError()); 72 VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE); 73 CloseHandle(targetProc); 74 return 1; 75 } 76 // Now create a thread in the target process that will load our DLL 77 HANDLE hThread = CreateRemoteThread( 78 targetProc, nullptr, 0, 79 (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW"), 80 pLibRemote, 0, nullptr); 81 if (hThread == nullptr) { 82 fprintf(stderr, "Error %lu in CreateRemoteThread\n", GetLastError()); 83 VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE); 84 CloseHandle(targetProc); 85 return 1; 86 } 87 WaitForSingleObject(hThread, INFINITE); 88 // Cleanup, not that it's going to matter at this point 89 CloseHandle(hThread); 90 VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE); 91 CloseHandle(targetProc); 92 93 return 0; 94 }