元始天尊 发表于 2014-4-20 18:00:38

可执行文件另类加密

操作方法:给定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此时可以运行

正在实现,正在研究,需要时间

0xAA55 发表于 2014-4-22 08:01:48

期待楼主的成果。此外你考虑过64位没

元始天尊 发表于 2014-4-22 14:44:40

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的内存映射中,这样就可以正常运行了。

元始天尊 发表于 2014-4-22 14:45:50

目前只测试了2个程序,不知道有没有其他bug

0xAA55 发表于 2014-5-3 14:00:01

0xAA55 发表于 2014-5-3 14:00:04

0xAA55 发表于 2014-5-3 14:08:32

你既然把加密的原理都贴出来了,你就不怕别人看穿了你的原理?
没用的,因为地址是随机的,很多都是随机的,除非逆向每一个程序。这就像公钥算法,大家都知道他的算法,但是解不了密
页: [1]
查看完整版本: 可执行文件另类加密