• 加壳:挂起方式创建进程


    写入部分

    1,壳文件新增一个节
    2,源文件与Harmonica异或
    3,加密后源文件放入新增节中
    4,存盘
    VOID Shell(WCHAR* shellName, WCHAR* srcName) {
        FILE* fpShell;
        FILE* fpSrc;
        _wfopen_s(&fpShell, shellName, L"rb");
        _wfopen_s(&fpSrc, srcName, L"rb");
        if (fpShell == NULL||fpSrc==NULL) {
            MessageBox(0, L"can't open file", 0, MB_OK);
            return;
        }
        fseek(fpShell, 0, SEEK_END);
        int shellLen = ftell(fpShell);
        fseek(fpShell, 0, SEEK_SET);
        fseek(fpSrc, 0, SEEK_END);
        int srcLen = ftell(fpSrc);
        fseek(fpSrc, 0, SEEK_SET);
        CHAR* shellBuffer = (CHAR*)malloc(2 * (shellLen + srcLen));
        if (shellBuffer != NULL) {
            memset(shellBuffer, 'x00', 2 * (shellLen + srcLen));
            fread(shellBuffer, shellLen , 1, fpShell);
        }
        else {
            return;
        }
        fclose(fpShell);
        CHAR* srcBuffer = (CHAR*)malloc(srcLen);
        if (srcBuffer != NULL) {
            memset(srcBuffer, 'x00', srcLen);
            fread(srcBuffer, srcLen, 1, fpSrc);
        }
        else {
            free(shellBuffer);
            shellBuffer = NULL;
            return;
        }
        fclose(fpSrc);
    
        DWORD e_lfanew = *(DWORD*)(shellBuffer + 0x3c);
        CHAR* peHeader = shellBuffer + e_lfanew + 0x4;
        CHAR* opHeader = peHeader + 0x14;
        DWORD SectionAlignment = *(DWORD*)(opHeader + 0x20);
        DWORD SizeOfImage = *(DWORD*)(opHeader + 0x38);
        *(DWORD*)(opHeader + 0x38) = SizeOfImage + (srcLen / SectionAlignment + 1) * SectionAlignment;
        SizeOfImage = *(DWORD*)(opHeader + 0x38);
        DWORD SizeoOfHeaders = *(DWORD*)(opHeader + 0x3c);
        WORD NumberOfSections = *(WORD*)(peHeader + 0x2);
        *(WORD*)(peHeader + 0x2) = NumberOfSections + 1;
        WORD SizeOfOptionalHeader = *(WORD*)(peHeader + 0x10);
        CHAR* Sections_addr = opHeader + SizeOfOptionalHeader;
    
        DWORD Misc;
        DWORD VirtualAddress;
        DWORD SizeOfRawData;
        DWORD PointerToRawData;
        for (DWORD j = 0; j < NumberOfSections; j++) {
            Misc = *(DWORD*)(Sections_addr + 0x8);
            VirtualAddress = *(DWORD*)(Sections_addr + 0xc);
            SizeOfRawData = *(DWORD*)(Sections_addr + 0x10);
            PointerToRawData = *(DWORD*)(Sections_addr + 0x14);
            Sections_addr = Sections_addr + 0x28;
        }
        DWORD check = SizeoOfHeaders - (Sections_addr - shellBuffer);
        if (check < 0x50) {//太小了无法新增节
            free(shellBuffer);
            shellBuffer = NULL;
            free(srcBuffer);
            srcBuffer = NULL;
            return;
        }
    
        DWORD newSec_addr = VirtualAddress + SectionAlignment;
        DWORD newSec_PointerToRawData = PointerToRawData + SizeOfRawData;
        *(DWORD64*)Sections_addr = 0x000000007261482e;
        *(DWORD*)(Sections_addr + 0x8) = srcLen;
        *(DWORD*)(Sections_addr + 0xc) = newSec_addr;
        *(DWORD*)(Sections_addr + 0x10) = (srcLen / SectionAlignment + 1) * SectionAlignment;
        *(DWORD*)(Sections_addr + 0x14) = newSec_PointerToRawData;
        *(DWORD*)(Sections_addr + 0x24) = 0xC0000040;
    
        UCHAR key[9] = { 0x48,0x61,0x72,0x6d,0x6f,0x6e,0x69,0x63,0x61 };
        for (DWORD i = 0; i < srcLen; i++) {
            *(UCHAR*)(shellBuffer + newSec_PointerToRawData + i) = *(UCHAR*)(srcBuffer + i) ^ key[i % 9];
        }
    
        FILE* fpout;
        WCHAR fileName[256] = { 0 };
        wcscpy(fileName, srcName);
        WCHAR* tmp = wcsstr(fileName, L".exe");
        wcscpy(tmp, L"_shell.exe");
        _wfopen_s(&fpout, fileName, L"wb");
        if (fpout == NULL) {
            free(shellBuffer);
            shellBuffer = NULL;
            free(srcBuffer);
            srcBuffer = NULL;
            return;
        }
        fwrite(shellBuffer, (srcLen / SectionAlignment + 1) * SectionAlignment + newSec_PointerToRawData, 1, fpout);
        
        fclose(fpout);
        free(shellBuffer);
        shellBuffer = NULL;
        free(srcBuffer);
        srcBuffer = NULL;
        MessageBox(0, L"加壳成功", L"", MB_OK);
    }

    壳部分

    1,解密源文件
    2,拉伸源文件
    3,以挂起方式创建进程,获取进程信息
    4,强制卸载进程模块
    5,在进程内分配空间
    6,修复重定位表
    7,源文件写入进程
    8,修复Imagebase和oep
    9,恢复进程
    #define _CRT_SECURE_NO_WARNINGS
    #include <windows.h>
    
    CONTEXT cs;
    CHAR* SrcBuffer;            //
    CHAR* ImageBuffer;            //拉伸后的源文件
    DWORD SizeOfImage;
    DWORD ImageBase;
    DWORD OEP;
    
    LPVOID lp;                    //VirtualAllocEx返回的地址
    BOOL HasReloc = FALSE;
    
    
    BOOL UnloadShell(HANDLE ProcHnd, unsigned long BaseAddr)
    {
        typedef unsigned long(__stdcall* pfZwUnmapViewOfSection)(unsigned long, unsigned long);
        pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;
        BOOL res = FALSE;
        HMODULE m = LoadLibraryA("ntdll.dll");
        if (m) {
                ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection");
                if (ZwUnmapViewOfSection)
                    res = (ZwUnmapViewOfSection((unsigned long)ProcHnd, BaseAddr) == 0);
                FreeLibrary(m);
        }
        return res;
    }
    
    BOOL DecodeSrc(HANDLE hShellModule) {
        //解密源程序
        CHAR* lpShellModule = (CHAR*)hShellModule;
        DWORD e_lfanew = *(DWORD*)(lpShellModule + 0x3c);
        CHAR* peHeader = lpShellModule + e_lfanew + 0x4;
        CHAR* opHeader = peHeader + 0x14;
        WORD NumberOfSections = *(WORD*)(peHeader + 0x2);
        WORD SizeOfOptionalHeader = *(WORD*)(peHeader + 0x10);
        CHAR* Sections_addr = opHeader + SizeOfOptionalHeader;
        DWORD Misc;
        DWORD VirtualAddress;
        DWORD SizeOfRawData;
        DWORD PointerToRawData;
        for (DWORD j = 0; j < NumberOfSections - 1; j++) {
            Sections_addr = Sections_addr + 0x28;
        }
    
        if (*(DWORD64*)Sections_addr != 0x000000007261482e) {
            return FALSE;
        }
    
        UCHAR key[9] = { 0x48,0x61,0x72,0x6d,0x6f,0x6e,0x69,0x63,0x61 };
        DWORD srcLen = *(DWORD*)(Sections_addr + 0x8);
        CHAR* lpSrc = lpShellModule + *(DWORD*)(Sections_addr + 0xc);
        SrcBuffer = (CHAR*)malloc(srcLen + 1);
        if (SrcBuffer != NULL) {
            memset(SrcBuffer, 'x00', srcLen + 1);
            for (DWORD i = 0; i < srcLen; i++) {
                *(SrcBuffer + i) = *(lpSrc + i) ^ key[i % 9];
            }
        }
        else {
            return FALSE;
        }
        return TRUE;
    }
    
    BOOL ExtendSrc() {
        WORD peCheck = *(WORD*)(SrcBuffer);
        if (peCheck != 0x5A4D) {
            return FALSE;
        }
        DWORD e_lfanew = *(DWORD*)(SrcBuffer + 0x3c);
        CHAR* peHeader = SrcBuffer + e_lfanew + 0x4;
        CHAR* opHeader = peHeader + 0x14;
        DWORD SectionAlignment = *(DWORD*)(opHeader + 0x20);
        SizeOfImage = *(DWORD*)(opHeader + 0x38);
        ImageBase = *(DWORD*)(opHeader + 0x1c);
        OEP = *(DWORD*)(opHeader + 0x10);
        if (*(DWORD*)(opHeader + 0x60 + 0x28) != NULL) {
            HasReloc = TRUE;
        }
        DWORD SizeoOfHeaders = *(DWORD*)(opHeader + 0x3c);
        WORD NumberOfSections = *(WORD*)(peHeader + 0x2);
        WORD SizeOfOptionalHeader = *(WORD*)(peHeader + 0x10);
        CHAR* Sections_addr = opHeader + SizeOfOptionalHeader;
        
        ImageBuffer = (CHAR*)malloc(SizeOfImage + 1);
        if (ImageBuffer == NULL) {
            return FALSE;
        }
        else {
            memset(ImageBuffer, 'x00', SizeOfImage + 1);
        }
        memcpy(ImageBuffer, SrcBuffer, SizeoOfHeaders);
        
        DWORD Misc;
        DWORD VirtualAddress;
        DWORD SizeOfRawData;
        DWORD PointerToRawData;
        for (DWORD j = 0; j < NumberOfSections; j++) {
            Misc = *(DWORD*)(Sections_addr + 0x8);
            VirtualAddress = *(DWORD*)(Sections_addr + 0xc);
            SizeOfRawData = *(DWORD*)(Sections_addr + 0x10);
            PointerToRawData = *(DWORD*)(Sections_addr + 0x14);
            if (SizeOfRawData == NULL) {
                Sections_addr = Sections_addr + 0x28;
                continue;
            }
            if (Misc > SizeOfRawData) {
                memcpy(ImageBuffer + VirtualAddress, SrcBuffer + PointerToRawData, Misc);
            }
            else {
                memcpy(ImageBuffer + VirtualAddress, SrcBuffer + PointerToRawData, SizeOfRawData);
            }
            Sections_addr = Sections_addr + 0x28;
        }
        free(SrcBuffer);
        SrcBuffer = NULL;
        return TRUE;
    }
    
    VOID repairReloc(DWORD newAddr) {
        DWORD e_lfanew = *(DWORD*)(ImageBuffer + 0x3c);
        CHAR* peHeader = ImageBuffer + e_lfanew + 0x4;
        CHAR* opHeader = peHeader + 0x14;
        DWORD relocRVA = *(DWORD*)(opHeader + 0x60 + 0x28);
        
        CHAR* addr = ImageBuffer + relocRVA;
        CHAR* size = addr + 4;
        CHAR* data = size + 4;
        while (*(DWORD*)addr != 0 && *(DWORD*)size != 0) {
            DWORD num = (*(DWORD*)size - 8) / 2;
            for (DWORD i = 0; i < num; i++) {
                WORD Characteristics = (*(WORD*)data & 0xf000) >> 12;
                WORD offset = *(WORD*)data & 0x0fff;
                if (Characteristics == 0x3) {
                    DWORD NewData = *(DWORD*)(ImageBuffer + *(DWORD*)addr + offset) - ImageBase + newAddr;
                    *(DWORD*)(ImageBuffer + *(DWORD*)addr + offset) = NewData;
                }
                data += 2;
            }
            addr += *(DWORD*)size;
            size = addr + 4;
            data = size + 4;
        }
    }
    
    BOOL MyAlloc(HANDLE p) {
        lp = VirtualAllocEx(p, (VOID*)ImageBase, SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (lp == NULL) {
            if (HasReloc) {
                lp = VirtualAllocEx(p, NULL, SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                if (lp == NULL) {
                    return FALSE;
                }
                repairReloc((DWORD)lp);
            }
            else
            {
                return FALSE;
            }
        }
        return TRUE;
    }
    
    int main()
    {
        LPWSTR fileName;
        fileName = GetCommandLineW();
        HANDLE hShellProcess = GetCurrentProcess();
        HANDLE hShellModule = GetModuleHandleW(NULL);
        cs.ContextFlags = CONTEXT_FULL;
    
        //解密源文件
        BOOL isDecode = DecodeSrc(hShellModule);
        if (isDecode == FALSE) {
            return 0;
        }
        //拉伸源文件
        BOOL isExtend = ExtendSrc();
        if (isExtend == FALSE) {
            free(SrcBuffer);
            SrcBuffer = NULL;
        //    return 0;
        }
    
        //以挂起方式创建进程
        STARTUPINFO s = { 0 };
        s.cb = sizeof(STARTUPINFO);
        PROCESS_INFORMATION p;
        ::CreateProcess(
            NULL,
            fileName,
            NULL, NULL,
            FALSE,
            CREATE_SUSPENDED,
            NULL, NULL,
            &s, &p);
        //获取进程信息
        GetThreadContext(p.hThread, &cs);
        DWORD shellOEP = cs.Eax;
        CHAR* baseAddress = (CHAR*)cs.Ebx + 8;
        TCHAR szBuffer[4] = { 0 };
        ReadProcessMemory(p.hProcess, baseAddress, szBuffer, 4, NULL);
        DWORD shellImageBase = *(DWORD*)szBuffer;
    
        //卸载模块
        BOOL UnloadCheck = UnloadShell(p.hProcess, shellImageBase);
        if (UnloadCheck == FALSE) {
            free(ImageBuffer);
            ImageBuffer = NULL;
            ::TerminateProcess(p.hProcess, 0);
            return 0;
        }
    
        //分配空间
        BOOL allocCheck = MyAlloc(p.hProcess);
        if (allocCheck == FALSE) {
            free(ImageBuffer);
            ImageBuffer = NULL;
            ::TerminateProcess(p.hProcess, 0);
            return 0;
        }
    
        BOOL writeCheck = WriteProcessMemory(p.hProcess, lp, ImageBuffer, SizeOfImage, NULL);
        if (writeCheck == FALSE) {
            free(ImageBuffer);
            ImageBuffer = NULL;
            ::TerminateProcess(p.hProcess, 0);
            return 0;
        }
    
        //更改Imagebase和oep
        WriteProcessMemory(p.hProcess, (LPVOID)(cs.Ebx + 8), &lp, sizeof(DWORD), NULL);
        cs.Eax = (DWORD)lp + OEP;
        SetThreadContext(p.hThread, &cs);
        //::TerminateProcess(p.hProcess, 0);
        ::ResumeThread(p.hThread);
        ::CloseHandle(p.hProcess);
        
        return 0;
    
    }

    因为我没修复IAT表,使用API会挂

  • 相关阅读:
    struts2 标签
    Ubutu命令 笔记积累
    虚拟机VirtualBox和Ubutu
    更新PostgreSQL数据
    向PostgreSQL插入数据
    PostgreSQL表依赖性跟踪
    PostgreSQL外部数据
    PostgreSQL分区介绍
    PostgreSQL继承详解
    PostgreSQL模式介绍
  • 原文地址:https://www.cnblogs.com/harmonica11/p/14127146.html
Copyright © 2020-2023  润新知