Update Injector

This commit is contained in:
Changhua 2022-08-14 07:15:05 +08:00
parent ab93568598
commit 19f83f3c0c
3 changed files with 63 additions and 680 deletions

View File

@ -1,653 +1,70 @@
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "injector.h"
#include "injector.h"
#include <malloc.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
typedef BOOL(WINAPI *IsWow64Process2_t)(HANDLE hProcess, USHORT *pProcessMachine, USHORT *pNativeMachine);
static DWORD page_size = 0;
static size_t func_LoadLibraryW;
static size_t func_FreeLibrary;
static size_t func_GetLastError;
static char errmsg[512];
static injector_t *g_injector;
#ifdef _M_AMD64
static const char x64_code_template[] =
// ---------- call LoadLibraryW ----------
/* 0000: */ "\x48\x83\xEC\x28" // sub rsp,28h
/* 0004: */ "\xFF\x15\x3E\x00\x00\x00" // call LoadLibraryW
// 0x0000003e = X64_ADDR_LoadLibraryW - (0x0004 + 6)
/* 000A: */ "\x48\x85\xC0" // test rax,rax
/* 000D: */ "\x74\x0B" // je L1
/* 000F: */ "\x48\x89\x05\xEA\x0F\x00\x00" // mov [load_address], rax
// 0x00000fea = 0x1000 - (0x000F + 7)
/* 0016: */ "\x33\xC0" // xor eax,eax
/* 0018: */ "\xEB\x06" // jmp L2
/* 001A: L1: */ "\xFF\x15\x38\x00\x00\x00" // call GetLastError
// 0x00000038 = X64_ADDR_GetLastError - (0x001A + 6)
/* 0020: L2: */ "\x48\x83\xC4\x28" // add rsp,28h
/* 0024: */ "\xC3" // ret
// ---------- call FreeLibrary ----------
#define X64_UNINJECTION_CODE_OFFSET 0x25
/* 0025: */ "\x48\x83\xEC\x28" // sub rsp,28h
/* 0029: */ "\xFF\x15\x21\x00\x00\x00" // call FreeLibrary
// 0x00000021 = X64_ADDR_FreeLibrary - (0x0029 + 6)
/* 002F: */ "\x85\xC0" // test eax,eax
/* 0031: */ "\x74\x04" // je L1
/* 0033: */ "\x33\xC0" // xor eax,eax
/* 0035: */ "\xEB\x06" // jmp L2
/* 0037: L1: */ "\xFF\x15\x1B\x00\x00\x00" // call GetLastError
// 0x0000001B = X64_ADDR_GetLastError - (0x0037 + 6)
/* 003D: L2: */ "\x48\x83\xC4\x28" // add rsp,28h
/* 0041: */ "\xC3" // ret
// padding
/* 0042: */ "\x90\x90\x90\x90\x90\x90"
// ---------- literal pool ----------
#define X64_ADDR_LoadLibraryW 0x0048
/* 0048: */ "\x90\x90\x90\x90\x90\x90\x90\x90"
#define X64_ADDR_FreeLibrary 0x0050
/* 0050: */ "\x90\x90\x90\x90\x90\x90\x90\x90"
#define X64_ADDR_GetLastError 0x0058
/* 0058: */ "\x90\x90\x90\x90\x90\x90\x90\x90";
#define X64_CODE_SIZE 0x0060
#endif
#if defined(_M_AMD64) || defined(_M_IX86)
static const char x86_code_template[] =
// ---------- call LoadLibraryW ----------
/* 0000: */ "\xFF\x74\x24\x04" // push dword ptr [esp+4]
#define X86_CALL_LoadLibraryW 0x0004
/* 0004: */ "\xE8\x00\x00\x00\x00" // call LoadLibraryW@4
/* 0009: */ "\x85\xC0" // test eax,eax
/* 000B: */ "\x74\x09" // je L1
#define X86_MOV_EAX 0x000D
/* 000D: */ "\xA3\x00\x00\x00\x00" // mov dword ptr [load_address], eax
/* 0012: */ "\x33\xC0" // xor eax,eax
/* 0014: */ "\xEB\x05" // jmp L2
#define X86_CALL_GetLastError1 0x0016
/* 0016: L1: */ "\xE8\x00\x00\x00\x00" // call GetLastError@0
/* 001B: L2: */ "\xC2\x04\x00" // ret 4
// ---------- call FreeLibrary ----------
#define X86_UNINJECTION_CODE_OFFSET 0x001E
/* 001E: */ "\xFF\x74\x24\x04" // push dword ptr [esp+4]
#define X86_CALL_FreeLibrary 0x0022
/* 0022: */ "\xE8\x00\x00\x00\x00" // call FreeLibrary@4
/* 0027: */ "\x85\xC0" // test eax,eax
/* 0029: */ "\x74\x04" // je L1
/* 002B: */ "\x33\xC0" // xor eax,eax
/* 002D: */ "\xEB\x05" // jmp L2
#define X86_CALL_GetLastError2 0x002F
/* 002F: L1: */ "\xE8\x00\x00\x00\x00" // call GetLastError@0
/* 0034: L2: */ "\xC2\x04\x00" // ret 4
;
#define X86_CODE_SIZE 0x0037
#endif
#ifdef _M_AMD64
#define CURRENT_ARCH "x64"
#define CODE_SIZE X64_CODE_SIZE
#endif
#ifdef _M_IX86
#define CURRENT_ARCH "x86"
#define CODE_SIZE X86_CODE_SIZE
#endif
static void set_errmsg(const char *format, ...);
static const char *w32strerr(DWORD err);
static USHORT process_arch(HANDLE hProcess);
static const char *arch_name(USHORT arch);
struct injector {
HANDLE hProcess;
char *remote_mem;
char *injection_code;
char *uninjection_code;
};
static BOOL init(void)
{
SYSTEM_INFO si;
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tp;
HMODULE kernel32 = GetModuleHandleA("kernel32");
if (kernel32 == 0) {
return FALSE;
}
GetSystemInfo(&si);
page_size = si.dwPageSize;
func_LoadLibraryW = (size_t)GetProcAddress(kernel32, "LoadLibraryW");
func_FreeLibrary = (size_t)GetProcAddress(kernel32, "FreeLibrary");
func_GetLastError = (size_t)GetProcAddress(kernel32, "GetLastError");
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
return FALSE;
}
if (!LookupPrivilegeValue(0, SE_DEBUG_NAME, &luid)) {
CloseHandle(hToken);
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL)) {
CloseHandle(hToken);
return FALSE;
}
CloseHandle(hToken);
return TRUE;
}
#if defined(_M_AMD64)
static int cmp_func(const void *context, const void *key, const void *datum)
{
ptrdiff_t rva_to_va = (ptrdiff_t)context;
const char *k = (const char *)key;
const char *d = (const char *)(rva_to_va + *(const DWORD *)datum);
return strcmp(k, d);
}
static int funcaddr(DWORD pid, size_t *load_library, size_t *free_library, size_t *get_last_error)
{
HANDLE hSnapshot;
MODULEENTRY32W me;
BOOL ok;
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFileMapping = NULL;
void *base = NULL;
IMAGE_NT_HEADERS *nt_hdrs;
ULONG exp_size;
const IMAGE_EXPORT_DIRECTORY *exp;
const DWORD *names, *name, *funcs;
const WORD *ordinals;
ptrdiff_t rva_to_va;
int rv = INJERR_OTHER;
/* Get the full path of kernel32.dll. */
retry:
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
if (hSnapshot == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
switch (err) {
case ERROR_BAD_LENGTH:
goto retry;
case ERROR_ACCESS_DENIED:
rv = INJERR_PERMISSION;
break;
case ERROR_INVALID_PARAMETER:
rv = INJERR_NO_PROCESS;
break;
default:
rv = INJERR_OTHER;
}
set_errmsg("CreateToolhelp32Snapshot error: %s", w32strerr(err));
return rv;
}
me.dwSize = sizeof(me);
for (ok = Module32FirstW(hSnapshot, &me); ok; ok = Module32NextW(hSnapshot, &me)) {
if (wcsicmp(me.szModule, L"kernel32.dll") == 0) {
break;
}
}
CloseHandle(hSnapshot);
if (!ok) {
set_errmsg("kernel32.dll could not be found.");
return INJERR_OTHER;
}
/* Get the export directory in the kernel32.dll. */
hFile = CreateFileW(me.szExePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
set_errmsg("failed to open file %s: %s", me.szExePath, w32strerr(GetLastError()));
goto exit;
}
hFileMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hFileMapping == NULL) {
set_errmsg("failed to create file mapping of %s: %s", me.szExePath, w32strerr(GetLastError()));
goto exit;
}
base = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
if (base == NULL) {
set_errmsg("failed to map file %s to memory: %s", me.szExePath, w32strerr(GetLastError()));
goto exit;
}
nt_hdrs = ImageNtHeader(base);
if (nt_hdrs == NULL) {
set_errmsg("ImageNtHeader error: %s", w32strerr(GetLastError()));
goto exit;
}
exp = (const IMAGE_EXPORT_DIRECTORY *)ImageDirectoryEntryToDataEx(base, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT,
&exp_size, NULL);
if (exp == NULL) {
set_errmsg("ImageDirectoryEntryToDataEx error: %s", w32strerr(GetLastError()));
goto exit;
}
if (exp->NumberOfNames == 0) {
set_errmsg("No export entires are not found.");
goto exit;
}
names = (const DWORD *)ImageRvaToVa(nt_hdrs, base, exp->AddressOfNames, NULL);
if (names == NULL) {
set_errmsg("ImageRvaToVa error: %s", w32strerr(GetLastError()));
goto exit;
}
ordinals = (const WORD *)ImageRvaToVa(nt_hdrs, base, exp->AddressOfNameOrdinals, NULL);
if (ordinals == NULL) {
set_errmsg("ImageRvaToVa error: %s", w32strerr(GetLastError()));
goto exit;
}
funcs = (const DWORD *)ImageRvaToVa(nt_hdrs, base, exp->AddressOfFunctions, NULL);
if (funcs == NULL) {
set_errmsg("ImageRvaToVa error: %s", w32strerr(GetLastError()));
goto exit;
}
rva_to_va = (size_t)ImageRvaToVa(nt_hdrs, base, names[0], NULL) - (size_t)names[0];
/* Find the address of LoadLibraryW */
name = bsearch_s((void *)"LoadLibraryW", names, exp->NumberOfNames, sizeof(DWORD), cmp_func, (void *)rva_to_va);
if (name == NULL) {
set_errmsg("Could not find the address of LoadLibraryW");
goto exit;
}
*load_library = (size_t)me.modBaseAddr + funcs[ordinals[name - names]];
/* Find the address of FreeLibrary */
name = bsearch_s((void *)"FreeLibrary", names, exp->NumberOfNames, sizeof(DWORD), cmp_func, (void *)rva_to_va);
if (name == NULL) {
set_errmsg("Could not find the address of FreeLibrary");
goto exit;
}
*free_library = (size_t)me.modBaseAddr + funcs[ordinals[name - names]];
/* Find the address of GetLastError */
name = bsearch_s((void *)"GetLastError", names, exp->NumberOfNames, sizeof(DWORD), cmp_func, (void *)rva_to_va);
if (name == NULL) {
set_errmsg("Could not find the address of GetLastError");
goto exit;
}
*get_last_error = (size_t)me.modBaseAddr + funcs[ordinals[name - names]];
rv = 0;
exit:
if (base != NULL) {
UnmapViewOfFile(base);
}
if (hFileMapping != NULL) {
CloseHandle(hFileMapping);
}
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
}
return rv;
}
#endif
int cki_attach(injector_t **injector_out, DWORD pid)
{
injector_t *injector;
DWORD dwDesiredAccess = PROCESS_QUERY_LIMITED_INFORMATION | /* for IsWow64Process() */
PROCESS_CREATE_THREAD | /* for CreateRemoteThread() */
PROCESS_VM_OPERATION | /* for VirtualAllocEx() */
PROCESS_VM_READ | /* for ReadProcessMemory() */
PROCESS_VM_WRITE; /* for WriteProcessMemory() */
USHORT arch;
DWORD old_protect;
SIZE_T written;
int rv;
char code[CODE_SIZE];
size_t code_size;
size_t load_library, free_library, get_last_error;
if (page_size == 0) {
init();
}
load_library = func_LoadLibraryW;
free_library = func_FreeLibrary;
get_last_error = func_GetLastError;
injector = (injector_t *)calloc(1, sizeof(injector_t));
if (injector == NULL) {
set_errmsg("malloc error: %s", strerror(errno));
return INJERR_NO_MEMORY;
}
injector->hProcess = OpenProcess(dwDesiredAccess, FALSE, pid);
if (injector->hProcess == NULL) {
DWORD err = GetLastError();
set_errmsg("OpenProcess error: %s", w32strerr(err));
switch (err) {
case ERROR_ACCESS_DENIED:
rv = INJERR_PERMISSION;
break;
case ERROR_INVALID_PARAMETER:
rv = INJERR_NO_PROCESS;
break;
default:
rv = INJERR_OTHER;
}
goto error_exit;
}
arch = process_arch(injector->hProcess);
switch (arch) {
#ifdef _M_AMD64
case IMAGE_FILE_MACHINE_AMD64:
break;
case IMAGE_FILE_MACHINE_I386:
rv = funcaddr(pid, &load_library, &free_library, &get_last_error);
if (rv != 0) {
goto error_exit;
}
break;
#endif
#ifdef _M_IX86
case IMAGE_FILE_MACHINE_I386:
break;
#endif
default:
set_errmsg("%s target process isn't supported by %s process.", arch_name(arch), CURRENT_ARCH);
rv = INJERR_UNSUPPORTED_TARGET;
goto error_exit;
}
injector->remote_mem
= (char *)VirtualAllocEx(injector->hProcess, NULL, 2 * page_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (injector->remote_mem == NULL) {
set_errmsg("VirtualAllocEx error: %s", w32strerr(GetLastError()));
rv = INJERR_OTHER;
goto error_exit;
}
injector->injection_code = injector->remote_mem;
switch (arch) {
#ifdef _M_AMD64
case IMAGE_FILE_MACHINE_AMD64: /* x64 */
memcpy(code, x64_code_template, X64_CODE_SIZE);
code_size = X64_CODE_SIZE;
*(size_t *)(code + X64_ADDR_LoadLibraryW) = load_library;
*(size_t *)(code + X64_ADDR_FreeLibrary) = free_library;
*(size_t *)(code + X64_ADDR_GetLastError) = get_last_error;
injector->uninjection_code = injector->remote_mem + X64_UNINJECTION_CODE_OFFSET;
break;
#endif
#if defined(_M_AMD64) || defined(_M_IX86)
case IMAGE_FILE_MACHINE_I386: /* x86 */
memcpy(code, x86_code_template, X86_CODE_SIZE);
code_size = X86_CODE_SIZE;
#define FIX_CALL_RELATIVE(addr, offset) \
*(uint32_t *)(code + offset + 1) = addr - ((uint32_t)(size_t)injector->remote_mem + offset + 5)
FIX_CALL_RELATIVE(load_library, X86_CALL_LoadLibraryW);
FIX_CALL_RELATIVE(free_library, X86_CALL_FreeLibrary);
FIX_CALL_RELATIVE(get_last_error, X86_CALL_GetLastError1);
FIX_CALL_RELATIVE(get_last_error, X86_CALL_GetLastError2);
*(uint32_t *)(code + X86_MOV_EAX + 1) = (uint32_t)(size_t)injector->remote_mem + page_size;
injector->uninjection_code = injector->remote_mem + X86_UNINJECTION_CODE_OFFSET;
break;
#endif
default:
set_errmsg("Never reach here: arch=0x%x", arch);
rv = INJERR_OTHER;
goto error_exit;
}
if (!WriteProcessMemory(injector->hProcess, injector->remote_mem, code, code_size, &written)) {
set_errmsg("WriteProcessMemory error: %s", w32strerr(GetLastError()));
rv = INJERR_OTHER;
goto error_exit;
}
if (!VirtualProtectEx(injector->hProcess, injector->remote_mem, page_size, PAGE_EXECUTE_READ, &old_protect)) {
set_errmsg("VirtualProtectEx error: %s", w32strerr(GetLastError()));
rv = INJERR_OTHER;
goto error_exit;
}
*injector_out = injector;
return 0;
error_exit:
cki_detach(injector);
return rv;
}
int cki_inject(injector_t *injector, const char *path, void **handle)
{
DWORD pathlen = (DWORD)strlen(path);
wchar_t *wpath;
DWORD wpathlen;
if (pathlen == 0) {
set_errmsg("The specified path is empty.");
return INJERR_FILE_NOT_FOUND;
}
if (pathlen > MAX_PATH) {
set_errmsg("too long file path: %s", path);
return INJERR_FILE_NOT_FOUND;
}
wpath = (wchar_t *)_alloca((pathlen + 1) * sizeof(wchar_t));
wpathlen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, path, pathlen, wpath, pathlen + 1);
wpath[wpathlen] = L'\0';
return cki_inject_w(injector, wpath, handle);
}
int cki_inject_w(injector_t *injector, const wchar_t *path, void **handle)
{
struct {
void *load_address;
wchar_t fullpath[MAX_PATH];
} data = {
NULL,
};
DWORD pathlen;
SIZE_T written;
HANDLE hThread;
DWORD err;
pathlen = GetFullPathNameW(path, MAX_PATH, data.fullpath, NULL);
if (pathlen > MAX_PATH) {
set_errmsg("too long file path: %S", path);
return INJERR_FILE_NOT_FOUND;
}
if (pathlen == 0) {
set_errmsg("failed to get the full path: %S", path);
return INJERR_FILE_NOT_FOUND;
}
if (!WriteProcessMemory(injector->hProcess, injector->remote_mem + page_size, &data, sizeof(data), &written)) {
set_errmsg("WriteProcessMemory error: %s", w32strerr(GetLastError()));
return INJERR_OTHER;
}
hThread = CreateRemoteThread(injector->hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)injector->injection_code,
injector->remote_mem + page_size + sizeof(void *), 0, NULL);
if (hThread == NULL) {
set_errmsg("CreateRemoteThread error: %s", w32strerr(GetLastError()));
return INJERR_OTHER;
}
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &err);
CloseHandle(hThread);
if (err != 0) {
set_errmsg("LoadLibrary in the target process failed: %s", w32strerr(err));
return INJERR_ERROR_IN_TARGET;
}
if (!ReadProcessMemory(injector->hProcess, injector->remote_mem + page_size, &data, sizeof(void *), &written)) {
set_errmsg("ReadProcessMemory error: %s", w32strerr(GetLastError()));
return INJERR_OTHER;
}
if (handle != NULL) {
*handle = data.load_address;
}
return 0;
}
int cki_uninject(injector_t *injector, void *handle)
int InjectDll(DWORD pid, const WCHAR *dllPath)
{
HANDLE hThread;
DWORD err;
DWORD dwWriteSize = 0;
// 1. 获取目标进程,并在目标进程的内存里开辟空间
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE);
hThread = CreateRemoteThread(injector->hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)injector->uninjection_code,
handle, 0, NULL);
if (hThread == NULL) {
set_errmsg("CreateRemoteThread error: %s", w32strerr(GetLastError()));
return INJERR_OTHER;
// 2. 把 dll 的路径写入到目标进程的内存空间中
if (pRemoteAddress) {
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, wcslen(dllPath) * 2 + 2, &dwWriteSize);
} else {
MessageBox(NULL, L"DLL 路径写入失败", L"InjectDll", 0);
return -1;
}
// 3. 创建一个远程线程,让目标进程调用 LoadLibrary
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, pRemoteAddress, NULL, NULL);
if (hThread) {
WaitForSingleObject(hThread, -1);
} else {
MessageBox(NULL, L"LoadLibrary 调用失败", L"InjectDll", 0);
return -2;
}
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &err);
CloseHandle(hThread);
if (err != 0) {
set_errmsg("FreeLibrary in the target process failed: %s", w32strerr(err));
return INJERR_ERROR_IN_TARGET;
}
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 0;
}
int cki_detach(injector_t *injector)
int EjectDll(DWORD pid, const WCHAR *dllPath)
{
if (injector->remote_mem != NULL) {
VirtualFreeEx(injector->hProcess, injector->remote_mem, 0, MEM_RELEASE);
DWORD dwHandle, dwID;
HANDLE hThread = NULL;
DWORD dwWriteSize = 0;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE);
if (pRemoteAddress)
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, wcslen(dllPath) * 2 + 2, &dwWriteSize);
else {
MessageBox(NULL, L"DLL 路径写入失败", L"EjectDll", 0);
return -1;
}
if (injector->hProcess != NULL) {
CloseHandle(injector->hProcess);
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetModuleHandleW, pRemoteAddress, 0, &dwID);
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &dwHandle);
} else {
MessageBox(NULL, L"GetModuleHandleW 调用失败!", L"EjectDll", 0);
return -2;
}
free(injector);
CloseHandle(hThread);
// 使目标进程调用 FreeLibrary卸载 DLL
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, (LPVOID)dwHandle, 0, &dwID);
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
} else {
MessageBox(NULL, L"FreeLibrary 调用失败!", L"EjectDll", 0);
return -3;
}
CloseHandle(hThread);
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 0;
}
const char *cki_error(void) { return errmsg; }
static void set_errmsg(const char *format, ...)
{
va_list ap;
int rv;
va_start(ap, format);
rv = vsnprintf(errmsg, sizeof(errmsg), format, ap);
va_end(ap);
if (rv == -1 || rv >= sizeof(errmsg)) {
errmsg[sizeof(errmsg) - 1] = '\0';
}
}
static const char *w32strerr(DWORD err)
{
static char errmsg[512];
DWORD len;
len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), errmsg, sizeof(errmsg), NULL);
if (len > 0) {
while (len > 0) {
char c = errmsg[len - 1];
if (c == ' ' || c == '\n' || c == '\r') {
len--;
} else {
break;
}
}
errmsg[len] = '\0';
} else if ((int)err >= 0) {
sprintf(errmsg, "win32 error code %d", err);
} else {
sprintf(errmsg, "win32 error code 0x%x", err);
}
return errmsg;
}
static USHORT process_arch(HANDLE hProcess)
{
static IsWow64Process2_t IsWow64Process2_func = (IsWow64Process2_t)-1;
if (IsWow64Process2_func == (IsWow64Process2_t)-1) {
IsWow64Process2_func = (IsWow64Process2_t)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process2");
}
if (IsWow64Process2_func != NULL) {
/* Windows 10 */
USHORT process_machine;
USHORT native_machine;
if (IsWow64Process2_func(hProcess, &process_machine, &native_machine)) {
if (process_machine != IMAGE_FILE_MACHINE_UNKNOWN) {
return process_machine;
} else {
return native_machine;
}
}
} else {
/* Windows 8.1 or earlier */
/* arch will be either x86 or x64. */
#ifdef _M_AMD64
BOOL is_wow64_proc;
if (IsWow64Process(hProcess, &is_wow64_proc)) {
if (is_wow64_proc) {
return IMAGE_FILE_MACHINE_I386;
} else {
return IMAGE_FILE_MACHINE_AMD64;
}
}
#endif
#ifdef _M_IX86
BOOL is_wow64_proc;
if (IsWow64Process(GetCurrentProcess(), &is_wow64_proc)) {
if (!is_wow64_proc) {
/* Run on 32-bit Windows */
return IMAGE_FILE_MACHINE_I386;
}
/* Run on Windows x64 */
if (IsWow64Process(hProcess, &is_wow64_proc)) {
if (is_wow64_proc) {
return IMAGE_FILE_MACHINE_I386;
} else {
return IMAGE_FILE_MACHINE_AMD64;
}
}
}
#endif
}
return IMAGE_FILE_MACHINE_UNKNOWN;
}
static const char *arch_name(USHORT arch)
{
switch (arch) {
case IMAGE_FILE_MACHINE_AMD64:
return "x64";
case IMAGE_FILE_MACHINE_I386:
return "x86";
default:
return "unknown";
}
}
BOOL InjectDll(DWORD pid, const WCHAR *dllpath)
{
if (cki_attach(&g_injector, pid) != 0) {
printf("%s\n", cki_error());
return FALSE;
}
if (cki_inject_w(g_injector, dllpath, NULL) == 0) {
return TRUE;
} else {
fprintf(stderr, " %s\n", cki_error());
return FALSE;
}
}
BOOL EnjectDll(DWORD pid, const WCHAR *dllname)
{
if (cki_detach(g_injector) == 0) {
return TRUE;
}
return FALSE;
}

