First on the source code
#include "Inject_Main.h" #include "resource.h" #include <Windows.h> #include <TlHelp32.h> #include <string> #include <TCHAR.H> using namespace std; /// <summary> /// Get the process handle by the process name /// </summary> /// <param name="processName"></param> /// <returns>Successful return DWORD,Failure returned 0</returns> DWORD GetProcessByName(CONST TCHAR* processName) { // Get the process of the whole system HANDLE processALL = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); // Define a container that is used to receive process information PROCESSENTRY32W processInfo = { 0 }; processInfo.dwSize = sizeof(PROCESSENTRY32W); // According to the process name, loop to judge whether it is the specified process do { if (_tcscmp(processInfo.szExeFile, processName) == 0) { // Release process snapshot to prevent memory leakage CloseHandle(processALL); // If yes, return the specified process handle return processInfo.th32ProcessID; } // An iterative function } while (Process32Next(processALL, &processInfo)); // Release process snapshot to prevent memory leakage CloseHandle(processALL); return 0; } /// <summary> /// Get specified DLL Memory address of /// </summary> /// <param name="pid"></param> /// <param name="moduleName"></param> /// <returns></returns> HMODULE GetProcessModuleHandle(DWORD pid, CONST TCHAR* moduleName) { MODULEENTRY32 moduleEntry; HANDLE handle = NULL; handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); if (!handle) { CloseHandle(handle); return NULL; } ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32)); moduleEntry.dwSize = sizeof(MODULEENTRY32); if (!Module32First(handle, &moduleEntry)) { CloseHandle(handle); return NULL; } do { if (_tcscmp(moduleEntry.szModule, moduleName) == 0) { // Release process snapshot to prevent memory leakage CloseHandle(handle); return moduleEntry.hModule; } } while (Module32Next(handle, &moduleEntry)); CloseHandle(handle); return 0; } /// <summary> /// Assign DLL Inject into the specified process /// </summary> /// <param name="processName">processName Process name</param> /// <param name="dllPath">dllPath dll route</param> void InjectDll(const wchar_t* processName, const char* dllPath) { // Gets the handle of the specified process DWORD dword = GetProcessByName(processName); if (dword == 0) { MessageBox(NULL, TEXT("The specified process was not found"), TEXT("error"), 0); return; } // Open the specified process HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dword); if (hProcess == NULL) { MessageBox(NULL, TEXT("The specified process failed to open"), TEXT("error"), 0); return; } /* Open up a memory space at the address of the specified process to save the path information of the DLL LPVOID VirtualAllocEx( [in] HANDLE hProcess, Open up memory in that process [in, optional] LPVOID lpAddress, The starting address of the development memory (NULL, no need to control the starting position) [in] SIZE_T dwSize, The size of the development memory (the current saved content is the path of the DLL) [in] DWORD flAllocationType, Type of memory allocation. (open up memory) [in] DWORD flProtect,Set memory permissions (readable and writable) ); */ LPVOID DLLAddress = VirtualAllocEx(hProcess, NULL, strlen(dllPath), MEM_COMMIT, PAGE_READWRITE); /* Write the path of the DLL into the newly opened memory BOOL WriteProcessMemory( [in] HANDLE hProcess, // Specified process [in] LPVOID lpBaseAddress, // DLL Path string, write base address [in] LPCVOID lpBuffer, // DLL Path string, pointer to [in] SIZE_T nSize, // Length of bytes to be written to memory [out] SIZE_T *lpNumberOfBytesWritten // [out] Return a pointer, no need, NULL ); */ if (WriteProcessMemory(hProcess, DLLAddress, dllPath, strlen(dllPath), NULL) == 0) { MessageBox(NULL, TEXT("Path write failed"), TEXT("error"), 0); return; } // obtain Kernel32.dll This module HMODULE k32 = GetModuleHandle(TEXT("Kernel32.dll")); // stay Kernel32.dll Found in module LoadLibrary Memory address of this function LPVOID loadADD = GetProcAddress(k32, "LoadLibraryA"); /* Create a thread in the specified process And through this thread, call the LoadLibrary function Load the DLL into the target process through the LoadLibrary function HANDLE CreateRemoteThread( [in] HANDLE hProcess, // Specify process [in] LPSECURITY_ATTRIBUTES lpThreadAttributes, // Set the thread safety property to indicate whether the thread can inherit. NULL is enough [in] SIZE_T dwStackSize, // The initial size of the stack. 0 means the default size of the executable file is used [in] LPTHREAD_START_ROUTINE lpStartAddress, // Pointer to the function to be executed in the remote process [in] LPVOID lpParameter, // Pointer to the DLL path in the current process [in] DWORD dwCreationFlags, // 0 The thread runs immediately after creation. [out] LPDWORD lpThreadId // [out] This return value is not currently required ); */ HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadADD, DLLAddress, 0, NULL); // Release the specified module CloseHandle(hThread); CloseHandle(hProcess); } /// <summary> /// Put in the specified process DLL Unload /// </summary> /// <param name="processName"></param> /// <param name="dllPath"></param> void UnInjectDll(const wchar_t* processName) { // Get the process handle by the process name DWORD dword = GetProcessByName(processName); if (dword == 0) { MessageBox(NULL, TEXT("The specified process was not found"), TEXT("error"), 0); return; } // Gets the memory address of the specified module in the specified process HMODULE hmodule = GetProcessModuleHandle(dword, L"WX_Read_Write.dll"); // Open the specified process HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dword); if (hProcess == NULL) { MessageBox(NULL, TEXT("The specified process failed to open"), TEXT("error"), 0); return; } // obtain Kernel32.dll This module HMODULE k32 = GetModuleHandle(TEXT("Kernel32.dll")); // stay Kernel32.dll Found in module LoadLibrary Memory address of this function LPVOID loadADD = GetProcAddress(k32, "FreeLibrary"); HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadADD, (LPVOID)hmodule, 0, NULL); // Release the specified module CloseHandle(hThread); CloseHandle(hProcess); } /// <summary> /// /// </summary> /// <param name="hwndDlg"></param> /// <param name="uMsg"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <returns></returns> INT_PTR CALLBACK dialogProc(_In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) { wchar_t processName[100] = L"WeChat.exe"; char dllPath[400] = { "C://Users//qiaoas//documents//visual studio 2015//Projects//ConsoleApplication1//Debug//WX_Read_Write.dll" }; switch (uMsg) { case WM_INITDIALOG: break; case WM_CLOSE: EndDialog(hwndDlg, 0); // Closing Windows break; case WM_COMMAND: /*GetDlgItemText(hwndDlg, Text_ProcessName, processName, sizeof(processName)); GetDlgItemText(hwndDlg, Text_DLLPath, (LPWSTR)dllPath, sizeof(dllPath));*/ if (wParam == Btn_Inject_DLL) { if (sizeof(processName) == 0) { MessageBox(NULL, TEXT("Process name cannot be empty"), TEXT("error"), 0); } if (sizeof(dllPath) == 0) { MessageBox(NULL, TEXT("DLL Path cannot be empty"), TEXT("error"), 0); } InjectDll(processName, dllPath); // injection DLL } if (wParam == Btn_unInject_DLL) { UnInjectDll(processName); // uninstall DLL } break; default: break; } return FALSE; } /// <summary> /// initialization /// </summary> /// <param name="hInstance"></param> /// <param name="hPrevInstance"></param> /// <param name="lpCmdLine"></param> /// <param name="nCmdShow"></param> /// <returns></returns> int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, &dialogProc); return 0; }
For beginners of C + +, the code may not be well written in some places, but there is no problem with injection and unloading.
Injection logic explanation:
Use the CreateRemoteThread function to create a new thread for the target process.
A thread created in one process for another process is a remote thread.
Use the LoadLibrary function to load the specified DLL into the process
Therefore, you can call the LoadLibrary function while creating a remote thread to load the specified DLL into the target process.
Why can the DLL be injected into the target process by calling the LoadLibrary function when creating a remote thread
The LoadLibrary function is Kernel32 A member in DLL
Kernel32.dll this DLL is a necessary DLL for creating processes, and all processes point to Kernel32 in memory DLL is the same address
So just get the address of the LoadLibrary function in the current process
Why open up a block of memory in the target process and then write the DLL path to the block memory
The LoadLibrary function requires a parameter, which is the path of the DLL
Transfer an address in the current process to another process. Who knows if the other process reads what we want when it obtains the data in this address.
Therefore, you need to write the path of the DLL directly to the target process.
VirtualAllocEx Function to open up a space in the target process for storage DLL route
WriteProcessMemory Function, put DLL Write in path
GetModuleHandle obtain Kernel32.dll modular
GetProcAddress obtain LoadLibraryA The address of the function in memory
CreateRemoteThread Create a remote thread and call LoadLibraryA function
The difference between LoadLibrary, LoadLibraryA and LoadLibraryW.
LoadLibrary is a macro that can automatically decide whether to use LoadLibraryA or LoadLibraryW according to different character sets
LoadLibrary Macro definition source code WINBASEAPI _Ret_maybenull_ HMODULE WINAPI LoadLibraryA( _In_ LPCSTR lpLibFileName ); WINBASEAPI _Ret_maybenull_ HMODULE WINAPI LoadLibraryW( _In_ LPCWSTR lpLibFileName ); #ifdef UNICODE #define LoadLibrary LoadLibraryW #else #define LoadLibrary LoadLibraryA #endif // !UNICODE
Unload logic:
Use the CreateRemoteThread function to create a remote thread
Call the FreeLibrary function to unload the DLL
FreeLibrary function in Kernel32 DLL module, the logic is the same as above
The FreeLibrary function requires the memory address of the DLL
The memory address of the specified module can be obtained by traversing the process snapshot
The idea of unloading and injection is the same
Confirm whether the DLL is injected into the target process
Method 1: use {procexp
Mode 2: Cheat Engine
Confirm Kernel32 Whether FreeLibrary and LoadLibraryA in DLL point to the same memory address in multiple processes:
You can view {Kernel32. In multiple processes through CE Is the memory address of DLL the same
And then through # Kernel32 DLL, and confirm the functions FreeLibrary and loadlibrary a