dll oem证书导入工具_技术干货 | 恶意代码分析之反射型DLL注入

1d21f7e71b02822d39fe13351dca4def.png

欢迎各位添加微信号:qinchang_198231  

加入安全+ 交流群 和大佬们一起交流安全技术

01

技术概要

这是一种允许攻击者从内存而非磁盘向指定进程注入DLL的技术,该技术比常规的DLL注入更为隐蔽,因为除了不需要磁盘上的实际DLL文件之外,它也不需要任何Windows加载程序的辅助即可注入。这消除了将DLL注册为进程已加载模块的需求,从而可逃脱工具的监视。

首先准备好测试dll,使用VS2015先编译生成一个测试dll文件,作用是dll被进程附加的时候会执行MessageBox弹框,切记不要选择空项目。如下,在DLL_PROCESS_ATTACH添加一个消息框函数,直接编译生成dll。

5df0f8426ecb89ba18feb4314035567f.png

下面会根据源码逐步分析整体执行流程,示例代码是模拟内存自加载dll的过程,为了演示所以采用了比较简单的方式,dll文件生成后放在在本地,而真实案例中恶意代码会存在母体文件的内存中,因为需要不落地内存加载。

先声明相应的结构体变量,采用指定位数的方式指定结构体变量实际占用的位数(根据重定位表的特性),声明一个函数指针便于后续进行调用执行dll入口。

ccd5adb446fb40c1a9167f35d67e2858.png

第一步先通过GetModuleHandleA获取基址,避免ASLR随机基址影响,读取dll文件内容加载至内存中,通过PE结构获取实际加载至内存中dll的PE头部数据。

ef72fdec6fd03e9d3c94066a17469b8c.png

分配dll加载时所需的内存空间,获取加载基址与预期基址的差值,接着复制dll头部数据至新的内存空间。

3181dd22a0296d2bbc7ffc918a2d09de.png

开始模拟Windows加载器功能加载PE文件至内存,如下。

e0c63beeaf960919ab965634ae68dd7e.png

02

PE文件重定位

基址重定位表位于PE头的IMAGE_NT_HEADERS/IMAGE_OPTION_HEADER/IMAGE_DATA_DIRECTORY[5],换句话说重定位表位于可选头的数据目录表下的第六项,基址重定位表中记录硬编码地址的位置(偏移),使用这张表就能获得准确的硬编码地址偏移并后续对其修正。重定位表是按照一个物理页(4kb或1000H)进行存储的,也就是一个重定位块负责一个4kb内存页,一个重定位表只管自己当前的物理页重定位。一个重定位表的记录偏移的大小是2个字节(1000H最多需要12bit即可0~FFFH),也就是16位,而记录偏移的大小是由SizeofBlock决定的。

如何修正?

将指令中的操作数按照指针字节数读取出来,然后将其减去默认加载基址(扩展头中的字段ImageBase),再加上新的加载基址,最后把新地址存入原来的地址中。

2f3f5831c3db8ba6d068dde58bec4912.png

重定位工作完成之后,进行导入表的解析。

acb7da731f26967f0c4713301f390210.png

以上工作准备完毕之后,就已经模拟内存加载完成,之后获取dll文件入口点进行执行,利用了之前声明的函数指针。

defc38494570a167c8a64361242a13bf.png

03

示例源码

#include

#include

typedef struct BASE_RELOCATION_BLOCK {

       DWORD PageAddress;

       DWORD BlockSize;

} BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK;

typedef struct BASE_RELOCATION_ENTRY {

       USHORT Offset : 12;

       USHORT Type : 4;

} BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY;

using DLLEntry = BOOL(WINAPI *)(HINSTANCE dll, DWORD reason, LPVOID reserved);

int main()

