加壳:挂起方式创建进程

写入部分

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会挂

原文地址:https://www.cnblogs.com/harmonica11/p/14127146.html