pslib/ps_inject.cpp
2021-12-04 05:23:44 +02:00

144 lines
No EOL
4.2 KiB
C++

#include "ps_inject.h"
#include "ps_image.h"
int ps_inject(process_t* ps, pe_t* thisMod, LPCSTR lpCodeSec, LPCSTR lpDataSec,
LPVOID lpEntryPoint, ps_inject_t* inject)
{
PIMAGE_SECTION_HEADER pCodeHdr = ps_get_section_header(thisMod, lpCodeSec);
PIMAGE_SECTION_HEADER pDataHdr = ps_get_section_header(thisMod, lpDataSec);
if (!pCodeHdr || !pDataHdr) return PS_NO_SECTIONS;
inject->dwCodeSize = ps_section_size(pCodeHdr);
inject->dwDataSize = ps_section_size(pDataHdr);
inject->dwSize = inject->dwCodeSize + inject->dwDataSize + ps_page_size; //+1 page for PS_IMAGE_RDATA
inject->Base = (ULONG_PTR)VirtualAllocEx(ps->hProcess, NULL, inject->dwSize, MEM_RESERVE, PAGE_READWRITE);
ps_image_t* image = ps_image_create(thisMod, inject->Base, lpCodeSec, lpDataSec);
if (!image)
{
VirtualFreeEx(ps->hProcess, (LPVOID)inject->Base, inject->dwSize, MEM_RELEASE);
return PS_CREATE_IMAGE_FAILED;
}
ps_import_lib_t* lib = image->import;
while (lib)
{
ps_import_thunk_t* thunk = lib->thunk;
pe_t* pLib = ps_get_module(ps, lib->szLibName);
if (!pLib) continue;
pe_export_t* exp = export_load(ps, pLib);
if (!exp) continue;
while (thunk)
{
((PULONG_PTR)image->RSec[PS_IMAGE_SECTION_RDATA].pData)[thunk->dwIndex]
= export_find_function(exp, thunk->szFuncName);
thunk = thunk->next;
}
export_unload(exp);
lib = lib->next;
}
for (DWORD i = 0; i < PS_IMAGE_SECTIONS; i++)
{
DWORD dwOldProtect;
ULONG_PTR Addr = image->VirtualBase + image->VSec[i].dwRVA;
VirtualAllocEx(ps->hProcess, (LPVOID)Addr, image->VSec[i].dwSize, MEM_COMMIT, PAGE_READWRITE);
ps_write(ps, Addr, image->RSec[i].pData, image->RSec[i].dwRealSize);
VirtualProtectEx(ps->hProcess, (LPVOID)Addr,
image->VSec[i].dwSize, image->VSec[i].dwFlags, &dwOldProtect);
}
inject->dwSize = image->dwVirtualSize;
inject->CodeVA = image->VirtualBase + image->VSec[PS_IMAGE_SECTION_CODE].dwRVA;
inject->DataVA = image->VirtualBase + image->VSec[PS_IMAGE_SECTION_DATA].dwRVA;
inject->EntryPointVA = inject->CodeVA + ((ULONG_PTR)lpEntryPoint
- (thisMod->BaseAddress + pCodeHdr->VirtualAddress));
ps_image_free(image);
return PS_INJECT_OK;
}
BOOL ps_adjust_privilege(LPCSTR lpPrivilegeName)
{
HANDLE hToken;
LUID luidPrivilege;
TOKEN_PRIVILEGES privileges;
if (!LookupPrivilegeValue(NULL, lpPrivilegeName, &luidPrivilege))
return FALSE;
if (!OpenProcessToken(ps_this_process->hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
return FALSE;
privileges.PrivilegeCount = 1;
privileges.Privileges[0].Luid = luidPrivilege;
privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &privileges, sizeof(privileges), NULL, NULL);
CloseHandle(hToken);
return TRUE;
}
static BYTE _ps_hijack_boot[16];
#define OP_PUSHFD 0x9C
#define OP_PUSHAD 0x60
#define OP_POPAD 0x61
#define OP_POPFD 0x9D
#define OP_CALL 0xE8
#define OP_JMP 0xE9
#define JMP_OFFSET(from,to) ((to) - (from) - 5)
BOOL ps_hijack_thread(process_t* ps, DWORD dwTid, ULONG_PTR Code)
{
CONTEXT Ctx;
DWORD dwOldProtect;
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION
| THREAD_SUSPEND_RESUME
| THREAD_GET_CONTEXT
| THREAD_SET_CONTEXT,
FALSE, dwTid);
if (hThread == INVALID_HANDLE_VALUE)
return FALSE;
ZeroMemory(&Ctx, sizeof(CONTEXT));
Ctx.ContextFlags = CONTEXT_CONTROL;
SuspendThread(hThread);
GetThreadContext(hThread, &Ctx);
ULONG_PTR BootCode = (ULONG_PTR)VirtualAllocEx(ps->hProcess, NULL,
4096, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ULONG_PTR PrevAddr = Ctx.Eip;
//Build shell code
_ps_hijack_boot[0] = OP_PUSHFD;
_ps_hijack_boot[1] = OP_PUSHAD;
_ps_hijack_boot[2] = OP_CALL;
*(PLONG_PTR)&_ps_hijack_boot[3] = JMP_OFFSET((LONG_PTR)BootCode + 2, (LONG_PTR)Code);
_ps_hijack_boot[7] = OP_POPAD;
_ps_hijack_boot[8] = OP_POPFD;
_ps_hijack_boot[9] = OP_JMP;
*(PLONG_PTR)&_ps_hijack_boot[10] = JMP_OFFSET((LONG_PTR)BootCode + 2, (LONG_PTR)PrevAddr);
//Write
ps_write(ps, BootCode, _ps_hijack_boot, sizeof(_ps_hijack_boot));
VirtualProtect((LPVOID)BootCode, sizeof(_ps_hijack_boot), PAGE_EXECUTE_READWRITE, &dwOldProtect);
//Execute
Ctx.Eip = BootCode;
SetThreadContext(hThread, &Ctx);
ResumeThread(hThread);
CloseHandle(hThread);
return TRUE;
}