可执行文件另类加密


layout: post
title: 可执行文件另类加密
categories: Windows
description: 可执行文件另类加密
keywords: PE 加壳
url: https://lichao890427.github.io/ https://github.com/lichao890427/


操作方法:给定A.exe进行保护

  • 1.使用生成工具去除A.exe所有段内容,例如
fileoff memoff segname
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此时可以运行
#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[header.SizeOfRawData];
        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[j] >> 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[j] & 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[2], "MAKE" ) )
    {       /* 生成注入文件 */
        char dir[MAX_PATH], newfile[MAX_PATH];
        strcpy( dir, __argv[1] );
        PathRemoveFileSpec( dir );
        strcpy( newfile, dir );
        strcat( newfile, "\\data" );
        CopyFile( __argv[1], newfile, FALSE );

        IMAGE_DOS_HEADER DosHeader;
        IMAGE_NT_HEADERS NtHeader;
        DWORD dwNumberOfBytesRead = 0;
        HANDLE hOldFile = CreateFile( __argv[1], 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[curHeader.SizeOfRawData];
        memset( newbuf, 0, curHeader.SizeOfRawData );
        WriteFile( hOldFile, newbuf, curHeader.SizeOfRawData, &dwNumberOfBytesRead, NULL );
        CloseHandle( hOldFile );
        delete[]newbuf;
    }else if ( !StrCmp( __argv[2], "RUN" ) )
    {       /* 运行文件 */
        char dir[MAX_PATH];
        strcpy( dir, __argv[1] );
        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[dwFileSize];
        memset( pInjectFileBuf, 0, dwFileSize );
        DWORD dwNumberOfBytesRead = 0;
        ReadFile( hNewFile, pInjectFileBuf, dwFileSize, &dwNumberOfBytesRead, NULL );
        CloseHandle( hNewFile );
        InjectProcess( __argv[1], pInjectFileBuf );
        delete[]pInjectFileBuf;
    }

用法:

  • 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的内存映射中,这样就可以正常运行了
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容