VC实现SMC加密技术
来源:互联网 发布:tomcat 域名绑定 编辑:程序博客网 时间:2024/05/16 18:45
前言
SMC是一种局部代码加密技术,通过对一段代码进行加密来达到增加逆向工程难度或者免杀的目的。
编写SMC代码不是汇编语言的专利。——《加密与解密 第三版》
是的,SMC不仅能使用汇编上实现,还能很容易的使用VC实现,但是有一个比较致命缺陷:要精准的定位某个函数非常麻烦,所以我们就要以区块为加密的基础单位。
预备知识
需要一点点的PE结构基础就ok啦。
加密算法
既然是加密,就必然需要加密算法。Internet上有许多优秀的开源加密算法,在这篇文章中我将使用自己编写的加密算法。
加密原理简单,是大家耳熟能详的异或加密。
异或的运算方法是一个二进制运算:
1^1=0
0^0=0
1^0=1
0^1=1
两者相等为0,不等为1.
对于一个字符来说,都可以用二进制码来表示.如A:01000001
字符的异或就是对每一位进行二进制运算.
用于加密算法时,假设你要加密的内容为A,密钥为B,则可以用异或加密:
C=A^B
在数据中保存C就行了.
用的时候:
A=B^C
即可取得原加密的内容,所以只要知道密钥,就可以完成加密和解密.
根据原理可以推导出,加密函数也自带解密功能。
void xorPlus(char *soure,int dLen,char *Key,int Klen){ for (int i=0;i<dLen;) { for (int j=0;(j<Klen) && (i<dLen);j++,i++) { soure[i]=soure[i] ^ Key[j]; soure[i]=~soure[i]; } }}
参数说明
1. soure 被加数据的指针
2. dLen 被加密数据的长度
3. key 密匙数据的指针
4. key 的长度
NOTE:这个函数即时加密函数也是解密函数。
保护敏感代码
这里的敏感代码指的是Cracker和杀毒软件感兴趣的代码,也许你并不想让它们轻松地得到想要的结果。
因为定位一个具体的函数很繁琐,所以我们选择直接定位一个节表。把敏感的代码放入一个新的节表中,然后在需要的时候进行解密,这就是SMC动态加密技术的精髓。
如何把敏感代码放入一个新的节表中?
#pragma code_seg(".SMC")void Fun1(){ MessageBoxA(NULL,"正在执行被加密算法。",NULL,MB_OK);}#pragma code_seg()#pragma comment(linker, "/SECTION:.SMC,ERW")
#pragma code_seg(“.SMC”) 是一条预编译指令,作用是告诉链接器下面的代码放入 .SMC 代码段中。参数是代码段节表名,学过PE结构的人都知道,节表名<=8 个字符
#pragma code_seg() 是指示链接器,下面的代码放在原来的代码段中。
因为我们是加密敏感代码,而不是主程序代码,所以必须把它切换回去,要不然加密的时候主程序也被一起加密了,就没有负责解密的代码了。
#pragma comment(linker, “/SECTION:.SMC,ERW”) 是设置节表的属性。因为这个节表的数据是要被解密的,所以它必须具有可读写的属性;因为解密后这个节表中有代码,所以它必须具有可执行的属性。当然,这一步不是必须的,也可以在解密前调用VirtualProtect函数来修改内存属性。
一般写法
#pragma code_seg(".SMC")#include "关键的源代码.h"#pragma code_seg()#pragma comment(linker, "/SECTION:.SMC,ERW")
现在,你可以尝试调用Fun1() ,它是能准确无误的执行的。
解密我们的代码
现在来说说如何解密。
要解密我们首先要定位到镜像文件的载入基址。
GetModuleHandle(0);
然后定位到节表。
void SMC(char *pBuf,char *key){ // SMC 加密XX区段 const char *szSecName = ".SMC"; short nSec; PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNtHeader; PIMAGE_SECTION_HEADER pSec; pDosHeader=(PIMAGE_DOS_HEADER)pBuf; pNtHeader=(PIMAGE_NT_HEADERS)&pBuf[pDosHeader->e_lfanew]; nSec=pNtHeader->FileHeader.NumberOfSections; pSec=(PIMAGE_SECTION_HEADER)&pBuf[ sizeof(IMAGE_NT_HEADERS)+pDosHeader->e_lfanew]; for (int i=0;i<nSec;i++) { if (strcmp((char *)&pSec->Name,szSecName)==0) { int pack_size; char *packStart; pack_size=pSec->SizeOfRawData; packStart = &pBuf[pSec->VirtualAddress]; //VirtualProtect(packStart,pack_size,PAGE_EXECUTE_READWRITE,&old); xorPlus(packStart,pack_size,key,strlen(key)); //AfxMessageBox(_T("SMC解密成功。")); return; } pSec++; }}
首先通过对PE结构的解析找到第一个节表所在的地方,然后用strcmp对Name字段进行比较,如果Name字段的值=.SMC 就说明是被加密的代码块,然后取出VirtualAddress和SizeOfRawData调用xorPlus对节表.SMC进行解密。
void CTestDlg::OnBnClickedButton2(){ __try { Fun1(); } __except(1) { UnPack(KeyBuffer); //修正数据 AfxMessageBox(_T("Key不正确,请重新输入。")); }}
如果解密失败,Fun1() 一定会发生异常,主程序捕获这个异常并提示用户,就可以带到机器码检查的目的。
加密我们的敏感代码
读者可能已经注意到了,编译器肯定是没有加密功能的,所以只有我们自己写程序来加密。
原理:
打开PE文件->定位到节表->查找 .SMC 节表->加密.SMC节表
void SMC(HANDLE hFile,char *key){ // SMC 加密XX区段 HANDLE hMap; const char *szSecName = ".SMC"; char *pBuf; int size; short nSec; PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNtHeader; PIMAGE_SECTION_HEADER pSec; size = GetFileSize(hFile,0); hMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,size,NULL); if (hMap==INVALID_HANDLE_VALUE) {_viewf: AfxMessageBox(_T("映射失败")); return ; } pBuf=(char *)MapViewOfFile(hMap,FILE_MAP_WRITE|FILE_MAP_READ,0,0,size); if(!pBuf) goto _viewf; pDosHeader=(PIMAGE_DOS_HEADER)pBuf; pNtHeader=(PIMAGE_NT_HEADERS)&pBuf[pDosHeader->e_lfanew]; if (pNtHeader->Signature!=IMAGE_NT_SIGNATURE) { AfxMessageBox(_T("不是有效的win32 可执行文件")); goto _clean; } nSec=pNtHeader->FileHeader.NumberOfSections; pSec=(PIMAGE_SECTION_HEADER)&pBuf[ sizeof(IMAGE_NT_HEADERS)+pDosHeader->e_lfanew]; for (int i=0;i<nSec;i++) { if (strcmp((char *)&pSec->Name,szSecName)==0) { int pack_size; char *packStart; pack_size=pSec->SizeOfRawData; packStart = &pBuf[pSec->PointerToRawData]; xorPlus(packStart,pack_size,key,strlen(key)); AfxMessageBox(_T("SMC加密成功。")); goto _clean; } pSec++; } AfxMessageBox(_T("未找到 .SMC 段"));_clean: UnmapViewOfFile(pBuf); CloseHandle(hMap); return ;}
写在最后
vs2012编译的MFC工程的基址是变动,如果基址是变动的,程序每次在载入后都会进行重定位,敏感代码中的绝对地址就会被改变,因为改写的时候在解密代码之前。所以当解密后将会得到错误的结果。所以,这个技术不适用与基址会变得DLL中。
你需要这样配置:
源代码:
一个工程,两个项目,分别是:
SMC Pack SMC加密程序
Test 被加密的程序
使用VS2012编译
链接:http://pan.baidu.com/s/1kTvfWF1 密码:89wv
我的VS配色 O(∩_∩)O~
- VC实现SMC加密技术
- 用C/C++实现SMC动态代码加密技术
- 用C/C++实现SMC动态代码加密技术
- 用C/C++实现SMC动态代码加密技术
- 用C/C++实现SMC动态代码加密技术
- 用C/C++实现SMC动态代码加密技术
- 用C/C++实现SMC动态代码加密技术 .
- SMC技术
- 浅析SMC技术
- 浅析SMC技术
- SMC之抛砖引玉(VC++6.0)
- 浅谈SMC技术,值得路过
- C实现加密技术
- C实现加密技术
- vc++实现文件加密解密
- 在VC++实现数据加密
- 带壳破解SMC补丁技术
- VC实现托盘技术
- android笔记--处理started service的多次启动请求
- 汉诺塔
- 拷贝构造函数 -百度百科
- 移植Boa服务器到S3C2440
- java方面中,参数后面跟三个点(...)的含义---例如String...
- VC实现SMC加密技术
- pppoe抓包流程和拨号流程
- [Unity3D]如何渲染一个在camera frustum外面的物体
- DCT算法可以说是有损压缩的第一步,多用在视频压缩方面。
- Groovy入门教程
- Android两种常见错误(ANR和FC)解决办法
- C++文件读写详解(ofstream,ifstream,fstream)
- leetcode - Container With Most Water
- JAVA连接oracle数据库代码