{

       //得到当前模块的基址

       PVOID imageBase = GetModuleHandleA(NULL);

       //本地加载dll内容至内存中

       HANDLE dll =  CreateFileA("C:\\Users\\onion\\Desktop\\dll\\Release\\dll.dll", GENERIC_READ,  NULL, NULL, OPEN_EXISTING, NULL, NULL);

       DWORD64 dllSize = GetFileSize(dll, NULL);

       LPVOID dllBytes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dllSize);

       DWORD outSize = 0;

       ReadFile(dll, dllBytes, dllSize, &outSize, NULL);

       //获取已加载至内存中的dll的头部数据

       PIMAGE_DOS_HEADER dosHeaders = (PIMAGE_DOS_HEADER)dllBytes;

       PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)dllBytes +  dosHeaders->e_lfanew);

       SIZE_T dllImageSize = ntHeaders->OptionalHeader.SizeOfImage;

       //分配dll加载时所需的内存空间

       LPVOID dllBase = VirtualAlloc((LPVOID)ntHeaders->OptionalHeader.ImageBase,  dllImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

       //得到实际分配的内存基址与预期的基址差值,便于后续进行重定向

       DWORD_PTR deltaImageBase = (DWORD_PTR)dllBase -  (DWORD_PTR)ntHeaders->OptionalHeader.ImageBase;

       //将dll头部数据复制到分配的内存空间

       std::memcpy(dllBase, dllBytes, ntHeaders->OptionalHeader.SizeOfHeaders);

       //加载节区数据至新的内存空间

       PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);

       for (size_t i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)

       {

              LPVOID sectionDestination = (LPVOID)((DWORD_PTR)dllBase +  (DWORD_PTR)section->VirtualAddress);

              LPVOID sectionBytes = (LPVOID)((DWORD_PTR)dllBytes +  (DWORD_PTR)section->PointerToRawData);

              std::memcpy(sectionDestination, sectionBytes,  section->SizeOfRawData);

              section++;

       }

       // 开始dll加载实现重定位

       IMAGE_DATA_DIRECTORY relocations =  ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

       DWORD_PTR relocationTable = relocations.VirtualAddress +  (DWORD_PTR)dllBase;

       DWORD relocationsProcessed = 0;

       while (relocationsProcessed < relocations.Size)

       {

              PBASE_RELOCATION_BLOCK relocationBlock =  (PBASE_RELOCATION_BLOCK)(relocationTable + relocationsProcessed);

              relocationsProcessed += sizeof(BASE_RELOCATION_BLOCK);

              DWORD relocationsCount = (relocationBlock->BlockSize -  sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY);

              PBASE_RELOCATION_ENTRY relocationEntries =  (PBASE_RELOCATION_ENTRY)(relocationTable + relocationsProcessed);

              for (DWORD i = 0; i < relocationsCount; i++)

              {

                     relocationsProcessed += sizeof(BASE_RELOCATION_ENTRY);

                     if (relocationEntries[i].Type == 0)

                     {

                           continue;

                     }

                     DWORD_PTR relocationRVA = relocationBlock->PageAddress +  relocationEntries[i].Offset;

                     DWORD_PTR addressToPatch = 0;

                     ReadProcessMemory(GetCurrentProcess(),  (LPCVOID)((DWORD_PTR)dllBase + relocationRVA), &addressToPatch, sizeof(DWORD_PTR),  NULL);

                     addressToPatch += deltaImageBase;

                     std::memcpy((PVOID)((DWORD_PTR)dllBase + relocationRVA),  &addressToPatch, sizeof(DWORD_PTR));

              }

       }

       //解析导入表

       PIMAGE_IMPORT_DESCRIPTOR importDescriptor = NULL;

       IMAGE_DATA_DIRECTORY importsDirectory =  ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

       importDescriptor =  (PIMAGE_IMPORT_DESCRIPTOR)(importsDirectory.VirtualAddress + (DWORD_PTR)dllBase);

       LPCSTR libraryName = "";

       HMODULE library = NULL;

       while (importDescriptor->Name != NULL)

       {

              libraryName = (LPCSTR)importDescriptor->Name + (DWORD_PTR)dllBase;

              library = LoadLibraryA(libraryName);

              if (library)

              {

                     PIMAGE_THUNK_DATA thunk = NULL;

                     thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)dllBase +  importDescriptor->FirstThunk);

                     while (thunk->u1.AddressOfData != NULL)

                     {

                           if (IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal))

                           {

                                  LPCSTR functionOrdinal =  (LPCSTR)IMAGE_ORDINAL(thunk->u1.Ordinal);

                                  thunk->u1.Function =  (DWORD_PTR)GetProcAddress(library, functionOrdinal);

                           }

                           else

                           {

                                  PIMAGE_IMPORT_BY_NAME functionName =  (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)dllBase + thunk->u1.AddressOfData);

                                  DWORD_PTR functionAddress =  (DWORD_PTR)GetProcAddress(library, functionName->Name);

                                  thunk->u1.Function = functionAddress;

                           }

                           ++thunk;

                     }

              }

              importDescriptor++;

       }

       //执行加载的dll

       DLLEntry DllEntry = (DLLEntry)((DWORD_PTR)dllBase +  ntHeaders->OptionalHeader.AddressOfEntryPoint);

       (*DllEntry)((HINSTANCE)dllBase, DLL_PROCESS_ATTACH, 0);

       CloseHandle(dll);

       HeapFree(GetProcessHeap(), 0, dllBytes);

       return 0;

}

04

整个流程

1、读入原始DLL文件至内存缓冲区;

2、解析DLL标头并获取SizeOfImage;

3、为DLL分配新的内存空间,大小为SizeOfImage;

4、将DLL标头和PE节复制到步骤3中分配的内存空间;

5、执行重定位;

6、加载DLL导入的库;

