内存免杀--

通过分析Ekko项目了解内存加密过程,这对对抗内存扫描来说很重要。

概述

Edr会扫描程序的内存空间,检测是否存在恶意软件,这种检测恶意软件的方式,应该和静态检测没什么区别,只不过一个扫描的对象是硬盘,一个是内存,应该都是基于特征码来检测的,为了绕过这种扫描我们可以对内存中的beacon进行加密,但这样的话就会出现问题,因为beacon被加密后是无法正常的运行的,因为代码被加密了。
#
我们提到过自己是不可以加密自己的,但是Ekko项目实现了自己加密自己的内存,这对对抗内存扫描很有帮助。

API理解

CreateEvent()创建或打开一个事件对象

SetEvent()设置对象状态已通知状态

CreateTimerQueue()创建计时器队列

CreateTimerQueueTimer()创建计时器队列计时器


BOOL CreateTimerQueueTimer([out]          PHANDLE             phNewTimer,[in, optional] HANDLE              TimerQueue,[in]           WAITORTIMERCALLBACK Callback,[in, optional] PVOID               Parameter,[in]           DWORD               DueTime,[in]           DWORD               Period,[in]           ULONG               Flags
);

phNewTimer接受计时器队列计时器的缓冲区

TimeQueue计时器队列句柄

CallBack回调函数,计时器过期时要执行的函数

Parameter回调函数的参数

DueTime过多长时间向计时器发信号

Period计时器的周期,如果为0就向计时器发信号

Flag标志,指定函数调用相关内容。

对于CreateTimerQueueTimer函数可以这样理解,它可以定时执行一个函数,应该是异步执行的。

WaitForSingleObject()等待某个对象的状态,如果状态为已通知就往下执行,或者等待超时也会往下执行,也可以设置一直等待

SystemFunction032()通过RC4加密方式加密内存

RtlCaptureContext()得到当前线程的CONTEXT结构

对于CONTEXT结构可以理解为:用于存储线程运行时寄存器的值,RIP,RSP......

NtContinue()对于这个函数确实不太理解,这里只需要知道给它传进去一个CONTEXT结构,就可以执行CONTEXT对应的代码,也就是可以控制程序执行流程。

Ekko代码阅读

一些不太重要的代码会跳过去

image.png

  hEvent = CreateEventW(0, 0, 0, 0);//创建一个未通知状态自动复位的事件hTimerQueue = CreateTimerQueue();//创建计时器队列NtContinue = GetProcAddress(GetModuleHandleA("Ntdll"), "NtContinue");//得到函数地址SysFunc032 = GetProcAddress(LoadLibraryA("Advapi32"), "SystemFunction032");ImageBase = GetModuleHandleA(NULL);//当前程序地址ImageSize = ((PIMAGE_NT_HEADERS)((DWORD64)ImageBase + ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew))->OptionalHeader.SizeOfImage;//大小

这段代码通过调用CreateTimerQueue创建了一个计时器队列接着,通过调用GetModuleHandleAGetProcAddress得到了NtContinueSystemFunction032函数的地址,接着又得到了当前程序的基地址和当前程序的大小

image.png

if (CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)RtlCaptureContext, &CtxThread, 0, 0, WT_EXECUTEINTIMERTHREAD))//调用RtlCaptureContext得到CONTEXT结构{WaitForSingleObject(hEvent, 0x32);//等待memcpy(&RopProtRW, &CtxThread, sizeof(CONTEXT));memcpy(&RopMemEnc, &CtxThread, sizeof(CONTEXT));memcpy(&RopDelay, &CtxThread, sizeof(CONTEXT));memcpy(&RopMemDec, &CtxThread, sizeof(CONTEXT));memcpy(&RopProtRX, &CtxThread, sizeof(CONTEXT));memcpy(&RopSetEvt, &CtxThread, sizeof(CONTEXT));

通过CreateTimerQueueTimer创建了一个计时器,在创建后会立刻调用(因为DueTimeperiod都是0)RtlCaptureContext函数得到当前线程的CONTEXT结构,接着使用得到的CONTEXT结构初始化了一些CONTEXT结构,为下面的调用做准备。

