Files
xdbg/Utils.cpp
2016-03-13 17:09:35 +08:00

262 lines
6.8 KiB
C++

#include <Windows.h>
#include "Utils.h"
#include "common.h"
#include "Win32ApiWrapper.h"
#include <tlhelp32.h>
#include <Psapi.h>
#include <assert.h>
bool LoadRemoteDll(DWORD pid, const char* dllPath)
{
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (hProc == NULL)
return false;
PVOID p = VirtualAllocEx(hProc, NULL, strlen(dllPath) + 1, MEM_COMMIT, PAGE_READWRITE);
SIZE_T l;
BOOL r = WriteProcessMemory(hProc, p, dllPath, strlen(dllPath) + 1, &l);
if (!r) {
VirtualFreeEx(hProc, p, strlen(dllPath) + 1, MEM_RELEASE);
return false;
}
DWORD tid;
HANDLE hThread = CreateRemoteThread(hProc, NULL, 0,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA"),
p, 0, &tid);
VirtualFreeEx(hProc, p, strlen(dllPath) + 1, MEM_RELEASE);
if (hThread == NULL) {
return false;
}
WaitForSingleObject(hThread, INFINITE);
DWORD exitCode;
GetExitCodeThread(hThread, &exitCode);
CloseHandle(hThread);
return exitCode != 0;
}
BOOL injectDll(DWORD pid, HMODULE hInst)
{
char dllPath[MAX_PATH];
if (!GetModuleFileName((HMODULE)hInst, dllPath, sizeof(dllPath) - 1)) {
assert(false);
return FALSE;
}
if (!LoadRemoteDll(pid, dllPath)) {
assert(false);
MyTrace("injectDll(%u) failed", pid);
return FALSE;
}
return TRUE;
}
typedef NTSTATUS(NTAPI* pNtQIT)(HANDLE ThreadHandle, LONG ThreadInformationClass, PVOID ThreadInformation,
ULONG ThreadInformationLength, PULONG ReturnLength OPTIONAL);
static pNtQIT NtQueryInformationThread = NULL;
PVOID WINAPI GetThreadStartAddress(HANDLE hThread)
{
NTSTATUS ntStatus;
HANDLE hDupHandle;
PVOID dwStartAddress;
if (NtQueryInformationThread == NULL)
NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtQueryInformationThread");
if (NtQueryInformationThread == NULL) {
MyTrace("%s(): cannot found NtQueryInformationThread()", __FUNCTION__);
return 0;
}
HANDLE hCurrentProcess = GetCurrentProcess();
if (!DuplicateHandle(hCurrentProcess, hThread, hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)){
SetLastError(ERROR_ACCESS_DENIED);
MyTrace("%s(): cannot found open thread", __FUNCTION__);
return 0;
}
UINT32 ThreadQuerySetWin32StartAddress = 9;
ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress,
sizeof(PVOID), NULL);
XDbgCloseHandle(hDupHandle);
if (ntStatus != 0) {
MyTrace("%s(): NtQueryInformationThread() failed. status: %x, threadHandle: %x, threadId: %d",
__FUNCTION__, ntStatus, hThread, GetThreadId(hThread));
return 0;
}
return dwStartAddress;
}
PVOID WINAPI GetThreadStartAddress(DWORD tid)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
PVOID addr = GetThreadStartAddress(hThread);
XDbgCloseHandle(hThread);
return addr;
}
_TEB* GetThreadTeb(DWORD tid)
{
NTSTATUS ntStatus;
if (NtQueryInformationThread == NULL)
NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtQueryInformationThread");
if (NtQueryInformationThread == NULL) {
MyTrace("%s(): cannot found NtQueryInformationThread()", __FUNCTION__);
return 0;
}
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid);
UINT32 ThreadBasicInformation = 0;
THREAD_BASIC_INFORMATION bi;
ntStatus = NtQueryInformationThread(hThread, ThreadBasicInformation, &bi, sizeof(bi), NULL);
XDbgCloseHandle(hThread);
if (ntStatus != 0)
return 0;
return (_TEB*)bi.TebBaseAddress;
}
#ifndef MAKEULONGLONG
#define MAKEULONGLONG(ldw, hdw) ((ULONGLONG(hdw) << 32) | ((ldw) & 0xFFFFFFFF))
#endif
#ifndef MAXULONGLONG
#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0))
#endif
DWORD GetProcessMainThread(DWORD dwProcID)
{
DWORD dwMainThreadID = 0;
ULONGLONG ullMinCreateTime = MAXULONGLONG;
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap != INVALID_HANDLE_VALUE) {
THREADENTRY32 th32;
th32.dwSize = sizeof(THREADENTRY32);
BOOL bOK = TRUE;
for (bOK = Thread32First(hThreadSnap, &th32); bOK;
bOK = Thread32Next(hThreadSnap, &th32)) {
if (th32.th32OwnerProcessID == dwProcID) {
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION,
TRUE, th32.th32ThreadID);
if (hThread) {
FILETIME afTimes[4] = { 0 };
if (GetThreadTimes(hThread,
&afTimes[0], &afTimes[1], &afTimes[2], &afTimes[3])) {
ULONGLONG ullTest = MAKEULONGLONG(afTimes[0].dwLowDateTime,
afTimes[0].dwHighDateTime);
if (ullTest && ullTest < ullMinCreateTime) {
ullMinCreateTime = ullTest;
dwMainThreadID = th32.th32ThreadID; // let it be main... :)
}
}
CloseHandle(hThread);
}
}
}
CloseHandle(hThreadSnap);
}
return (dwMainThreadID);
}
#ifdef _M_X64
void cloneThreadContext(CONTEXT* dest, const CONTEXT* src, DWORD ContextFlags)
{
// NO IMPLEMENTATION
assert(false);
}
#else
void cloneThreadContext(CONTEXT* dest, const CONTEXT* src, DWORD ContextFlags)
{
// no extended registers && floating point registers
if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
/* EBP, EIP and EFLAGS */
dest->Ebp = src->Ebp;
dest->Eip = src->Eip;
dest->EFlags = src->EFlags;
dest->SegCs = src->SegCs;
dest->SegSs = src->SegSs;
dest->Esp = src->Esp;
}
if ((ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) {
dest->SegGs = src->SegGs;
dest->SegFs = src->SegFs;
dest->SegEs = src->SegEs;
dest->SegDs = src->SegDs;
}
if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
dest->Eax = src->Eax;
dest->Ebx = src->Ebx;
dest->Ecx = src->Ecx;
dest->Edx = src->Edx;
dest->Esi = src->Esi;
dest->Edi = src->Edi;
}
if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) {
dest->Dr0 = src->Dr0;
dest->Dr1 = src->Dr1;
dest->Dr2 = src->Dr2;
dest->Dr3 = src->Dr3;
dest->Dr6 = src->Dr6;
dest->Dr7 = src->Dr7;
}
if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
dest->FloatSave = src->FloatSave;
}
if ((ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS) {
memcpy(dest->ExtendedRegisters, src->ExtendedRegisters, sizeof(src->ExtendedRegisters));
}
}
#endif
DWORD WINAPI GetThreadIdFromHandle(HANDLE hThread)
{
NTSTATUS ntStatus;
if (NtQueryInformationThread == NULL)
NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtQueryInformationThread");
if (NtQueryInformationThread == NULL) {
MyTrace("%s(): cannot found NtQueryInformationThread()", __FUNCTION__);
return 0;
}
HANDLE hThread2;
if (!DuplicateHandle(GetCurrentProcess(), hThread, GetCurrentProcess(), &hThread2,
THREAD_ALL_ACCESS, FALSE, 0))
return 0;
UINT32 ThreadBasicInformation = 0;
THREAD_BASIC_INFORMATION bi;
ntStatus = NtQueryInformationThread(hThread2, ThreadBasicInformation, &bi, sizeof(bi), NULL);
CloseHandle(hThread2);
if (ntStatus != 0)
return 0;
return bi.ClientId.UniqueThread;
}