7、解析导入地址表(IAT);

8、调用DLL的DLL_PROCESS_ATTACH;

05

演示效果

a163eb2974a83a9a9620aef74e862e73.gif

06

真实案例

Netwalker勒索软件dll自加载技术

恶意文件是一个混淆并加密过的PowerShell脚本,先对PowerShell脚本进行解混淆。解混淆后的内容如下,字节序列中的0x4d、0x5a明显是一个PE文件标志头,一旦加载执行后,这部分内容就在内存中了。

4b9ec76e911458dadd9ee7ca98e9d84b.png

明显的C#代码模拟解析PE结构,如下。

d53904ddfa7838f00e94241e0e9bf1f7.png

执行自加载执行,如下。

2682bb91d52a670e2fc1544b6151771e.png0c92db184aadd95c70063096578a5372.png

更详细的内容可去除混淆后自行查看,该勒索样本实现的反射加载过程非常明显。加载执行后,通过模拟加载dll并调用导出函数Do后进而实现注入目标进程,类似的技术则与开源项目PowerSploit中的反射自加载的Mimikatz脚本实现相类似。

07

参考

https://ired.team/offensive-security/code-injection-process-injection/reflective-dll-injection

https://blog.trendmicro.com/trendlabs-security-intelligence/netwalker-fileless-ransomware-injected-via-reflective-loading/

https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Invoke-Mimikatz.ps1

d1f36e8de6cf04c84f6f7983b8d97524.png

583c001bb01f48bde049b8c408a2f290.png

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

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

相关文章

锐捷亮相GITC:请互联网企业为我点个赞!

【51CTO.com原创稿件】GITC全球互联网技术大会已成功举办四届&#xff0c;今年的会议现场依然是摩肩接踵围观者众。围绕互联网热点技术&#xff0c;众人根据云、大数据、安全、运维、基础架构的不同主题&#xff0c;各自聚成小圈子展开深入交流。 锐捷的展位在主会场的内侧&…

react.lazy 路由懒加载_React lazy/Suspense使用及源码解析

React v16.6.0已经发布快一年了&#xff0c;为保障项目迭代发布&#xff0c;没有及时更新react版本&#xff0c;最近由于开启了新项目&#xff0c;于是使用新的react版本进行了项目开发。项目工程如何搭建&#xff0c;如何满足兼容性要求&#xff0c;如何规范化等等这里不作为介…

c语言数据结构系统化,C语言数据结构+数据库+操作系统

http://cv.qiaobutang.com/post/55c419b20cf2009bd4607795第二部分是专业相关的C &#xff0c;数据库&#xff0c;操作系统&#xff0c;数据结构。http://c.biancheng.net/cpp/u/shuju/数据(Data)是信息的载体&#xff0c;它能够被计算机识别、存储和加工处理。它是计算机程序加…

c语言判断一个序列是不是另一个的子序列

1 #include <stdio.h>2 #include <string.h>//添加字符串头文件3 4 int Subsequence(char s[], char t[]) 5 {6 int m,n,i,j;7 n strlen(s); //n表示序列S的长度8 m strlen(t); //m表示序列T的长度9 i0; 10 j0; 11 if (m>…

linux中python如何调用matlab的数据_特征锦囊:如何在Python中处理不平衡数据

今日锦囊特征锦囊&#xff1a;如何在Python中处理不平衡数据? Index1、到底什么是不平衡数据2、处理不平衡数据的理论方法3、Python里有什么包可以处理不平衡样本4、Python中具体如何处理失衡样本印象中很久之前有位朋友说要我写一篇如何处理不平衡数据的文章&#xff0c;整理…

Hadoop不适合哪些场景 哪些场景适合?

Hadoop设计的目的主要包括下面几个方面&#xff0c;也就是所谓的适用场景&#xff1a; 1&#xff1a;超大文件 可以是几百M&#xff0c;几百T这个级别的文件。 2&#xff1a;流式数据访问 Hadoop适用于一次写入&#xff0c;多次读取的场景&#xff0c;也就是数据复制进去之后&a…

阿里Android p6准备,项目经历准备篇——如何准备阿里巴巴P6/P7前端面试

项目经历准备篇——如何准备阿里巴巴P6/P7前端面试在上次的校招文章之后&#xff0c;有很多同学问有没有社招相关的东西可以写一篇&#xff0c;现在它来了。比起校招&#xff0c;社招更加看重项目经历项目经历反应的思考。本文针对的是想进入阿里的P6/P7同学&#xff0c;着重讲…

for in for of区别_Python 第4课:for…in循环黄金搭档之range()函数

乐学趣学Py● 04&#xff1a;for…in循环黄金搭档之range()函数●Python趣味小百科Python中的绘图模块为什么叫Turtle海龟&#xff0c;而不是cat ,dog,bird呢&#xff1f;原来Python引用了麻省理工大学教授开发的logo海龟制图语言,能通过绘图直观地教大家学习编程。实践是最好的…

