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 ...
随机推荐
- 【Git】git多分支开发 git远程仓库 ssh链接远程仓库 协同开发 冲突解决 线上分支合并 pycharm操作git 远程仓库回滚
目录 昨日回顾 1 git多分支开发 分支操作 合并分支 2 git远程仓库 2.1 把路飞项目传到远程仓库(非空的) 3 ssh链接远程仓库,协同开发 4 协同开发 5 冲突解决 5.1 多人同一分 ...
- BBS项目(一):BBS需求分析 数据表设计 注册登录功能实现
目录 BBS需求分析 数据表设计 注册页面前端 上传头像 提交数据 FormData 注册后端逻辑 接受参数 验证参数 数据入库 密码加盐操作 返回数据 登录页面前端 生成验证码 前端提交数据 登录后 ...
- 用 WebRTC 打造一个音乐教育 App,要解决哪些音质难题?
在去年疫情期间,在线教育行业获得了井喷式的发展,这背后的技术功臣非 RTC 莫属.本文将分享 RTC 技术在音乐教育场景下的实践经验. 作者| 逸城 审校| 泰一 音乐教育场景 - 在线陪练 2020 ...
- Dapper.Lite 使用教程
以MySQL数据库为例 一. 安装 NuGet搜索Dapper.Lite并安装最新版本. NuGet搜索MySqlConnector并安装最新版本. 也可以使用MySql.Data库,但MySqlCo ...
- #2035:人见人爱A^B
实现代码 #include<iostream> using namespace std; int main() { int n, m, t; while (cin >> n & ...
- ZOJ - 1610 区间修改+暴力单点查询
一.内容 题意:给定[1,8000]区间,给定n组操作,每次将一段区间修改成某种颜色(对上一次颜色进行覆盖),最后问你能看到多少种颜色,且每种颜色有多少段. 二.思路 题目给定的区间是(x, y]左开 ...
- 2012年第三届蓝桥杯【C++省赛B组】
第一题:微生物增殖 假设有两种微生物 X 和 Y X出生后每隔3分钟分裂一次(数目加倍),Y出生后每隔2分钟分裂一次(数目加倍). 一个新出生的X,半分钟之后吃掉1个Y,并且,从此开始,每隔1分钟吃1 ...
- Java 并发编程之 JMM & volatile 详解
本文从计算机模型开始,以及CPU与内存.IO总线之间的交互关系到CPU缓存一致性协议的逻辑进行了阐述,并对JMM的思想与作用进行了详细的说明.针对volatile关键字从字节码以及汇编指令层面解释了它 ...
- python之HtmlTestRunner(一)生成测试报告
一.下载安装 windows10,cmd环境通过如下命令
- centos7进入单用户模式(忘记密码操作-真正解决方案)
centos7密码忘记了,如何登录进去呢. 1.重新启动 2.按e进入以下界面:linux系统引导 3.在标记的如下位置行尾增加:rw init=/bin/sh 4.按Ctrl+x执行可进入单用户 ...