168 lines
4.8 KiB
C++
168 lines
4.8 KiB
C++
|
// inject.cc
|
||
|
// 1/27/2013 jichi
|
||
|
#include "windbg/inject.h"
|
||
|
#include "windbg/windbg_p.h"
|
||
|
#include <cwchar> // for wcslen
|
||
|
|
||
|
//#define DEBUG "windbg::inject"
|
||
|
#include "sakurakit/skdebug.h"
|
||
|
|
||
|
WINDBG_BEGIN_NAMESPACE
|
||
|
|
||
|
// - Remote Injection -
|
||
|
|
||
|
BOOL InjectFunction1(LPCVOID addr, LPCVOID data, SIZE_T dataSize, DWORD pid, HANDLE hProcess, INT timeout)
|
||
|
{
|
||
|
DOUT("enter: pid =" << pid);
|
||
|
if (hProcess == INVALID_HANDLE_VALUE && pid) {
|
||
|
hProcess = ::OpenProcess(PROCESS_INJECT_ACCESS, FALSE, pid);
|
||
|
// TODO: Privilege elevation is not implemented. See: skwinsec.py.
|
||
|
//if (!hProcess) {
|
||
|
// priv = SkProcessElevator('SeDebugPrivilege')
|
||
|
// if not priv.isEmpty():
|
||
|
// handle = win32api.OpenProcess(PROCESS_INJECT_ACCESS, 0, pid)
|
||
|
//}
|
||
|
}
|
||
|
if (hProcess == INVALID_HANDLE_VALUE) {
|
||
|
DOUT("exit: error: failed to get process handle");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL ret = FALSE;
|
||
|
if (LPVOID remoteData = ::VirtualAllocEx(hProcess, nullptr, dataSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)) {
|
||
|
if (::WriteProcessMemory(hProcess, remoteData, data, dataSize, nullptr))
|
||
|
if (HANDLE hThread = ::CreateRemoteThread(
|
||
|
hProcess,
|
||
|
nullptr, 0,
|
||
|
reinterpret_cast<LPTHREAD_START_ROUTINE>(addr),
|
||
|
remoteData,
|
||
|
0, nullptr)) {
|
||
|
::WaitForSingleObject(hThread, timeout);
|
||
|
::CloseHandle(hThread);
|
||
|
ret = TRUE;
|
||
|
}
|
||
|
::VirtualFreeEx(hProcess, remoteData, dataSize, MEM_RELEASE);
|
||
|
}
|
||
|
::CloseHandle(hProcess);
|
||
|
DOUT("exit: ret =" << ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
BOOL injectDllW(LPCWSTR dllPath, DWORD pid, HANDLE hProcess, INT timeout)
|
||
|
{
|
||
|
DOUT("enter: pid =" << pid);
|
||
|
LPCVOID fun = details::getModuleFunctionAddressA("LoadLibraryW", "kernel32.dll");
|
||
|
if (!fun) {
|
||
|
DOUT("exit error: cannot find function");
|
||
|
return FALSE;
|
||
|
}
|
||
|
LPCVOID data = dllPath;
|
||
|
SIZE_T dataSize = ::wcslen(dllPath) * 2 + 2; // L'\0'
|
||
|
BOOL ok = InjectFunction1(fun, data, dataSize, pid, hProcess, timeout);
|
||
|
DOUT("exit: ret =" << ok);
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
BOOL ejectDll(HANDLE hDll, DWORD pid, HANDLE hProcess, INT timeout)
|
||
|
{
|
||
|
DOUT("enter: pid =" << pid);
|
||
|
LPCVOID fun = details::getModuleFunctionAddressA("FreeLibrary", "kernel32.dll");
|
||
|
if (!fun) {
|
||
|
DOUT("exit error: cannot find function");
|
||
|
return FALSE;
|
||
|
}
|
||
|
LPCVOID data = &hDll;
|
||
|
SIZE_T dataSize = sizeof(hDll);
|
||
|
BOOL ok = InjectFunction1(fun, data, dataSize, pid, hProcess, timeout);
|
||
|
DOUT("exit: ret =" << ok);
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
WINDBG_END_NAMESPACE
|
||
|
|
||
|
// EOF
|
||
|
|
||
|
/*
|
||
|
enum { CREATE_THREAD_ACCESS = (PROCESS_CREATE_THREAD |
|
||
|
PROCESS_QUERY_INFORMATION |
|
||
|
PROCESS_VM_OPERATION |
|
||
|
PROCESS_VM_WRITE |
|
||
|
PROCESS_VM_READ ) };
|
||
|
|
||
|
|
||
|
int InjectDll(HANDLE hProcess, HINSTANCE hInst) {
|
||
|
HANDLE hThread;
|
||
|
|
||
|
wchar_t dllFile[2*MAX_PATH];
|
||
|
if (GetModuleFileNameW(hInst, dllFile, sizeof(dllFile)/2) > sizeof(dllFile)/2) return 0;
|
||
|
|
||
|
void *loadLibraryW = GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW");
|
||
|
if (!loadLibraryW) return 0;
|
||
|
|
||
|
wchar_t *name;
|
||
|
if (!(name = wcsrchr(dllFile, '\\'))) return 0;
|
||
|
name ++;
|
||
|
wcscpy(name, DLL_NAME);
|
||
|
if (GetFileAttributes(dllFile) == INVALID_FILE_ATTRIBUTES) return 0;
|
||
|
|
||
|
size_t len = sizeof(wchar_t)*(1+wcslen(dllFile));
|
||
|
void *remoteString = (LPVOID)VirtualAllocEx(hProcess,
|
||
|
NULL,
|
||
|
len,
|
||
|
MEM_RESERVE|MEM_COMMIT,
|
||
|
PAGE_READWRITE
|
||
|
);
|
||
|
if (remoteString) {
|
||
|
if (WriteProcessMemory(hProcess, (LPVOID)remoteString, dllFile, len, NULL)) {
|
||
|
if (hThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)loadLibraryW, (LPVOID)remoteString, 0,0)) {
|
||
|
WaitForSingleObject(hThread, 3000);
|
||
|
CloseHandle(hThread);
|
||
|
VirtualFreeEx(hProcess, remoteString, len, MEM_FREE);
|
||
|
// Make sure it's injected before resuming.
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
VirtualFreeEx(hProcess, remoteString, len, MEM_FREE);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int getPriv(const char * name) {
|
||
|
HANDLE hToken;
|
||
|
LUID seValue;
|
||
|
TOKEN_PRIVILEGES tkp;
|
||
|
|
||
|
if (!LookupPrivilegeValueA(NULL, name, &seValue) ||
|
||
|
!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
tkp.PrivilegeCount = 1;
|
||
|
tkp.Privileges[0].Luid = seValue;
|
||
|
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||
|
|
||
|
int res = AdjustTokenPrivileges(hToken, 0, &tkp, sizeof(tkp), NULL, NULL);
|
||
|
|
||
|
CloseHandle(hToken);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
inline int getDebugPriv() {
|
||
|
return getPriv("SeDebugPrivilege");
|
||
|
}
|
||
|
|
||
|
int InjectIntoProcess(int pid) {
|
||
|
HANDLE hProcess = OpenProcess(CREATE_THREAD_ACCESS, 0, pid);
|
||
|
if (hProcess == 0) {
|
||
|
getDebugPriv();
|
||
|
hProcess = OpenProcess(CREATE_THREAD_ACCESS, 0, pid);
|
||
|
if (!hProcess) return 0;
|
||
|
}
|
||
|
|
||
|
int out = InjectDll(hProcess);
|
||
|
|
||
|
CloseHandle(hProcess);
|
||
|
return out;
|
||
|
}
|
||
|
*/
|