image.png

        //构造VirtualProtect函数的CONTEXT结构,此函数用于修改内存权限// VirtualProtect( ImageBase, ImageSize, PAGE_READWRITE, &OldProtect );RopProtRW.Rsp -= 8;RopProtRW.Rip = (DWORD64)VirtualProtect;RopProtRW.Rcx = (DWORD64)ImageBase;RopProtRW.Rdx = (DWORD64)ImageSize;RopProtRW.R8 = PAGE_READWRITE;RopProtRW.R9 = (DWORD64)&OldProtect;//构造SystemFunction032函数的CONTEXT结构,此函数用于加密内存// SystemFunction032( &Key, &Img );RopMemEnc.Rsp -= 8;RopMemEnc.Rip = (DWORD64)SysFunc032;RopMemEnc.Rcx = (DWORD64)&Img;RopMemEnc.Rdx = (DWORD64)&Key;//构造WaitForSingleObject函数的CONTEXT结构,此函数用于睡眠// WaitForSingleObject( hTargetHdl, SleepTime );RopDelay.Rsp -= 8;RopDelay.Rip = (DWORD64)WaitForSingleObject;RopDelay.Rcx = (DWORD64)NtCurrentProcess();RopDelay.Rdx = SleepTime;//构造SystemFunction032函数的CONTEXT结构,此函数用于解密内存// SystemFunction032( &Key, &Img );RopMemDec.Rsp -= 8;RopMemDec.Rip = (DWORD64)SysFunc032;RopMemDec.Rcx = (DWORD64)&Img;RopMemDec.Rdx = (DWORD64)&Key;//构造VirtualProtect函数的CONTEXT结构,此函数用于修改内存权限// VirtualProtect( ImageBase, ImageSize, PAGE_EXECUTE_READWRITE, &OldProtect );RopProtRX.Rsp -= 8;RopProtRX.Rip = (DWORD64)VirtualProtect;RopProtRX.Rcx = (DWORD64)ImageBase;RopProtRX.Rdx = (DWORD64)ImageSize;RopProtRX.R8 = PAGE_EXECUTE_READWRITE;RopProtRX.R9 = (DWORD64)&OldProtect;//构造SetEvent函数CONTEXT结构,设置对象为已通知状态// SetEvent( hEvent );RopSetEvt.Rsp -= 8;RopSetEvt.Rip = (DWORD64)SetEvent;RopSetEvt.Rcx = (DWORD64)hEvent;

这段代码为调用VirtualProtectSystemFunction032......做准备
主要通过给CONTEXT结构的成员赋值,来模拟对应函数的调用(当然这里不是真的调用)

image.png

    //等100毫秒向计时器发信号,通过NtContinue调用VirtualProtect取消内存可执行权限CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, &RopProtRW, 100, 0, WT_EXECUTEINTIMERTHREAD);//等200毫秒向计时器发信号,通过NtContinue调用SystemFunction032加密内存CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, &RopMemEnc, 200, 0, WT_EXECUTEINTIMERTHREAD);//等300毫秒向计时器发信号,通过NtContinue调用WaitForSingleObject进行睡眠CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, &RopDelay, 300, 0, WT_EXECUTEINTIMERTHREAD);

这段代码负责加密,主要通过CreateTimerQueueTimer函数创建计时器,计时器在等待指定的毫秒后,调用回调函数(也就是调用NtContinue)而NtContinue则会根据我们传入的CONTEXT结构去执行对应的函数。

比如第一行,传入的是VirtualProtect函数的CONTEXT结构,那么NtContinue将会调用VirtualProtect

下面是调用流程,画的有点丑,师傅们见谅^ _^......

image.png
第二行就是调用SystemFunction032来对内存进行加密
第三行就是调用WaitForSingleObject来实现睡眠,SleepTime就是睡眠的时间

