第43章:内核6中的DLL注入
由于从 Win 7 开始引入了会话机制,因此使得之前通过 CreateRemoteThread() API 注入的旧方法对某些进程(服务进程)不再适用.
注入非0级的会话层能够成功,而对于0级会话的进程,例如 svchost.exe 会注入失败.
探索一下原因:
在 OD 中打开程序,并输入参数( X64dbg 没有找到能输入参数的地方 ).
可以看到 函数里面调用了 Ex 后缀的函数,跟进后:
里面存在了很多代码.根据书中提示, Ex 后缀的函数,比原来多了一个参数. 但是记住一点, CreateRemoteThread() API 的参数是没有改变的.
多的这一个参数是 lpAttributeList , If lpThreadAttributes is NULL, the thread gets a default security descriptor and the handle cannot be inherited.
看到这里,其实可以发现,这里不是影响其注入的原因.继续向下找:
此处的参数变多, 而且名字中也有创建线程之意, 并且根据书中作者的测试, 如果直接调用 CreateThreadEx() 是可以成功的.
可以推测, 这11个参数中的某些参数, 用了前面的代码计算出的值, 而这些参数引起线程不能成功创建.
从书中得知,真正的不同在 CreateSuspended 值, 使用 CreateThreadEx 成功创建的话该值为1, 而使用 CreateRemoteThread 时该值为0.
并且,书中提到,实际上, CreateThreadEx() 正常工作并且成功创建了线程,但是在后面的API 中,通过判断,没有启动该线程:
自己在做实验时,并没有出现如作者所示的提示, 可能是用的 OD 的版本不一样导致的.
BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf) { HANDLE hThread = NULL; FARPROC pFunc = NULL; if( IsVistaOrLater() ) // Vista, 7, Server2008 { pFunc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateThreadEx"); if( pFunc == NULL ) { printf("MyCreateRemoteThread() : GetProcAddress(\"NtCreateThreadEx\") failed!!! [%d]\n", GetLastError()); return FALSE; } ((PFNTCREATETHREADEX)pFunc)(&hThread, // 调用 CreateRemoteThread 的内部函数,直接注入,不再需要恢复运行 0x1FFFFF, // 因为此处 CreateSuspended 为 NULL NULL, hProcess, pThreadProc, pRemoteBuf, FALSE, NULL, NULL, NULL, NULL); if( hThread == NULL ) { printf("MyCreateRemoteThread() : NtCreateThreadEx() failed!!! [%d]\n", GetLastError()); return FALSE; } } else // 2000, XP, Server2003 { hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); if( hThread == NULL ) { printf("MyCreateRemoteThread() : CreateRemoteThread() failed!!! [%d]\n", GetLastError()); return FALSE; } } if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) ) { printf("MyCreateRemoteThread() : WaitForSingleObject() failed!!! [%d]\n", GetLastError()); return FALSE; } return TRUE; }