本文为看雪论优秀文章
看雪论坛作者ID:一半人生
HRSRC hrsrc = FindResource(NULL, L"LOWLEVEL", RT_RCDATA);
if (! hrsrc)
return false;
ULONG binsize = SizeofResource(NULL, hrsrc);
if (! binsize)
return false;
HGLOBAL hglob = LoadResource(NULL, hrsrc);
..................
section = IMAGE_FIRST_SECTION(nt_hdrs);
..................
m_LdrInitializeThunk = (ULONG_PTR) GetProcAddress(_Ntdll, "LdrInitializeThunk");
if (! m_LdrInitializeThunk)
return false;
x64 add
#ifdef _WIN64
if (Dll_Windows >= 10) {
unsigned char * code;
code = (unsigned char *)m_LdrInitializeThunk;
if (*(ULONG *)&code[0] == 0x24048b48 && code[0xa] == 0x48) {
m_LdrInitializeThunk += 0xa;
}
}
DriverAssist::InjectLow_InitSyscalls()负责初始化sys_data
void DriverAssist::InjectLow(void *_msg)是SvcInjectEntry入口点,填充lowdata结构体,Lowdata结构体包括下述
SBIELOW_DATA lowdata;
memzero(&lowdata, sizeof(lowdata));
lowdata.ntdll_base = (ULONG64)(ULONG_PTR)_Ntdll;
lowdata.is_wow64 = msg->is_wow64;
lowdata.bHostInject = msg->bHostInject;
lowdata.RealNtDeviceIoControlFile = (ULONG64) GetProcAddress((HMODULE) lowdata.ntdll_base,"NtDeviceIoControlFile");
void *remote_addr = InjectLow_CopyCode(hProcess, lowdata.is_wow64, lowdata.LdrInitializeThunk_tramp, sizeof(lowdata.LdrInitializeThunk_tramp));
if (!remote_addr) {
errlvl = 0x33;
goto finish;
}
lowdata.long_diff = TRUE;
if (Has32BitJumpHorizon((void *)m_LdrInitializeThunk, remote_addr)) {
lowdata.long_diff = FALSE;
}
#else
lowdata.long_diff = FALSE;
#endif
1.InjectLow_SendHandle将SbieDrv句柄拷贝到目标进程
lowdata.api_device_handle = (ULONG64)(ULONG_PTR)
InjectLow_SendHandle(hProcess);
if (! lowdata.api_device_handle) {
errlvl = 0x22;
goto finish;
}
lowdata.api_sbiedrv_ctlcode = API_SBIEDRV_CTLCODE;
lowdata.api_invoke_syscall = API_INVOKE_SYSCALL;
memcpy(lowdata.NtDelayExecution_code, &m_syscall_data[2], (32 * 4));
#ifdef _WIN64
lowdata.Sbie64bitJumpTable = (SBIELOW_J_TABLE *) ((ULONG_PTR) remote_addr +m_sbielow_len+0x400); //(0x400 - (m_sbielow_len & 0x3ff))+ m_sbielow_len;
#endif
ULONG_PTR tramp_remote_addr = // calculate address in remote process
(ULONG_PTR)remote_addr
+ m_sbielow_data_offset // offset of args area
+ FIELD_OFFSET(SBIELOW_DATA, LdrInitializeThunk_tramp);
targets = (MY_TARGETS *)& bindata[section[1].PointerToRawData];
m_sbielow_start_offset = (ULONG)targets->entry - section[0].VirtualAddress;
m_sbielow_data_offset = (ULONG)targets->data - section[0].VirtualAddress;
if (! InjectLow_BuildTramp(_msg, lowdata.long_diff,
lowdata.LdrInitializeThunk_tramp, tramp_remote_addr)) {
errlvl = 0x44;
goto finish;
}
//
// copy the syscall data buffer (m_syscall_data) to target process
void *remote_syscall_data = InjectLow_CopySyscalls(hProcess);
if (! remote_syscall_data) {
errlvl = 0x55;
goto finish;
}
lowdata.syscall_data = (ULONG64)(ULONG_PTR)remote_syscall_data;
if (! InjectLow_CopyData(hProcess, remote_addr, &lowdata)) {
errlvl = 0x66;
goto finish;
}
if (!InjectLow_WriteJump(hProcess, (UCHAR *)remote_addr + m_sbielow_start_offset, lowdata.long_diff, &lowdata)) {
errlvl = 0x77;
goto finish;
}
//
// put process into a job for win32 restrictions
//
2.
if (!msg->bHostInject)
{
if(! GuiServer::GetInstance()->InitProcess(
hProcess, msg->process_id, msg->session_id,
msg->add_to_job)) {
errlvl = 0x88;
goto finish;
}
}
//
// notify driver that we successfully injected the lowlevel code
//
if (SbieApi_CallOne(API_INJECT_COMPLETE, msg->process_id) == 0)
#define ANTSDLL_HOOK(pfx,proc) \
*(ULONG_PTR *)&__sys_##proc = (ULONG_PTR) \
ANTSDLL_Hook(#proc, proc, pfx##proc); \
if (! __sys_##proc) return FALSE;
#define GETPROCADDR_DEF(name) \ 获取函数地址
P_##name name = (P_##name) GetProcAddress(module, #name)
_FX void *ANTSDLL_Hook(
const char *SourceFuncName, void *SourceFunc, void *DetourFunc
用法:
GETPROCADDR_DEF(CoGetClassObject);
ANTSDLL_HOOK(Com_, CoGetClassObject);
_FX void *ANTSDLL_Hook(
const char *SourceFuncName, void *SourceFunc, void *DetourFunc
)
{
UCHAR *tramp, *func;
ULONG_PTR diff;
ULONG_PTR target;
ULONG prot, dummy_prot;
void *orig_addr;
#ifdef _WIN64
long long delta;
BOOLEAN CallInstruction64 = FALSE;
#endif _WIN64
// validate parameter - 验证参数
if (!SourceFunc) {
return NULL;
}
// jmp xx 共两个字节
if (*(UCHAR *)SourceFunc == 0xEB) {
signed char offset = *((signed char *)SourceFunc + 1);
SourceFunc = (UCHAR *)SourceFunc + offset + 2;
}
// jmp xx xx xx xx 后面 jmp current + diff + 5
while (*(UCHAR *)SourceFunc == 0xE9) {
diff = *(LONG *)((ULONG_PTR)SourceFunc + 1);
target = (ULONG_PTR)SourceFunc + diff + 5;
if (target == (ULONG_PTR)DetourFunc) {
return NULL;
}
#ifdef _WIN64
SourceFunc = (void *)target;
#else ! WIN_64
func = SbieDll_Hook_CheckChromeHook((void *)target);
if (func != (void *)target) {
SourceFunc = func;
goto skip_e9_rewrite;
}
func = (UCHAR *)SourceFunc;
diff = (UCHAR *)DetourFunc - (func + 5);
++func;
if (!VirtualProtect(func, 4, PAGE_EXECUTE_READWRITE, &prot)) {
ULONG err = GetLastError();
return NULL;
}
*(ULONG *)func = (ULONG)diff;
VirtualProtect(func, 4, prot, &dummy_prot);
return (void *)target;
skip_e9_rewrite:;
#endif _WIN64
}
#ifdef _WIN64
// avast.snxhk64.dll compatibility nop+jmp (90,E9)
if (*(USHORT *)SourceFunc == 0xE990) {
diff = *(LONG *)((ULONG_PTR)SourceFunc + 2);
target = (ULONG_PTR)SourceFunc + diff + 6;
if (*(USHORT *)target == 0x25FF)
SourceFunc = (void *)target;
}
// 如果 [x] 只替换地址
// 0xff25 四个字节地址
if(*(USHORT *)SourceFunc == 0x48 &&
*(USHORT *)((UCHAR *)SourceFunc) == 0x25FF) {
// 4825ff and 25ff 一样 所以和ff25一起处理
SourceFunc = (UCHAR *)SourceFunc + 1;
}
if (*(USHORT *)SourceFunc == 0x25FF) {
orig_addr = NULL;
// 首先取地址 +2是0xff25
diff = *(LONG *)((ULONG_PTR)SourceFunc + 2);
// jmp qword ptr + 地址 jmp到目标地址判断是否等于我们的挂钩函数
target = (ULONG_PTR)SourceFunc + 6 + diff;
orig_addr = (void *)*(ULONG_PTR *)target;
if (orig_addr == DetourFunc) {
return NULL;
}
func = (UCHAR *)target;
if (!VirtualProtect(func, 8, PAGE_EXECUTE_READWRITE, &prot)) {
ULONG err = GetLastError();
return NULL;
}
// 进行挂钩HOOK
*(ULONG_PTR *)target = (ULONG_PTR)DetourFunc;
VirtualProtect(func, 8, prot, &dummy_prot);
return orig_addr;
}
#endif _WIN64
#ifdef _WIN64
// call qword ptr [0xaddress]
if (*(USHORT *)SourceFunc == 0x15FF) {
//
// the call instruction pushes a qword into the stack, we need
// to remove this qword before calling our detour function
//
UCHAR *NewDetour = (UCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 128);
NewDetour[0] = 0x58; // pop rax
NewDetour[1] = 0x48; // mov rax, DetourFunc
NewDetour[2] = 0xB8;
*(ULONG_PTR *)(&NewDetour[3]) = (ULONG_PTR)DetourFunc;
NewDetour[11] = 0xFF; // jmp rax
NewDetour[12] = 0xE0;
DetourFunc = NewDetour;
//
// when our detour function calls the trampoline to invoke the
// original code, we have to push the qword back into the stack,
// because this is what the original code expects
//
NewDetour[16] = 0x48; // mov rax, SourceFunc+6
NewDetour[17] = 0xB8;
*(ULONG_PTR *)(&NewDetour[18]) = (ULONG_PTR)SourceFunc + 6;
NewDetour[26] = 0x50; // push rax
NewDetour[27] = 0x48; // mov rax, trampoline code
NewDetour[28] = 0xB8;
*(ULONG_PTR *)(&NewDetour[29]) = 0;
NewDetour[37] = 0xFF; // jmp rax
NewDetour[38] = 0xE0;
CallInstruction64 = TRUE;
//
// overwrite the code at the target of the call instruction
//
diff = *(LONG *)((ULONG_PTR)SourceFunc + 2);
target = (ULONG_PTR)SourceFunc + 6 + diff;
SourceFunc = (void *)*(ULONG_PTR *)target;
// if is 0xff15, SourceFunc = jmp [current + offset + 6]
}
#endif _WIN64
/*
1. 0xFF25 jmp qword ptr xx xx xx xx R3进行inlinehook直接返回
2. EB/E9/FF15/驱动挂钩处理
3. 貌似没对E8做处理?
*/
// 调用驱动创建tramp
__declspec(align(8)) ULONG64 parms[8];
//tramp = (UCHAR*)VirtualAlloc(NULL, 128, MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
tramp = (UCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 128);
//memset(tramp, 0, 128);
parms[0] = 0;
parms[1] = (ULONG64)(ULONG_PTR)SourceFunc;
parms[2] = (ULONG64)(ULONG_PTR)tramp;
Hook_Api_Tramp(parms);
// NtDeviceIoControlFile --> API_HOOK_TRAMP --> \\Device\\SandboxieDriverApi 处理tramp
//
// drv.ApiInit() --> 初始化API_DEVICE_NAME端口 Api_SetFunction(API_HOOK_TRAMP, Hook_Api_Tramp);
//
// Hook_Api_Tramp() --> Hook_BuildTramp() 进行HOOK挂钩
//
// 先利用原dll导出函数
// if (SbieApi_HookTramp(SourceFunc, tramp) != 0) {
// return NULL;
//}
func = (UCHAR *)SourceFunc;
if (!VirtualProtect(&func[-8], 20, PAGE_EXECUTE_READWRITE, &prot)) {
ULONG err = GetLastError();
return NULL;
}
g_TrapFrameOffset = 0x90 and g_TrapFrameOffset = 0x1d8
struct PAGE {
LIST_ELEM list_elem;
PAGE *next;
POOL *pool;
ULONG eyecatcher;
USHORT num_free; // estimated, not accurate
};
Driver_PublicAcl = Mem_AllocEx(Driver_Pool, 128, TRUE);
if (! Driver_PublicAcl)
return FALSE;
RtlCreateAcl(Driver_PublicAcl, 128, ACL_REVISION);
static UCHAR AuthSid[12] = {
1, // Revision
1, // SubAuthorityCount
0,0,0,0,0,5, // SECURITY_NT_AUTHORITY // IdentifierAuthority
SECURITY_AUTHENTICATED_USER_RID // SubAuthority
};
static UCHAR WorldSid[12] = {
1, // Revision
1, // SubAuthorityCount
0,0,0,0,0,1, // SECURITY_WORLD_SID_AUTHORITY // IdentifierAuthority
SECURITY_WORLD_RID // SubAuthority
};
if (ok) {
Driver_RegistryPath =
Mem_AllocStringEx(Driver_Pool, RegistryPath->Buffer, TRUE);
if (! Driver_RegistryPath)
ok = FALSE;
}
Api_SetFunction(API_SET_USER_NAME, Conf_Api_SetUserName);
Api_SetFunction(API_IS_BOX_ENABLED, Conf_Api_IsBoxEnabled);
if (proc || (PsGetCurrentProcessId() != Api_ServiceProcessId)) {
return STATUS_ACCESS_DENIED;
}
DriverCode:API_IS_BOX_ENABLED
Conf_Read()
DLL_Init()
List_Init(&Dll_List);
Dll_List_Initialized = TRUE;
if (! Dll_Load(Dll_NTDLL))
return FALSE;
if (! Dll_Load(Dll_USER))
return FALSE;
return TRUE;
static LIST Syscall_List;
static SYSCALL_ENTRY **Syscall_Table = NULL;
static ULONG Syscall_MaxIndex = 0;
static UCHAR *Syscall_NtdllSavedCode = NULL;
static SYSCALL_ENTRY *Syscall_SetInformationThread = NULL;
ULONG *names = Dll_RvaToAddr(dll, dll->exports->AddressOfNames);
ULONG *addrs = Dll_RvaToAddr(dll, dll->exports->AddressOfFunctions);
USHORT *ordis = Dll_RvaToAddr(dll, dll->exports->AddressOfNameOrdinals);
if (syscall_index != -1) {
Syscall_GetKernelAddr(
syscall_index, &ntos_addr, ¶m_count);
}
Api_SetFunction(API_SESSION_LEADER, Session_Api_Leader);
Api_SetFunction(API_DISABLE_FORCE_PROCESS, Session_Api_DisableForce);
Api_SetFunction(API_MONITOR_CONTROL, Session_Api_MonitorControl);
Api_SetFunction(API_MONITOR_PUT, Session_Api_MonitorPut);
Api_SetFunction(API_MONITOR_PUT2, Session_Api_MonitorPut2);
Api_SetFunction(API_MONITOR_GET, Session_Api_MonitorGet);
if (!proc->bHostInject) {
if (ok)
ok = File_CreateBoxPath(proc);
if (ok)
ok = Ipc_CreateBoxPath(proc);
if (ok)
ok = Key_MountHive(proc);
//
// initialize the filtering components
//
if (ok)
ok = File_InitProcess(proc);
if (ok)
ok = Key_InitProcess(proc);
if (ok)
ok = Ipc_InitProcess(proc);
if (ok)
ok = Gui_InitProcess(proc);
if (ok)
ok = Process_Low_InitConsole(proc);
if (ok)
ok = Token_ReplacePrimary(proc);
if (ok)
ok = Thread_InitProcess(proc);
}
RtlInitUnicodeString(&objname, proc->box->file_path);
status = ZwCreateFile(
&handle,
FILE_GENERIC_READ | FILE_WRITE_ATTRIBUTES,
&objattrs,
&IoStatusBlock,
NULL, // AllocationSize
0, // FileAttributes
FILE_SHARE_VALID_FLAGS, // ShareAccess
FILE_OPEN_IF, // CreateDisposition
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0); // EaBuffer, EaLength
Ipc_CreateBoxPath(proc)
while (retries < 64) {
++retries;
RtlInitUnicodeString(&objname, proc->box->ipc_path);
status = ZwCreateDirectoryObject(
&handle, DIRECTORY_ALL_ACCESS, &objattrs);
if (status == STATUS_OBJECT_PATH_NOT_FOUND) {
Key_Init()
initialize the filtering components初始化过滤接口
File_InitProcess()
10) Thread_Init
11) File_Init
12) Key_Init
13) Ipc_Init
14) Gui_Init
15) Api_Init
16) Dll_Unload
看雪ID:一半人生
https://bbs.pediy.com/user-home-819685.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!