image.png
下面来看一下解密内存部分

 //等400毫秒向计时器发信号,通过NtContinue调用SystemFunction032解密内存CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, &RopMemDec, 400, 0, WT_EXECUTEINTIMERTHREAD);//等500毫秒向计时器发信号,通过NtContinue调用VirtualProtect更改内存权限为可执行CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, &RopProtRX, 500, 0, WT_EXECUTEINTIMERTHREAD);//等600毫秒向计时器发信号,通过NtContinue调用SetEvent设置对象为已通知状态CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, &RopSetEvt, 600, 0, WT_EXECUTEINTIMERTHREAD);

第一行通过调用SystemFunction032来解密内存,第二行调用VirtualProtect设置内存权限为可读可写可执行,第三行调用SetEvent将事件对象设置为已通知状态。
内存加密部分执行流程

image.png

主要的代码已经介绍完了,下面来看一下效果。

效果

睡眠前

image.png
睡眠后

image.png
因为作者水平有限,文章中难免会出现错误和不足之处,如果有哪些不好的地方希望各位师傅斧正。

参考

https://github.com/Cracked5pider/Ekko Ekko项目地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/207878.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flutter 自定义TabBar 【top 0 级别】

flutter 自定义TabBar 【top 0 级别】 前言一、基础widget二、tab 标签三、barView总结 前言 在日常开发中,tab 标签选项,是一个我们特别常用的一个组件了,往往我们在一个项目中,有很多地方会使用到它,每次单独去写&am…

vue 中 mixin 和 mixins 区别

目录 前言 用法 全局Mixin 局部Mixin 代码 理解 高质量的Mixin使用 在Vue.js框架中,Mixin是一种非常重要和强大的功能,它允许开发者创建可复用的代码片段,并将其应用到一个或多个组件中。Vue提供了两种方式来使用Mixin,分别…

Mybatis相关API(Sqlsession和sqlsessionFactroy)

