2.13 PE结构:实现PE代码段加密
代码加密功能的实现原理,首先通过创建一个新的.hack
区段,并对该区段进行初始化,接着我们向此区段内写入一段具有动态解密功能的ShellCode
汇编指令集,并将程序入口地址修正为ShellCode
地址位置处,当解密功能被运行后则可释放加密的.text
节,此时再通过一个JMP
指令跳转到原始OEP
位置,则可继续执行解密后的区段。
如下是一段异或解密功能实现,用于实现循环0x88
异或解密代码功能;
00408001 MOV EAX, main.00401000 (代码段首地址)
00408006 XOR BYTE PTR DS : [EAX], 88 (与0x88异或)
00408009 INC EAX
0040800A CMP EAX, main.00404B46 (代码段结束位置)
0040800F JNZ SHORT main.00408006 (写入原始OEP)
00408011 POPAD
00408012 MOV EAX, main.00401041 (写入新OEP)
00408017 JMP EAX
有了上述加密流程,则下一步就是对内部的变量进行填充,我们可以提取出这些汇编指令的机器码并存储到Code[]
数组内,通过对数组中的特定位置进行替换来完善跳转功能,此处我们需要提取如下几个位置的特征字段;
- 00408001 数组下标第
2
位替换为ImageBase + pSection->VirtualAddress
- 0040800A 数组下标第
11
位替换为ImageBase + pSection->VirtualAddress + pSection->Misc.VirtualSize
- 0040800F 数组下标第
19
位替换为ImageBase + BaseRVA
- 00408012 原始
OEP
位置替换为pSection->VirtualAddress
根据上述流程我们可以编写一个AddPacking
函数,该函数通过传入一个待加密程序路径,则可将一段解密代码Code[]
写入到程序节表中的最后一个节.hack
所在内存空间,并动态修正当前入口地址为.hack
节的首地址,最终执行解密后自动跳转回原始OEP位置执行功能,如下代码所示;
// 对文件执行加壳操作
void AddPacking(LPSTR szFileName)
{// 打开文件HANDLE hFile = CreateFileA(szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);// 创建文件映射HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, 0);HANDLE lpBase = MapViewOfFile(hMap, FILE_MAP_READ | FILE_SHARE_WRITE, 0, 0, 0);// 找到PE文件头PIMAGE_DOS_HEADER DosHdr = (PIMAGE_DOS_HEADER)lpBase;PIMAGE_NT_HEADERS NtHdr = (PIMAGE_NT_HEADERS)((DWORD)lpBase + DosHdr->e_lfanew);DWORD ImageBase = NtHdr->OptionalHeader.ImageBase;DWORD BaseRVA = NtHdr->OptionalHeader.AddressOfEntryPoint;PIMAGE_FILE_HEADER FileHdr = &NtHdr->FileHeader;PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(NtHdr);// 首先得到最后一个节的指针,然后找到里面的虚拟偏移值,填入到程序OEP位置即可。DWORD SectionNum = FileHdr->NumberOfSections;char Code[] ={"\x60""\xb8\x00\x00\x00\x00""\x80\x30\x88""\x40""\x3d\xff\x4f\x40\x00""\x75\xf5""\x61""\xb8\x00\x00\x00\x00""\xff\xe0"};DWORD dwWrite = 0;// 写入代码节开始位置*(DWORD *)&Code[2] = ImageBase + pSection->VirtualAddress;printf("[+] 写入代码节开始位置: 0x%08X \n", ImageBase + pSection->VirtualAddress);// 写入代码节终止位置*(DWORD *)&Code[11] = ImageBase + pSection->VirtualAddress + pSection->Misc.VirtualSize;printf("[+] 写入代码节结束位置:0x%08X \n", ImageBase + pSection->VirtualAddress + pSection->Misc.VirtualSize);// 写入原来的的OEP位置*(DWORD *)&Code[19] = ImageBase + BaseRVA;printf("[+] 写入原始OEP 0x%08X \n", ImageBase + BaseRVA);// 拿到最后一个节的文件偏移pSection = pSection + (SectionNum - 1);printf("[+] 得到最后一个节的实际地址: 0x%08X \n", pSection->PointerToRawData);// 设置指针到最后一个节文件偏移位置SetFilePointer(hFile, pSection->PointerToRawData, 0, FILE_BEGIN);WriteFile(hFile, (LPVOID)Code, sizeof(Code), &dwWrite, NULL);FlushViewOfFile(lpBase, 0);// 修正当前入口点地址printf("[+] 修正入口点地址为: 0x%08X \n", pSection->VirtualAddress);*(DWORD *)&NtHdr->OptionalHeader.AddressOfEntryPoint = pSection->VirtualAddress;UnmapViewOfFile(lpBase);
}
读者可自行运行上述代码片段,传入d://lyshark.exe
对该程序中的.text
节进行解密,运行后读者可打开x64dbg
调试器,观察入口地址处的变化,此时入口地址已经跳转到.hack
节内,此节中的汇编指令则用于对.text
代码节进行解密操作,当解密结束后则会跳转到原始地址0x45C865
位置处,如下图所示;
当加密功能写入后,则接下来就可以对.text
代码节进行加密了,加密的实现也非常容易,如下函数,通过定位到第一个节,并通过ReadFile
函数将这个节读入内存,通过循环对这个区域进行加密,最后调用WriteFile
函数再将加密后的数据回写到代码节,此时加密功能就实现了,如下所示;
// 将特定的节进行加密,此处只加密Text节
void EncrySection(LPSTR szFileName, DWORD Key)
{// 打开文件HANDLE hFile = CreateFileA(szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);// 创建文件映射HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, 0);HANDLE lpBase = MapViewOfFile(hMap, FILE_MAP_READ | FILE_SHARE_WRITE, 0, 0, 0);// 定位PE文件节PIMAGE_DOS_HEADER DosHdr = (PIMAGE_DOS_HEADER)lpBase;PIMAGE_NT_HEADERS NtHdr = (PIMAGE_NT_HEADERS)((DWORD)lpBase + DosHdr->e_lfanew);PIMAGE_FILE_HEADER FileHdr = &NtHdr->FileHeader;PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(NtHdr);printf("[-] 节虚拟地址: 0x%08X 虚拟大小: 0x%08X\n", pSection->VirtualAddress, pSection->Misc.VirtualSize);printf("[-] 读入FOA基地址: 0x%08X 节表长度: 0x%08X \n", pSection->PointerToRawData, pSection->SizeOfRawData);printf("[-] 已对 %s 节 --> XOR加密/解密 --> XOR密钥: %d \n\n", pSection->Name, Key);// 分配内存空间DWORD dwRead = 0;PBYTE pByte = (PBYTE)malloc(pSection->SizeOfRawData);SetFilePointer(hFile, pSection->PointerToRawData, 0, FILE_BEGIN);memset(pByte, 0, pSection->SizeOfRawData);ReadFile(hFile, pByte, pSection->SizeOfRawData, &dwRead, NULL);// 对代码节加密for (int x = 0; x < pSection->SizeOfRawData; x++){pByte[x] ^= Key;}// 写出加密后的数据SetFilePointer(hFile, pSection->PointerToRawData, 0, FILE_BEGIN);WriteFile(hFile, pByte, pSection->SizeOfRawData, 0, FILE_BEGIN);pSection->Characteristics = 0xE0000020;free(pByte);FlushViewOfFile(lpBase, 0);UnmapViewOfFile(lpBase);
}
读者通过AddPacking
函数对文件加壳后,接着就可以调用EncrySection
函数对目标程序进行异或处理,此处分别传入d://lyshark.exe
路径,以及一个加密密钥0x88
,等待加密结束即可,此时运行程序即可实现对代码段的解密运行,这样也就起到了保护了代码段的作用,如下是解密之前的代码段;
当解密后,代码段将会被展开,并输出如下图所示的样子,此时程序即可被正确执行;
本文作者: 王瑞
本文链接: https://www.lyshark.com/post/5912e71.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章:

