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 ...
随机推荐
- C++ Idioms Pimpl
References C++ Coding Standard 這本書的中文版不知道是不是翻譯問題,還是原作就有這種傾向,有些咬文嚼字的很不好懂. Exceptional C++ 這本比上面那本容易理解 ...
- Codeforce1343C. Alternating Subsequence
Recall that the sequence b is a a subsequence of the sequence a if b can be derived from a by removi ...
- spring中的核心类有那些,各有什么作用?
BeanFactory:产生一个新的实例,可以实现单例模式BeanWrapper:提供统一的get及set方法ApplicationContext:提供框架的实现,包括BeanFactory的所有功能 ...
- mybatis-plus-QueryWrapper 如何写or效果的语句 以及如何给or加括号
先说想要的结果 希望mybatis-plus中QueryWrapper写法生成的sql语句中查询条件是 WHERE (( (LOGIN_ID = ? OR SHI_JI_LOGIN_ID = ?) ) ...
- Makeflie脚本使用
1.目标 2.Makefile的作用 自动化编译仿真 文件有引用层级关系,Tb会引用RTL顶层,RTL顶层也会引用一些其他的小的模块,编译的时候被引用的文件需要先进行编译. 脚本有两种模式,debug ...
- 通过 DBCA 创建 Oracle Database 21c 的进度停滞在 36%
1.问题 安装过程中一直卡在36% 检查 dbca 日志文件 位于 H:\app\trmbh\cfgtoollogs\dbca\ORCL\trace.log_2023-09-12_12-04-20PM ...
- C++11 同步与互斥
C++11 同步与互斥 0. C++11的线程 #include <thread> 面向对象的接口 RAII(资源获取即初始化)机制,当线程对象被销毁时,会自动执行析构函数,如果线程仍然在 ...
- 鲲鹏920上面 Docker 部署 clickhouse 的方式方法
鲲鹏920上面 Docker 部署 clickhouse 的方式方法 背景 最近有一套鲲鹏920的测试环境, 研发同事想纯Dcoker部署一套环境. 其中就包括了 Clickhouse 之前发现Cli ...
- [转帖]Web技术(四):TLS 握手过程与性能优化(TLS 1.2与TLS 1.3对比)
https://blog.csdn.net/m0_37621078/article/details/106126033?ops_request_misc=%257B%2522request%255Fi ...
- [转帖]3.3.7. 自动诊断和建议报告SYS_KDDM
https://help.kingbase.com.cn/v8/perfor/performance-optimization/performance-optimization-6.html#sys- ...