1. 程式人生 > 實用技巧 >加殼:掛起方式建立程序

加殼:掛起方式建立程序

寫入部分

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會掛