2.13 PE结构:实现PE代码段加密
代码加密功能的实现原理,首先通过创建一个新的.hack区段,并对该区段进行初始化,接着我们向此区段内写入一段具有动态解密功能的ShellCode汇编指令集,并将程序入口地址修正为ShellCode地址位置处,当解密功能被运行后则可…...
Rust更换Cargo国内源,镜像了寂寞
换皮不换身 换了国内源,构建时该卡还会卡。因为它所谓的换源,只是更换crates.io“索引”的源,而不是package“内容”的源。换了国内源后,在国内编译时访问 crates.io-index 自然会快很多,可是crates.io-index里面的信…...

【网络安全带你练爬虫-100练】第23练:文件内容的删除+写入
目录 0x00 前言: 0x02 解决: 0x00 前言: 本篇博文可能会有一点点的超级呆 0x02 解决: 你是不是也会想: 使用pyrhon将指定文件夹位置里面的1.txt中数据全部删除以后---->然后再将参数req_text的值写入到1.txt …...
ESP32蓝牙实例-BLE服务器与客户端通信
BLE服务器与客户端通信 文章目录 BLE服务器与客户端通信1、软件准备2、硬件准备3、代码实现3.1 BLE服务器实现3.2 Android手机测试BLE服务器3.3 ESP32 BLE客户端在本文中,我们将介绍如何使用低功耗蓝牙在两个 ESP32 开发板之间执行 BLE 服务器客户端通信。 换句话说,将介绍如…...