View File

@ -1,40 +1,6 @@
#ifndef __INJECTOR_H__
#define __INJECTOR_H__
#pragma once
#include "framework.h"
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
#define INJERR_SUCCESS 0
#define INJERR_OTHER -1
#define INJERR_NO_MEMORY -2
#define INJERR_NO_PROCESS -3
#define INJERR_NO_LIBRARY -4
#define INJERR_NO_FUNCTION -4
#define INJERR_ERROR_IN_TARGET -5
#define INJERR_FILE_NOT_FOUND -6
#define INJERR_INVALID_MEMORY_AREA -7
#define INJERR_PERMISSION -8
#define INJERR_UNSUPPORTED_TARGET -9
#define INJERR_INVALID_ELF_FORMAT -10
#define INJERR_WAIT_TRACEE -11
typedef struct injector injector_t;
int cki_attach(injector_t **injector, DWORD pid);
int cki_inject(injector_t *injector, const char *path, void **handle);
int cki_inject_w(injector_t *injector, const wchar_t *path, void **handle);
int cki_uninject(injector_t *injector, void *handle);
int cki_detach(injector_t *injector);
const char *cki_error(void);
BOOL InjectDll(DWORD pid, const WCHAR *dllpath);
BOOL EnjectDll(DWORD pid, const WCHAR *dllname);
#ifdef __cplusplus
}; /* extern "C" */
#endif
#endif
int InjectDll(DWORD pid, const WCHAR* dllPath);
int EjectDll(DWORD pid, const WCHAR* dllPath);

View File

@ -35,7 +35,7 @@ int WxInitSDK()
return status;
}
Sleep(2000); // 等待微信打开
if (!InjectDll(WeChatPID, SpyDllPath)) {
if (InjectDll(WeChatPID, SpyDllPath)) {
return -1;
}
@ -51,7 +51,7 @@ int WxInitSDK()
int WxDestroySDK()
{
RpcDisconnectServer();
EnjectDll(WeChatPID, SpyDllPath);
EjectDll(WeChatPID, SpyDllPath);
return ERROR_SUCCESS;
}