Inline Hook
@author: dlive
IAT Hook时如果要钩取的API不在IAT中(LoadLibrary后调用),则无法使用该技术。而Inline Hook不存在这个限制。
0x01 Inline Hook原理
原理比较简单,将API代码的前5个字节修改为JMP xxxxxx 指令来钩取API。调用执行被钩取的API时,JMP XXXXXX指令被执行,转而跳转至Hook函数。
0x02 相关API
用户模式下检测进程的相关API通常分为如下两类:
CreateToolhelp32Snapshot() 和 EnumProcess()
这两个API均在其内部调用了ntdll.ZwQuerySystemInformation
ZwQuerySystemInformation()
该API可获得运行中的所有进程信息(结构体),形成一个链表,操作该链表从链表中删除相关进程即可达到隐藏的目的。
0x03 隐藏进程时可能遇到的问题
- 要钩取进程的个数。要想把某个进程隐藏起来,需要钩取系统中运行的所有进程
- 需要对新启动的进程也做同样的钩取操作
以上就是全局钩取的概念
注意:鉴于系统安全性考虑,系统进程禁止进行注入操作
0x04 代码分析
1. HideProc.cpp
InjectAllProcess
向所有进程注入/卸载DLL
BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath)
{
DWORD dwPID = 0;
HANDLE hSnapShot = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe;
// Get the snapshot of the system
pe.dwSize = sizeof( PROCESSENTRY32 );
hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );
// find process
Process32First(hSnapShot, &pe);
do
{
dwPID = pe.th32ProcessID;
//鉴于系统安全性考虑,对于PID小于100的系统进程,不执行DLL诸如操作
if( dwPID < 100 )
continue;
if( nMode == INJECTION_MODE )
InjectDll(dwPID, szDllPath);
else
EjectDll(dwPID, szDllPath);
}
while( Process32Next(hSnapShot, &pe) );
CloseHandle(hSnapShot);
return TRUE;
}
2. stealth.cpp
实际API的钩取由stealth.dll负责
2.1 SetProcName
// global variable (in sharing memory)
#pragma comment(linker, "/SECTION:.SHARE,RWS")
#pragma data_seg(".SHARE")
TCHAR g_szProcName[MAX_PATH] = {0,};
#pragma data_seg()
#pragma data_seg(".SHARE")
一般用于DLL中,在DLL中定义一个共享的,有名字的节区。最关键的是:这个节区中的全局变量可以被多个进程共享。 这里将建立的节区命名为.SHARE
。您可以将这段命名为任何一个您喜欢的名字。在这里的#pragma叙述之后的所有初始化了的变量都放在.SHARE
节区中。
#pragma data_seg()
叙述标示段的结束。对变量进行专门的初始化是很重要的,否则编译器将把它们放在普通的未初始化数据段(.bss)中而不是放在shared中。
连结器必须知道有一个「shared」共享节区: #pragma comment(linker,"/SECTION:shared,RWS")
字母RWS表示节区具有读、写和共享属性。
// ------------------------------ 我是一个题外话 --------------------------------------
//说个题外话,通过共享节区变量可以做到防多开(腾讯游戏安全竞赛的时候曾经用过这个方法)
//DLL加载时count++, 卸载时count--
//demo代码如下,只是demo
#pragma data_seg("flag_data")
int count=0;
#pragma data_seg()
#pragma comment(linker,"/SECTION:flag_data,RWS")
if(count>1)
{
MessageBox("已经启动了一个应用程序","Warning",MB_OK);
return FLASE;
}
count++;
// ------------------------------ 我是一个题外话 --------------------------------------
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void SetProcName(LPCTSTR szProcName)
{
//将steach.dll字符串存放在内存共享节区
_tcscpy_s(g_szProcName, szProcName);
}
#ifdef __cplusplus
}
#endif
2.2 DllMain
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
char szCurProc[MAX_PATH] = {0,};
char *p = NULL;
// #1. 判断进程名称,不向HideProc.exe注入dll
GetModuleFileNameA(NULL, szCurProc, MAX_PATH);
p = strrchr(szCurProc, '\\');
if( (p != NULL) && !_stricmp(p+1, "HideProc.exe") )
return TRUE;
switch( fdwReason )
{
// #2. API Hooking
case DLL_PROCESS_ATTACH :
hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,
(PROC)NewZwQuerySystemInformation, g_pOrgBytes);
break;
// #3. API Unhooking
case DLL_PROCESS_DETACH :
unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,
g_pOrgBytes);
break;
}
return TRUE;
}
2.3 hook_by_code
BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes)
{
FARPROC pfnOrg;
DWORD dwOldProtect, dwAddress;
BYTE pBuf[5] = {0xE9, 0, };
PBYTE pByte;
// 获取要钩取的API地址
pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
pByte = (PBYTE)pfnOrg;
// 若已经被钩取,则返回False
if( pByte[0] == 0xE9 )
return FALSE;
// 修改内存属性
VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
// 备份原有的5字节
memcpy(pOrgBytes, pfnOrg, 5);
// JMP (E9 XXXX)
// => XXXX = pfnNew - pfnOrg - 5
dwAddress = (DWORD)pfnNew - (DWORD)pfnOrg - 5;
memcpy(&pBuf[1], &dwAddress, 4);
// Hook - 5 byte (JMP XXXX)
memcpy(pfnOrg, pBuf, 5);
// 恢复内存属性
VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect);
return TRUE;
}
JMP目的地址的计算,xxxxxxxx为相对地址
长跳转
E9 xxxxxxxx
xxxxxxxx = 要跳转的绝对地址 - 当前指令绝对地址 - 当前指令长度(5)
还有另外的一些跳转指令
短跳转 short jmp
EB xx (指令长度为两字节, xx为相对地址)
跳转到绝对地址
push xxxxxxxx; ret
68 xxxxxxxx c3
跳转到绝对地址
move eax, xxxxxxxx
jmp eax
B8 xxxxxxxx
FFE0
2.4 unhook_by_code
BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)
{
FARPROC pFunc;
DWORD dwOldProtect;
PBYTE pByte;
// 获取API地址
pFunc = GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
pByte = (PBYTE)pFunc;
// 判断API 代码是否被修改过
if( pByte[0] != 0xE9 )
return FALSE;
// 将API开始5Byte内存属性修改为RWX
VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
// Unhook,将原始的5Byte数据修改回来
memcpy(pFunc, pOrgBytes, 5);
// 恢复内存属性
VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
return TRUE;
}
2.5 NewZwQuerySystemInformation
Zw开头的函数和Nt开头的函数的区别:
在RING3下,应用程序调用NT或者ZW效果是一样的, 在dll中执行的是同一段代码。
在RING0下,调用NT函数跟ZW函数就不一样了,ZW开头的函数是通过eax中系统服务号去SSDT中查找相应的系统服务,然后调用之。
若在驱动中直接调用NT开头的函数是不会经过SSDT的 也不会被SSDT HOOK拦截的。
即:在R0下通过调用NT系列函数可以绕过SSDT HOOK 。微软推荐使用Zw开头的函数
ZwQuerySystemInformation微软官方手册(对各个字段解释不完整)
https://msdn.microsoft.com/en-us/library/windows/desktop/ms725506(v=vs.85).aspx
#define STATUS_SUCCESS (0x00000000L)
typedef LONG NTSTATUS;
//将SYSTEM_INFORMATION_CLASS设置为SystemProcessInformation(5)后调用ZwQuerySystemInformation API
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation = 0,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemProcessInformation = 5,
SystemProcessorPerformanceInformation = 8,
SystemInterruptInformation = 23,
SystemExceptionInformation = 33,
SystemRegistryQuotaInformation = 37,
SystemLookasideInformation = 45
} SYSTEM_INFORMATION_CLASS;
//API获得的信息为SYSTEM_PROCESS_INFORMATION结构体组成的单向链表的起始地址,该结构体重存储着运行中所有进程的信息
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset; //链表中下一个结构体相对于当前结构体的偏移量
ULONG NumberOfThreads; //线程数目;
BYTE Reserved1[48];
PVOID Reserved2[3]; //Reserved2[1]为进程名称,进程名称为Unicode字符串
HANDLE UniqueProcessId;
PVOID Reserved3;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)
(SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation, //参数单向链表的起始地址
ULONG SystemInformationLength,
PULONG ReturnLength);
#define DEF_NTDLL ("ntdll.dll")
#define DEF_ZWQUERYSYSTEMINFORMATION ("ZwQuerySystemInformation")
//NTSTATUS 是被定义为32位的无符号长整型。在驱动程序开发中,人们习惯用 NTSTATUS 返回状态。
NTSTATUS WINAPI NewZwQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength)
{
NTSTATUS status;
FARPROC pFunc;
PSYSTEM_PROCESS_INFORMATION pCur, pPrev;
char szProcName[MAX_PATH] = {0,};
// 首先脱钩
unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);
// 调用原始API
pFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL),
DEF_ZWQUERYSYSTEMINFORMATION);
status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)
(SystemInformationClass, SystemInformation,
SystemInformationLength, ReturnLength);
if( status != STATUS_SUCCESS )
goto __NTQUERYSYSTEMINFORMATION_END;
// 判断调用API时是否为要钩取的调用方式(SystemProcessInformation(5))
if( SystemInformationClass == SystemProcessInformation )
{
// pCur 存储单链表的首地址
pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
while(TRUE)
{
// 比较进程名称
// g_szProcName为要隐藏的进程
if(pCur->Reserved2[1] != NULL)
{
if(!_tcsicmp((PWSTR)pCur->Reserved2[1], g_szProcName))
{
// 删除链表节点
if(pCur->NextEntryOffset == 0)
pPrev->NextEntryOffset = 0;
else
pPrev->NextEntryOffset += pCur->NextEntryOffset;
}
else
pPrev = pCur;
}
//遍历结束
if(pCur->NextEntryOffset == 0)
break;
// 相当于p=p->next
pCur = (PSYSTEM_PROCESS_INFORMATION)
((ULONG)pCur + pCur->NextEntryOffset);
}
}
__NTQUERYSYSTEMINFORMATION_END:
// 重新Hook API
hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,
(PROC)NewZwQuerySystemInformation, g_pOrgBytes);
return status;
}
0x05 全局API钩取
全局API钩取技术针对的进程:
- 当前运行的所有进程
- 将来要运行的所有进程
前面的示例程序并不是全局API钩取的例子,因为它并不满足全局API钩取定义中的第二个条件
1.相关API
//Kernel32.CreateProcess
BOOL WINAPI CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
该API用于创建新进程,其他启动运行进程的API(WinExec, ShellExecute, system)在其内部调用的都是该函数
WinExec:
https://msdn.microsoft.com/en-us/library/ms687393(v=vs.85).aspx
可以直接钩取父进程(通常是explorer.exe)的CreateProcess API来监控子进程创建,从而达到钩取子进程的目的。
但是这种方法存在一些问题,且不说需要同时钩取CreateProcessA, CreateProcessW,CreateProcessInternalA, CreateProcessInternalW, 还存在在NewCreateProcess(攻击者自定义的Hook函数)调用CreateProcess创建子进程时,极短时间内,子进程可能在未钩取的状态下运行。
//Ntdll.ZwResumeThread
ZwResumeThread(
IN HANDLE ThreadHandle,
OUT PULONG SuspendCount OPTIONAL
)
该API也是一个未公开API,它是比CreateProcess更低级的API,它在进程创建后,主线程运行前被调用执行。所以只要钩取这个函数即可在不运行子进程代码的情况下钩取API。
但由于其为未公开API,随着OS的升级,API可能失效。
2.代码分析
stealth2.cpp中增加了对CreateProcessA和CreateProcessW的Hook操作,并对新创建的进程进行dll注入d
有NewCreateProcessA为例:
BOOL WINAPI NewCreateProcessA(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
)
{
BOOL bRet;
FARPROC pFunc;
// unhook
unhook_by_code("kernel32.dll", "CreateProcessA", g_pOrgCPA);
pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA");
bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
// 如果新进程创建成果,将stealth.dll注入到新进程中
if( bRet )
InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
// hook
hook_by_code("kernel32.dll", "CreateProcessA",
(PROC)NewCreateProcessA, g_pOrgCPA);
return bRet;
}
0x06 利用热补丁技术钩取API
前面demo程序中通过代码修改技术进行API Hook存在的缺点
- 频繁脱钩,挂钩会造成整体性能下降
- 多线程环境,当一个线程尝试运行某段代码,而另一进程刚好在对该代码进行写操作,这时就会发生冲突,会引起非法访问异常(Access Violation)。《windows核心编程》指出,利用代码修改技术钩取API会对系统安全造成威胁
1.热补丁(修改7Byte代码)
Windows系统库中的函数,如kernel32.CreateProcessA/W, user32.MessageBoxA,gdi32.TextOutW有一个相似点
- API以
MOV EDI, EDI
指令开始(IA-320X8bff
) - API上方有5个
NOP
指令(IA-320X90
)
微软做此设计的目的就是方便打热补丁。
使用热补丁Hook API的过程如下
- 修改API开始的两个字节
MOV EDI,EDI
为SHORT JMP指令EB F9
, 跳转的目标地址是address_of_api - 5,即5个NOP指令的第一条 - 修改5个NOP指令为长跳转
E9 XXXXXXXX
,跳转到用户自定义API - 用户自定义代码调用原始API时,直接以API+2的地址为API地址调用原API,这样就不会引起内存非法访问
2.代码分析
2.1 DllMain
和之前代码一样,在Dll附加进程的时候调用hook方法,在dll卸载时调用unhook方法
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
char szCurProc[MAX_PATH] = {0,};
char *p = NULL;
// 判断进程名称,不向HideProc2.exe注入dll
GetModuleFileNameA(NULL, szCurProc, MAX_PATH);
p = strrchr(szCurProc, '\\');
if( (p != NULL) && !_stricmp(p+1, "HideProc2.exe") )
return TRUE;
// change privilege
SetPrivilege(SE_DEBUG_NAME, TRUE);
switch( fdwReason )
{
case DLL_PROCESS_ATTACH :
// hook
hook_by_hotpatch("kernel32.dll", "CreateProcessA",
(PROC)NewCreateProcessA);
hook_by_hotpatch("kernel32.dll", "CreateProcessW",
(PROC)NewCreateProcessW);
//可以看到这里没有对ZwQuerySystemInformation使用热补丁Hook,具体原因见"3.热补丁Hook的缺点"
hook_by_code("ntdll.dll", "ZwQuerySystemInformation",
(PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);
break;
case DLL_PROCESS_DETACH :
// unhook
unhook_by_hotpatch("kernel32.dll", "CreateProcessA");
unhook_by_hotpatch("kernel32.dll", "CreateProcessW");
unhook_by_code("ntdll.dll", "ZwQuerySystemInformation",
g_pOrgZwQSI);
break;
}
return TRUE;
}
2.2 hook_by_hotpatch
修改API中无用的7字节数据,跳转到用户自定义Hook函数
BOOL hook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew)
{
FARPROC pFunc;
DWORD dwOldProtect, dwAddress;
BYTE pBuf[5] = { 0xE9, 0, };
BYTE pBuf2[2] = { 0xEB, 0xF9 };
PBYTE pByte;
pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
pByte = (PBYTE)pFunc;
if( pByte[0] == 0xEB )
return FALSE;
VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);
// 1. NOP (0x90)
dwAddress = (DWORD)pfnNew - (DWORD)pFunc;
memcpy(&pBuf[1], &dwAddress, 4);
memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);
// 2. MOV EDI, EDI (0x8BFF)
memcpy(pFunc, pBuf2, 2);
VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, dwOldProtect, &dwOldProtect);
return TRUE;
}
2.3 unhook_by_hotpatch
将7字节数据修改为原数据
BOOL unhook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName)
{
FARPROC pFunc;
DWORD dwOldProtect;
PBYTE pByte;
BYTE pBuf[5] = { 0x90, 0x90, 0x90, 0x90, 0x90 };
BYTE pBuf2[2] = { 0x8B, 0xFF };
pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
pByte = (PBYTE)pFunc;
if( pByte[0] != 0xEB )
return FALSE;
VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
// 1. NOP (0x90)
memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);
// 2. MOV EDI, EDI (0x8BFF)
memcpy(pFunc, pBuf2, 2);
VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
return TRUE;
}
2.4 NewCreateProcess
这里需要注意一点,在使用之前的hook方法进行API钩取时,在用户自定义NewCreateProcess函数开头需要调用unhook方法(防止进入钩取的死循环),函数结尾需要调用hook方法进行重新钩取。
但是使用热补丁Hook时不需要这样反复脱钩,挂钩,只需在调用原始API时,使用address of API + 2的地址调用API即可
BOOL WINAPI NewCreateProcessA(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
)
{
BOOL bRet;
FARPROC pFunc;
pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA");
//以API地址+2为函数地址调用CreateProcessA函数
pFunc = (FARPROC)((DWORD)pFunc + 2);
bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
// 注入steach3.dll
if( bRet )
InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
return bRet;
}
3.使用热补丁进行Hook的缺点
热补丁钩取技术有个明显的缺点,即不符合钩取条件(7字节无用代码)的API无法使用热补丁钩取
这样的API有,ntdll.dll提供的API 和kernel32.GetStartInfoA() 等
并非所有API都能使用热补丁钩取,所以使用前需要先确认要钩取的API是否支持,若不支持则需使用前面的5字节代码修改技术
0x07 Ntdll.dll API钩取技巧
Ntdll.dll中提供的API代码都较短,钩取这些API时有一种非常好的方法,使用这种方法时先将原API备份到用户内存区域,然后使用5字节代码修改技术修改原API的起始部分。在用户钩取函数内部调用API时,只需调用备份的API即可,这样实现的API钩取既简单又稳定。由于Ntdll.all API代码较短,且代码内部地址无依赖性,所以它们非常适合用该技术钩取。
0x08 一些问题
Dll在内存中只会加载一次,那么在Hook时对Dll进行修改后岂不是会影响所有使用该dll的进程?
主要是Copy-On-Write机制,a.dll在内存中只有一份拷贝,增加的是dll的引用计数,当dll的引用计数为0时,系统会回收对应内存和删除对应的映射。
如果有一个程序对dll的内存进行了相应的修改,比如说修改内存加载钩子,那么系统会将对应页面复制一份出来给程序,此时,两个程序指向的dll的对应内存就不同了。使用HideProc注入时注入失败
Windows 7/Vista中使用了会话隔离技术,可能导致Dll注入失败。出现这个问题时,不要使用kernel32.CreateRemoteThread而使用ntdll.NtCreateThreadEx就可以了。
此外,尝试向PE32+格式的进程注入PE32格式的DLL时也会失败(反之亦然)。注入时必须保证注入的DLL文件和目标进程PE格式一致。
Inline Hook的更多相关文章
- 对付ring0 inline hook
对付ring0 inline hook的基本思路是这样的,自己写一个替换的内核函数,以NtOpenProcess为例,就是MyNtOpenProcess.然后修改SSDT表,让系统服务进入自己的函数M ...
- Inline Hook NtQueryDirectoryFile
Inline Hook NtQueryDirectoryFile 首先声明这个是菜鸟—我的学习日记,不是什么高深文章,高手们慎看. 都总是发一些已经过时的文章真不好意思,几个月以来沉迷于游戏也是时候反 ...
- android inline hook
最近终于沉下心来对着书把hook跟注入方面的代码敲了一遍,打算写几个博客把它们记录下来. 第一次介绍一下我感觉难度最大的inline hook,实现代码参考了腾讯GAD的游戏安全入门. inline ...
- 在已有软件加壳保护 下实现 Inline hook
如写的不好请见谅,本人水平有限. 个人简历及水平:. http://www.cnblogs.com/hackdragon/p/3662599.html 正常情况: 接到一个项目实现对屏幕输出内容的获取 ...
- windows 32位以及64位的inline hook
Tips : 这篇文章的主题是x86及x64 windows系统下的inline hook实现部分. 32位inline hook 对于系统API的hook,windows 系统为了达成hotpatc ...
- INLINE HOOK过简单驱动保护的理论知识和大概思路
这里的简单驱动保护就是简单的HOOK掉内核API的现象 找到被HOOK的函数的当前地址在此地址处先修改页面保护属性然后写入5个字节.5个字节就是一个简单的JMP指令.这里说一下JMP指令,如下: 00 ...
- x86平台inline hook原理和实现
概念 inline hook是一种通过修改机器码的方式来实现hook的技术. 原理 对于正常执行的程序,它的函数调用流程大概是这样的: 0x1000地址的call指令执行后跳转到0x3000地址处执行 ...
- Android Hook框架adbi的分析(2)--- inline Hook的实现
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/74452308 一. Android Hook框架adbi源码中inline Hoo ...
- Android Hook框架adbi的分析(3)---编译和inline Hook实践
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/75200800 一.序言 在前面的博客中,已经分析过了Android Hook框架a ...
随机推荐
- Android Studio卡在refreshing gradle project的原因和快速解决办法
Android Studio更新后一直Refreshing的解决办法! 这个问题遇到过很多次,网上也有很多解决办法,但是好像都没有发现refreshing gradle project在做什么. 一般 ...
- CentOS 7.X 搭建时间服务器 --- chrony
之前centos6我们一直用的ntp时间服务器,虽然到CentOS7上也可以装ntp.但是各种坑啊.这次换一个时间同步工具---->chrony ======================== ...
- Webdriver--获得验证信息
title:获得当前页面的标题 current_url:获得当前页面的URL text:前面提到过,获得标签对的文本信息 try: couseTitle = driver.find_element_b ...
- python 学习分享-实战篇高级的ftp
#server代码 import socketserver,os,hashlib Base_paht = os.path.dirname(os.path.dirname(os.path.abspath ...
- LightGBM的并行优化--机器学习-周振洋
LightGBM的并行优化 上一篇文章介绍了LightGBM算法的特点,总结起来LightGBM采用Histogram算法进行特征选择以及采用Leaf-wise的决策树生长策略,使其在一批以树模型为基 ...
- Java UDP的简单实例以及知识点简述
UDP的实现 Java中实现UDP协议的两个类,分别是DatagramPacket数据包类以及DatagramSocket套接字类. 其与TCP协议实现不同的是: UDP的套接字DatagramSoc ...
- java语言基础第二讲 课程作业02 总结
一.编程的好习惯 1.注释习惯.单行注释://, 多行注释:/* */ . 2.程序中添加适当的空白:4个空格. 3.文件名必须与公有类名一致,即public class 类名. 4.java中 ...
- Linq学习(一)
与LINQ有关的语言特性 1.隐式类型 var 2.匿名类型 如:var obj = new {Guid.Empty, myTitle = "匿名类型", myOtherParam ...
- 史林枫:开源HtmlAgilityPack公共小类库封装 - 网页采集(爬虫)辅助解析利器【附源码+可视化工具推荐】
做开发的,可能都做过信息采集相关的程序,史林枫也经常做一些数据采集或某些网站的业务办理自动化操作软件. 获取目标网页的信息很简单,使用网络编程,利用HttpWebResponse.HttpWebReq ...
- HDU 1532 基础EK Drainage Ditches
Drainage Ditches Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...