第11章_瑞萨MCU零基础入门系列教程之SysTick
本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id728461040949 配套资料获取:https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总: ht…...
【面试题精讲】如何使用Stream的聚合功能
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 求和(Sum): List<Integer> numbers Arrays.asList(1, 2, 3, 4, 5);int sum n…...
Linux 中的 chmod 命令及示例
在 Unix 操作系统中,chmod命令用于更改文件的访问模式。该名称是change mode的缩写。其中规定每个文件和目录都有一组权限来控制权限,例如谁可以读取、写入或执行该文件。其中权限分为三类:同时读、写和执行,用“r”、“w”和“x”表示。这些字母组合在一起形成一组用户的特…...
sannaing i14 pro max使用体验
体验了一把山寨机,不明真相的人会以为这是三星的英文标志,又是pro又是max的,价格600,进系统去看了配置,cpu写的是snapdragon 888,运存12g,内存500g。下了个安兔兔也是被忽悠了,它也以…...

Shazam音乐检索算法原理及实现
算法基本流程如下: 1. 采集音乐库 2. 音乐指纹采集 3. 采用局部最大值作为特征点 4. 将临近的特征点进行组合形成特征点对 5. 对每个特征点对进行hash编码 编码过程:将f1和f2进行10bit量化,其余bit用来存储时间偏移合集形成32bit的hash码 …...
vue递归组件
父组件: <template><div><treeVue :treeData"treeData"></treeVue></div> </template><script setup lang"ts"> import { reactive } from "vue"; import treeVue from "./tree.vue…...

软件测试/测试开发丨测试用例自动录入 学习笔记
点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接:https://ceshiren.com/t/topic/27139 测试用例自动录入 测试用例自动录入的价值 省略人工同步的步骤,节省时间 兼容代码版本的自动化测试用例 用例的执行与调度统一化管理…...

来学Python啦,大话字符串
To be a happy man, reading, travel, hard work, care for the body and mind。做一个幸福的人,读书,旅行,努力工作,关心身体和心境。 前面我们讲解过关于用Python写温度转换器&…...

pyqt5设置背景图片
PyQt5设置背景图片 1、打开QTDesigner 创建一个UI,camera.ui。 2、创建一个pictures.qrc文件 在ui文件同级目录下先创建一个pictures.txt,填写内容: <RCC><qresource prefix"media"><file>1.jpg</file>…...

C# WPF 自己写的一个模拟病毒传播的程序,有可视化
源代码: https://github.com/t39q/VirusSpread 主要代码 using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace VirusSpread.Bu…...

stable diffusion实践操作-大模型介绍-SDXL1大模型
系列文章目录 大家移步下面链接中,里面详细介绍了stable diffusion的原理,操作等(本文只是下面系列文章的一个写作模板)。 stable diffusion实践操作 提示:写完文章后,目录可以自动生成,如何生…...
软考高级系统架构设计师系列案例考点专题四:嵌入式系统
软考高级系统架构设计师系列案例考点专题四:嵌入式系统 一、相关概念二、软件可靠性和硬件可靠性的区别三、可靠性指标四、可靠性设计五、冗余技术六、软件容错七、双机容错技术八、集群技术九、负载均衡十、可维护性的评价指标十一、软件维护的分类嵌入式每年必考一题,但是属…...

Django Form实现表单使用及应用场景
首先需要定义一个使用场景: 音乐网站的前端部分可以添加上传歌手的单曲, 这个添加页面就使用django form表单来实现。 目录 数据表内容 歌手表及表模型 单曲表及表模型 演示表单使用 设置路由 创建form.py 视图实例化表单类 模板使用表单对象 表…...

golang面试题:json包变量不加tag会怎么样?
问题 json包里使用的时候,结构体里的变量不加tag能不能正常转成json里的字段? 怎么答 如果变量首字母小写,则为private。无论如何不能转,因为取不到反射信息。如果变量首字母大写,则为public。 不加tag,…...
国内项目管理中级证书CSPM-3正在报名!
CSPM-3中级项目管理专业人员认证,是中国标准化协会(全国项目管理标准化技术委员会秘书处),面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系,建立健全人才职业能力评价和激励机制的要…...

vue表格不显示列号123456
我在网上找了半天,都是如何添加列号123456的,没有找到不显示列号的参考,现在把这个解决了,特此记录一下。 没有加右边的就会显示,加上右边的就隐藏了...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
高防服务器价格高原因分析
高防服务器的价格较高,主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因: 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器,因此…...