永恒python图片_python 数据词云展示实例(3)- 背景图设置

记录wordcloud库背景图的设置及样板 之前介绍了wordcloud的基本使用wordcloud的基本使用&#xff0c;本文记录一下如何设置背景图。 样图 背景图tim.jpg 生成样图dream.png 样板 from PIL import Image,ImageSequence image Image.open(tim.jpg)#打开背景图 graph np.array(im…

企业如何杜绝云端数据泄密?

一直以来&#xff0c;云计算所倡导的就是&#xff1a;“我们可以做得更好&#xff0c;更便宜”。云计算带给企业诸多利好&#xff0c;但实施云计算必然会加剧信息泄露风险。当企业打算把所有数据传输云端的时候&#xff0c;首先要考虑的就是数据保护的问题。 使用云服务&#x…

3dmark for android,Android版3DMark首测

听到这个消息估计很多像我一样看腻了3dmark11画面的跑分党及玩家们有些许小失望。 每年的12月影驰都会联合NVIDIA举办盛大的嘉年华&#xff0c;今年在武汉举办的影驰2012电子竞技嘉年华的合作伙伴名单上出现了futumark的身影。Futuremark中国区负责人影驰在当天的平板体验区也提…

android 申请usb权限,USB 权限申请流程

USB android授权方式权限的控制分三块&#xff1a;1:USB host端有个线程循环检测系统是否USB设备插拔&#xff0c;如果有就找到申请权限的APP并调用起来2:APP运行后主动申请权限&#xff0c;也就是requestPermission()接口3:APP运行后直接打开USB设备&#xff0c;这时候USB hos…

qt for android 图片可拉伸,qt实现九宫格布局,图片拉伸

在实现qt播放时&#xff0c;调用的mplayer,由于采用的是自定义绘图&#xff0c;用的是setAttribute(Qt::WA_TranslucentBackground);结果不能正常在上面显示播放画面&#xff0c;在默认皮肤下是没有问题的&#xff0c;决定用九宫格图片拉伸方式(效果如图)附件图片&#xff1a;文…

python不是内部文件_已安装python,但是出现‘python’不是内部或外部命令,也不是可运行的程序或批处理文件。...

解决方法&#xff1a; 1.打开python shell查看你的python安装路径&#xff08;黄色标注&#xff09; >>> import sys >>> sys.path [, C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python37\\Lib\\idlelib, C:\\Users\\Administrator\\App…

使用canvas绘制时钟

使用canvas绘制时钟 什么使canvas呢&#xff1f;HTML5 <canvas> 元素用于图形的绘制&#xff0c;通过脚本 (通常是JavaScript)来完成。<canvas> 标签只是图形容器&#xff0c;所以我们必须使用脚本来绘制图形。通过它可以绘制路径,盒、圆、字符以及添加图像等等。 …

c++分治法求最大最小值实现_最优化计算与matlab实现(12)——非线性最小二乘优化问题——G-N法...

参考资料《精通MATLAB最优化计算&#xff08;第二版&#xff09;》编程工具Matlab 2019a目录石中居士&#xff1a;最优化计算与Matlab实现——目录​zhuanlan.zhihu.com非线性最小二乘优化问题非线性最小二乘优化也叫无约束极小平方和函数问题&#xff0c;它是如下无约束极小问…

win7 IIS7环境下部署PHP 7.0

最近在本机电脑win7 II7环境下部署PHP 7.0遇到一些问题&#xff0c;将之记录下来 简要步骤如下&#xff1a; 1、到php官网下载php&#xff0c;由于是IIS环境要下载非线程安全的版本&#xff0c;我下载的是7.0.13 2、解压到本地文件目录下 3、通过控制台进入到php文件目录&#…

《Oracle高性能自动化运维》一一3.3 Redo产生场景

3.3 Redo产生场景我们知道&#xff0c;Oracle Redo是以条目&#xff08;Redo Entries/Records&#xff09;的形式记录数据库的所有更改操作&#xff08;OP&#xff09;。更改操作主要包括&#xff1a;数据库物理文件更改&#xff1a;主要指的是数据库物理文件的增减等操作&…

智能算法(GA、DBO等)求解零空闲流水车间调度问题(NIFSP)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

android 简单实现圆角,Android 实现圆角图片的简单实例

Android 实现圆角图片的简单实例实现效果图&#xff1a;本来想在网上找个圆角的例子看一看&#xff0c;不尽人意啊&#xff0c;基本都是官方的Demo的那张原理图&#xff0c;稍后会贴出。于是自己自定义了个View&#xff0c;实现图片的圆角以及圆形效果。效果图&#xff1a;Andr…