代码 private static SqlSessionFactory sqlSessionFactory;static { ​try { // 获得核心配置文件String resource "mybits-config.xml"; // 加载核心配置文件InputStream inputStream Resources.getResourceAsStream(resource…

MATLAB 和 Simulink 官方文档下载地址

MATLAB 官方文档中文版下载网址: https://ww2.mathworks.cn/help/pdf_doc/matlab/index.html 如图: MATLAB 官方文档英文版下载网址: https://ww2.mathworks.cn/help/pdf_doc/matlab/index.html?langen 如图: Simulink 官…

Oracle(2-7)Instance and Media Recovery Structures

文章目录 一、基础知识1、体系结构详解2、Database Files 数据库文件3、Database Other Files 其他数据文件4、Dynamic Views 动态视图5、Large Pool6、DB Buffer Cache,DBWn7、Configuring Tablespaces 配置表空间8、Redo Log Buffer, LGWR9、Database Checkpoints 数据库检查…

文献速递:人工智能在健康和医学中

人工智能在健康和医学中 01 文献速递介绍 这篇文章详细探讨了人工智能(AI)在医学领域的最新进展、挑战和未来发展的机遇。 1.医学AI算法的最新进展: **AI在医疗实践中的应用:**虽然AI系统在多项回顾性医学研究中表现出色&…

泊车功能专题介绍 ———— 汽车全景影像监测系统性能要求及试验方法(国标未公布)

文章目录 术语和定义一般要求功能要求故障指示 性能要求响应时间图像时延单视图视野范围平面拼接视图视野平面拼接效果总体要求行列畸变拼接错位及拼接无效区域 试验方法环境条件仪器和设备车辆条件系统响应时间试验图像时延试验单视图视野范围试验平面拼接视图视野试验平面拼接…

2022年6月1日 Go生态洞察:开发者反馈与Go的未来发展

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

继电保护-变压器纵联差动保护MATLAB仿真模型

微❤关注“电气仔推送”获得资料(专享优惠) 原理概述 差动保护是在两端设置的保护,通过比较两端测回来的电气量,进而看是否需要动作,纵联差动保护是变压器主保护。 纵联差动保护基本原则 双绕组变压器实现纵联差动…

C语言:写一个函数,实现3*3矩阵的转置(指针)

分析: 在主函数 main 中,定义一个 3x3 的整型数组 a,并定义一个指向整型数组的指针 p。然后通过循环结构和 scanf 函数,从标准输入中读取用户输入的 3x3 矩阵的值,并存储到数组 a 中。 接下来,调用 mov…

HarmonyOs 4 (二) HelloWord

目录 一 开发工具下载安装1.1 下载安装包1.2 下载相关依赖 二 开发者注册与个人实名认证三 第一个程序2.1 创建第一个程序2.2 认识开发者界面2.3 目录结构认识2.3.1 父目录认识2.3.2 AppScope 目录2.3.3 entry目录2.3.3.1 ets 目录2.3.3.2 resources目录 2.3.4 认识配置文件2.3…

服务器数据恢复—服务器断电导致XenServer数据文件丢失的数据恢复案例

服务器数据恢复环境: 某品牌720服务器搭配该品牌某型号RAID卡,使用4块STAT硬盘组建了一组RAID10阵列。服务器上部署XenServer虚拟化平台,系统盘 数据盘两个虚拟机磁盘。虚拟机上安装的是Windows Server操作系统,作为Web服务器使用…

centos7搭建 PXE 服务安装 window10/11 系统

最近想搭建之前基于 window server 的 window 批量安装,但想想装 window server 真的太麻烦了,我只是为了 PXE 安装系统而已,这些装一个极度消耗资源的系统真是相当麻烦呀,之前装的 server 不维护的话,不是被挖矿盯上就…

【数据结构】 堆排序与TopK问题详解

在学习完堆的创建后,就轮到了标题的两个问题 这两个问题在实际生活中会有比较强的实际问题解决能力 先分别解释一下 堆排序: 运用堆的思想进行排序,时间复杂度为O(NlogN)TopK: 从一大堆数据中选择K个最大或最小的数据&#xff0c…

鸿蒙开发学习——应用程序框架

文章目录 UIAbility的生命周期Create状态WindowStageCreateForeground和Background前后台展示控制onWindowStageDestroyDestory 总结 UIAbility的生命周期 感觉这里他讲的不清晰,UIAbility的4个声明周期是Create、Foreground(桌面展示)、Back…

IOS/安卓+charles实现抓包(主要解决证书网站无法打开问题)

安装 官网下载 https://www.charlesproxy.com/latest-release/download.do 安装charles文档 流程 上述链接解决下图问题 使用介绍 Charles介绍 上述链接看一至三即可,了解首页各个按钮的作用 charles全面使用教程及常见功能详解(较详细&#xff09…

计算机视觉(OpenCV+TensorFlow)

计算机视觉(OpenCVTensorFlow) 文章目录 计算机视觉(OpenCVTensorFlow)前言3.图像金字塔3.1 高斯金字塔3.2 拉普拉斯金字塔 4.图像轮廓图像边缘和图像轮廓的区别检测图像绘制边缘 5.轮廓近似外接矩形外接圆 6. 模板匹配6.1 什么是…

Windows安装Mysql Workbench及常用操作

Mysql Workbench是mysql自带的可视化操作界面,功能是强大的,但界面和navicat比,就是觉得别扭,但其实用惯了也还好,各有特色吧。这里记录一下常用的操作。 官方手册:MySQL Workbench 一、安装 1. 下载 官方…

一、服务器准备

本案例使用VMware Workstation Pro虚拟机创建虚拟服务器来搭建Linux服务器集群,所用软件及版本如下: Centos7.7-64bit 1、三台虚拟机创建 第一种方式:通过iso镜像文件来进行安装(不推荐) 第二种方式:直接复制安装好的虚拟机文…

golang 函数选项模式

一 什么是函数选项模式 函数选项模式允许你使用接受零个或多个函数作为参数的可变构造函数来构建复杂结构。我们将这些函数称为选项,由此得名函数选项模式。 例子: 有业务实体Animal结构体,构造函数NewAnimal()&…