可执行文件另类加密
操作方法:给定A.exe进行保护1.使用生成工具去除A.exe所有段内容,例如
00000400 +123C00 .text
00124000 +042E00 .rdata
00166E00 +009000 .data
0016FE00 +00F200 .rsrc
0017F000 +01E200 .reloc
工具会把这些段指向的文件内容置0,生成Afix.exe,这个文件无法运行,因为已经挖空了
2.把A.exe用可逆算法加密成其他文件
3.用启动工具以挂起模式启动Afix.exe
4.将A.exe各个段加载到缓冲区中,对各个段进行重定位
5.将缓冲区中各个段内容动态填充到挂起的Afix.exe的各个段中
6.恢复Afix.exe此时可以运行
正在实现,正在研究,需要时间
期待楼主的成果。此外你考虑过64位没 Encrypt.exe
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#include <shlwapi.h>
#include <winternl.h>
#include <zlib.h>
#include <zconf.h>
#include <list>
using namespace std;
#pragma comment(lib,"shlwapi.lib")
class MySection
{//记录PE各个段数据
public:
IMAGE_SECTION_HEADER header;//段头
BYTE* data;//段数据
public:
MySection()
{
data=NULL;
memset(&header,0,sizeof(header));
}
void SetHeader(IMAGE_SECTION_HEADER& header)
{
memcpy(&this->header,&header,sizeof(IMAGE_SECTION_HEADER));
data=new BYTE;
memset(data,0,header.SizeOfRawData);
}
~MySection()
{
if(data)
{
delete []data;
data=NULL;
}
}
};
list<MySection> Sections;
BOOL InjectProcess(LPTSTR VictimFile,LPBYTE pInjectFileBuf)
{//VictimFile宿主文件 IndectFile注入文件(原始文件)
IMAGE_DOS_HEADER DosHeaders,DosHeadero;
IMAGE_NT_HEADERS NtHeaders,NtHeadero;
PROCESS_INFORMATION pi;
STARTUPINFO si;
CONTEXT context;
PVOID ImageBase;
SIZE_T BaseAddr;
LONG offset;
DWORD dwBytes;
HMODULE hNtDll=GetModuleHandle("ntdll.dll");
if(!hNtDll)
return FALSE;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
CopyMemory((void*)&DosHeadero,pInjectFileBuf,sizeof(IMAGE_DOS_HEADER));
CopyMemory((void*)&NtHeadero,pInjectFileBuf+DosHeadero.e_lfanew,sizeof(IMAGE_NT_HEADERS));
//检查PE结构
//以挂起方式进程
BOOL res = CreateProcess(NULL,VictimFile,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,&pi);
if (res)
{
context.ContextFlags = CONTEXT_FULL;
if (!GetThreadContext(pi.hThread,&context)) //如果调用失败
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return FALSE;
}
ReadProcessMemory(pi.hProcess,(void *)(context.Ebx + 8),&BaseAddr,sizeof(unsigned long),NULL);
if (!BaseAddr)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return FALSE;
}
//计算FS的基址
LDT_ENTRY SelEntry;
PTEB pteb = new TEB;
PPEB ppeb = new PEB;
GetThreadSelectorEntry(pi.hThread, context.SegFs, &SelEntry);
DWORD dwFSBase = ( SelEntry.HighWord.Bits.BaseHi << 24) | (SelEntry.HighWord.Bits.BaseMid << 16) | SelEntry.BaseLow;
ReadProcessMemory( pi.hProcess, (LPCVOID)dwFSBase, pteb, sizeof(TEB), &dwBytes);
ReadProcessMemory( pi.hProcess, (LPCVOID)*(DWORD*)((BYTE*)pteb+0x30), ppeb, sizeof(PEB), &dwBytes);//pteb->Peb
ImageBase = *(PVOID*)((BYTE*)ppeb+0x08);//ppeb->ImageBaseAddress;
ReadProcessMemory(pi.hProcess,ImageBase,&DosHeaders,sizeof(IMAGE_DOS_HEADER),&dwBytes);
ReadProcessMemory(pi.hProcess,(LPVOID)((BYTE*)ImageBase+DosHeaders.e_lfanew),&NtHeaders,sizeof(IMAGE_NT_HEADERS),&dwBytes);
delete pteb;
delete ppeb;
offset = DosHeaders.e_lfanew + sizeof(IMAGE_NT_HEADERS);
IMAGE_SECTION_HEADER curHeader;//.text和.reloc的信息
WORD i = 0;
for(i=0; i < NtHeaders.FileHeader.NumberOfSections; i++)
{
MySection section;
ReadProcessMemory(pi.hProcess,(LPVOID)((BYTE*)ImageBase+offset+i*sizeof(IMAGE_SECTION_HEADER)),(void *)&curHeader,sizeof(IMAGE_SECTION_HEADER),&dwBytes);
//下面四行代码获取各个段信息
//.reloc段在CreateProcess后就已经被系统重定向应用到各个段里去了,如果要自己处理,就要取出这个段,并自己应用reloc
curHeader.SizeOfRawData=curHeader.Misc.VirtualSize;//用SizeOfRawData在写入的时候会发生堆溢出,目前不知道原因
section.SetHeader(curHeader);
CopyMemory(section.data,pInjectFileBuf+curHeader.PointerToRawData,curHeader.SizeOfRawData);
Sections.push_back(section);
if(!StrCmp((char*)curHeader.Name,".reloc"))//确保reloc是最后一个段
{//实现重定位
BYTE* relocdata=section.data;
IMAGE_BASE_RELOCATION CurReloc;
CopyMemory((void*)&CurReloc,relocdata,sizeof(CurReloc));
DWORD offset=0;
while(CurReloc.VirtualAddress)
{
int num=(CurReloc.SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/2;
WORD* pData=(WORD*)(relocdata+sizeof(IMAGE_BASE_RELOCATION)+offset);
for(int j=0;j<num;j++)
{
switch(pData>>12)
{
case IMAGE_REL_BASED_ABSOLUTE://什么都不做
break;
case IMAGE_REL_BASED_HIGHLOW:
{
list<MySection>::iterator itor=Sections.begin();
while(itor != Sections.end())
{
int inneroffset=CurReloc.VirtualAddress+(pData&0xFFF)-(*itor).header.VirtualAddress;
if(inneroffset >= 0 && inneroffset <= (*itor).header.SizeOfRawData)
{
*(DWORD*)((*itor).data+inneroffset) += NtHeaders.OptionalHeader.ImageBase - NtHeadero.OptionalHeader.ImageBase;
break;
}
++itor;
}
}
break;
default:
printf("unknown!!!!!!!!!!!!!!");
break;
}
}
offset+=CurReloc.SizeOfBlock;
CopyMemory((void*)&CurReloc,relocdata+offset,sizeof(CurReloc));
}
}
section.data=NULL;//浅拷贝防止析构
}
list<MySection>::iterator itor=Sections.begin();
while(itor != Sections.end())
{
//有些段会因为没有写入权限失败
WriteProcessMemory(pi.hProcess,(LPVOID)((DWORD)ImageBase + (*itor).header.VirtualAddress),(*itor).data,(*itor).header.SizeOfRawData,&dwBytes);
if(!StrCmp((char*)(*itor).header.Name,".text"))
{
break;
}
++itor;
}
ResumeThread(pi.hThread);
}
return TRUE;
}
void main()
{
if(__argc < 3)//文件名+MAKE 文件名+RUN
{
return;
}
if(!StrCmp(__argv,"MAKE"))
{//生成注入文件
char dir,newfile;
strcpy(dir,__argv);
PathRemoveFileSpec(dir);
strcpy(newfile,dir);
strcat(newfile,"\\data");
CopyFile(__argv,newfile,FALSE);
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS NtHeader;
DWORD dwNumberOfBytesRead = 0;
HANDLE hOldFile = CreateFile(__argv,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hOldFile == INVALID_HANDLE_VALUE)
{
return;
}
SetFilePointer(hOldFile,0,NULL,FILE_BEGIN);
ReadFile(hOldFile,&DosHeader,sizeof(DosHeader),&dwNumberOfBytesRead,NULL);
SetFilePointer(hOldFile,DosHeader.e_lfanew,NULL,FILE_BEGIN);
ReadFile(hOldFile,&NtHeader,sizeof(NtHeader),&dwNumberOfBytesRead,NULL);
IMAGE_SECTION_HEADER curHeader;//.text和.reloc的信息
WORD i = 0;
for(i=0; i < NtHeader.FileHeader.NumberOfSections; i++)
{
ReadFile(hOldFile,&curHeader,sizeof(curHeader),&dwNumberOfBytesRead,NULL);
if(!StrCmp((char*)curHeader.Name,".text"))
{
break;
}
}
SetFilePointer(hOldFile,curHeader.PointerToRawData,NULL,FILE_BEGIN);
BYTE* newbuf=new BYTE;
memset(newbuf,0,curHeader.SizeOfRawData);
WriteFile(hOldFile,newbuf,curHeader.SizeOfRawData,&dwNumberOfBytesRead,NULL);
CloseHandle(hOldFile);
delete []newbuf;
}
else if(!StrCmp(__argv,"RUN"))
{//运行文件
char dir;
strcpy(dir,__argv);
PathRemoveFileSpec(dir);
strcat(dir,"\\data");
HANDLE hNewFile = CreateFile(dir,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hNewFile == INVALID_HANDLE_VALUE)
{
return;
}
DWORD dwFileSize = GetFileSize(hNewFile, NULL);
LPBYTE pInjectFileBuf = new BYTE;
memset(pInjectFileBuf, 0, dwFileSize);
DWORD dwNumberOfBytesRead = 0;
ReadFile(hNewFile,pInjectFileBuf,dwFileSize,&dwNumberOfBytesRead,NULL);
CloseHandle(hNewFile);
InjectProcess(__argv,pInjectFileBuf);
delete []pInjectFileBuf;
}
}
虽然只有250行代码,但是这250行代码研究了我3天!!!
用法:
①Encrypt "D:\Program Files\Thunder Network\Thunder\Program\Thunder.exe" MAKE
执行后会将Thunder.exe的.text掏空,使原始文件无法运行,另外将Thunder.exe拷贝一份到同目录下的data文件,这个我没做加密处理,不过相加还是能加的
②Encrypt "D:\Program Files\Thunder Network\Thunder\Program\Thunder.exe" RUN
将被掏空代码的Thunder.exe以挂起模式运行,之后将data文件中正常数据,经过reloc手工修正各个段后填回Thunder.exe的内存映射中,这样就可以正常运行了。 目前只测试了2个程序,不知道有没有其他bug 嗯 嗯 你既然把加密的原理都贴出来了,你就不怕别人看穿了你的原理?
没用的,因为地址是随机的,很多都是随机的,除非逆向每一个程序。这就像公钥算法,大家都知道他的算法,但是解不了密
页:
[1]