C/C++ 动态解密释放ShellCode
今天在复习《加密与解密》时,在软件保护这一章中有一个代码与数据结合的案例,其原理是将代码段中的代码进行xor异或加密处理以后回写到原始位置,当程序运行后将此处的内容动态的进行解密,解密后回写替换回原始内存位置,这样就能实现内存加载。
由此案例我想到一个关于免杀的利用思路,首先杀软的运作方式多数为特征码查杀,当我们程序中使用了敏感的函数时,就会存在被杀的风险,而如果将代码段中的代码进行加密,需要时直接在内存中解密,那么杀软将无法捕捉硬盘文件的特征,从而可以规避杀软针对硬盘特征的查杀手法。
经过阅读该案例的源码,我首先提取出了案例中的核心代码,并加以改进后将其从软件保护改为了免杀手法,其注册码生成工具核心代码如下所示,这里我没有动使用原始的加密工具即可。
for ( i=0;i<strlen(szBuffer);i++)
{
k = k*6 + szBuffer[i];
}
Size=address2-address1;
Size=Size/0x4; //加密时,每次异或 DWORD数据,Size是为最终需要异或的次数
offset=address1;
for (i=0;i<Size;i++)
{
SetFilePointer(hFile,offset,NULL,FILE_BEGIN);
ReadFile(hFile,szBuffer, 4, &szTemp, NULL);//读取DWORD字节的文件内容
ptr=(DWORD*)szBuffer;
*ptr=(*ptr)^k;
SetFilePointer(hFile,offset,NULL,FILE_BEGIN);
if(!WriteFile(hFile,ptr,4,&nbWritten,NULL))// 写入文件
{
MessageBox(NULL,"Error while patching !","Patch aborted",MB_ICONEXCLAMATION);
CloseHandle(hFile);
return 1;
}
offset=offset+4;
}
CloseHandle(hFile);
MessageBox(NULL,"Patch successfull !","Patch",MB_ICONINFORMATION);
return 1;
}
下面则是客户端解密代码,该代码的原始部分是注册机加密,我把它抽取出来改成了这个样子,首先使用__asm mov AddressA, offset BeginOEP
定义两个段标签,分别用于表示段的开始与结束,也就是我们需要加密与解密的代码段位置,在两个标签内部的就是我们的恶意代码,将其写入到标签中,标签中的__asm inc eax dec eax
则是一串标志用于快速定位到需要加密的位置。
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
void Decrypt(DWORD*, DWORD, DWORD);
void Decrypt(DWORD* pData, DWORD Size, DWORD value)
{
//首先要做的是改变这一块虚拟内存的内存保护状态,以便可以自由存取代码
MEMORY_BASIC_INFORMATION mbi_thunk;
//查询页信息
VirtualQuery(pData, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
//改变页保护属性为读写。
VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect);
Size = Size / 0x4; //对数据共需要异或的次数
//解密begindecrypt与enddecrypt标签处的数据
while (Size--)
{
*pData = (*pData) ^ value;
pData++;
}
//恢复页的原保护属性。
DWORD dwOldProtect;
VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect);
}
int main(int argc, char* argv[])
{
DWORD AddressA, AddressB, Size, key;
DWORD *ptr;
TCHAR cCode[30] = { 0 };
__asm mov AddressA, offset BeginOEP
__asm mov AddressB, offset EndOEP
Size = AddressB - AddressA;
ptr = (DWORD*)AddressA;
_tcscpy(cCode, L"lyshark"); // 设置加密密钥
key = 1;
for (unsigned int i = 0; i< lstrlen(cCode); i++)
{
key = key * 6 + cCode[i];
}
Decrypt(ptr, Size, key); //执行解密函数
BeginOEP:
__asm inc eax // 在十六进制工具中对应0x40
__asm dec eax // 在十六进制工具中对应0x48
MessageBoxA(0, "hello lyshark", 0, 0);
MessageBoxA(0, "hello lyshark", 0, 0);
EndOEP:
__asm inc eax
__asm dec eax
return 0;
}
程序在运行时,首先会循环计算异或密钥,计算完成后执行Decrypt函数,对特定的段进行解密后,释放到源文件中(注意是内存中)然后在调用执行,打印出一句问候语hello lyshark
程序结束。
注意:编译时,请关闭DEP,ASLR,地址随机化等保护,否则VA不固定,无法确定位置。
首先我们需要编译上方魔改版的代码片段,然后使用winhex然后按下【ctrl+alt+X】输入4048找到开始于结束的位置。
这里我们记下,需要加密的开始位置是【526】结束位置是【54b】中间代码部分就是我们需要加密的恶意代码。
接着打开Encrypter.exe工具依次输入加密开始结束位置与密钥,这里设置如下即可。
打开程序执行,会首先经过解密函数将加密后的代码片段释放到内存中,然后才会执行弹窗,非常的安全。
反汇编看一下,解密前,代码是混乱的,根本不是代码。
而执行解密后,内存中立刻恢复到了可以执行的代码状态,然后就可以开心的执行下去了。
此方法也可以规避部分逆向分析,由于不是汇编代码,所以也就无法分析出到底是做什么的了,当然了,如果能找到加密算法的密钥,同样可以解密出来,此处我们并不是用来防范解密者的,而是用来切断程序中的病毒特征的。
C/C++ 动态解密释放ShellCode的更多相关文章
- 动态加载 ShellCode绕过杀软
反病毒解决方案用于检测恶意文件,并且通常使用静态分析技术来区分二进制文件的好坏.如果是恶意文件本身包含恶意内容(ShellCode),那么依靠静态分析技术会非常有效,但如果攻击者使用轻量级的stage ...
- 【C/C++开发】C语言 DLL(动态链接库)中申请动态内存释放的问题
参考:首先,声明一点,凡是使用malloc之类命令动态申请的内存,必须进行释放操作,否则就会发生内存泄漏问题. DLL中申请的内存释放,如果没有做过,很可能会认为是直接在调用程序中释放就可以了,其实不 ...
- C/C++ 对代码节的动态加解密
加壳的原理就是加密或者压缩程序中的已有资源,然后当程序执行后外壳将模拟PE加载器对EXE中的区块进行动态装入,下面我们来自己实现一个简单的区块加解密程序,来让大家学习了解一下壳的基本运作原理. 本次使 ...
- Android动态方式破解apk终极篇(加固apk破解方式)
一.前言 今天总算迎来了破解系列的最后一篇文章了,之前的两篇文章分别为: 第一篇:如何使用Eclipse动态调试smali源码 第二篇:如何使用IDA动态调试SO文件 现在要说的就是最后一篇了,如何应 ...
- shellcode在栈溢出中的利用与优化
0x00 前言 在<Windows Shellcode学习笔记——shellcode的提取与测试>中介绍了如何对shellcode作初步优化,动态获取Windows API地址并调用,并通 ...
- 00-DLL劫持&C语言远程加载shellcode
0x01 杀软拦截检测规则引导-DLL劫持上线 准备工具 cs vs2019 dll劫持工具:https://bbs.pediy.com/thread-224408.htm 极速PDF:https:/ ...
- android加固系列—6.仿爱加密等第三方加固平台之动态加载dex防止apk被反编译
[版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5402599.html ] 此方案的目的是隐藏源码防止直接性的反编译查看源码,原理是加密编译好的 ...
- C++ 动态数组实例
一维动态数组的实例: #include <iostream> using namespace std; int main() { int *arr; int n; cout<< ...
- C++动态内存分配
C++动态内存分配1.堆内存分配 :C/C++定义了4个内存区间:代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念:通常定 ...
- C++ Primer : 第十二章 : 动态内存之动态数组
动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...
随机推荐
- MB51选择屏幕与报表增强
1.文档说明 如之前文档<MIGO新增页签增强>,在MIGO中增强自定义字段,那么在查询MB51时,想通过自定义字段进行筛选,并将数据展示到报表中,就需要对MB51进行增强. 此处需要说明 ...
- 它来了!真正的 python 多线程
哈喽大家好,我是咸鱼 几天前,IBM 工程师 Martin Heinz 发文表示 python 3.12 版本回引入"Per-Interpreter GIL",有了这个 Per-I ...
- AtCoder Beginner Contest 188 题解
AtCoder Beginner Contest 188 A,B很简单就不多说 C - ABC Tournament 找出前一半的最大值和后一半的最大值,二者中较小的那一个对应的序号就是最后的答案. ...
- docker 容器ip查看及 网络配置区别
本文为博主原创,未经允许不得转载: 1. 查看容器ip: 方法一:查看所有容器的ip docker inspect --format='{{.Name}} - {{range .NetworkSett ...
- zookeeper 集群环境搭建及集群选举及数据同步机制
本文为博主原创,未经允许不得转载: 目录: 1. 分别创建3个data目录用于存储各节点数据 2. 编写myid文件 3. 编写配置文件 4.分别启动 5.分别查看状态 6. 检查集群复制情况 ...
- 状态: 失败 -测试失败: IO 错误: The Network Adapter could not establish the connection (CONNECTION_ID=BMRc/8PgR2+0i4PK2tnHQA==)
1.问题 问题如标题所示,在使用Oracle SQL Developer连接时发现错误: 状态: 失败 -测试失败: IO 错误: The Network Adapter could not esta ...
- NSSCTF Round#11 Basic 密码个人赛复盘
[NSSRound#11 Basic]ez_enc ABAABBBAABABAABBABABAABBABAAAABBABABABAAABAAABBAABBBBABBABBABBABABABAABBAA ...
- [转帖]nginx反向代理时保持长连接
https://www.cnblogs.com/liufarui/p/11075630.html ·[场景描述] HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上 ...
- [转帖]警惕Oracle数据库性能“隐形杀手”——Direct Path Read
一. 简介 Oracle 的11g版本正式发布到今天已经10年有余,最新版本也已经到了20c,但是Direct Path Read(直接路径读)导致性能问题的案例仍时有发生,很多12c的用户还是经常遇 ...
- [转帖]CentOS 8已经停止维护,怎么检查CentOS的版本
https://rumenz.com/rumenbiji/centos-check-version.html CentOS 8 在2021年12月31日停止更新并停止维护(EOL). CentOS 7 ...