From a8c82c0f3fc037a7826b83d959ad72129c75bba3 Mon Sep 17 00:00:00 2001 From: JorySeverijnse Date: Sat, 13 Dec 2025 14:02:33 +0100 Subject: [PATCH] Use pefile.cpp from stealthy branch --- src/pefile.cpp | 95 ++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 57 deletions(-) diff --git a/src/pefile.cpp b/src/pefile.cpp index 8a007efb..f2ce84a3 100644 --- a/src/pefile.cpp +++ b/src/pefile.cpp @@ -945,16 +945,22 @@ public: void PeFile::addKernelImport(const char *name) { ilinker->add_import(kernelDll(), name); } void PeFile::addStubImports() { + // Break UPX detection by ensuring import count doesn't match 2-6 pattern + addKernelImport("LoadLibraryA"); addKernelImport("VirtualProtect"); addKernelImport("GetProcAddress"); - addKernelImport("LoadLibraryA"); - if (!isdll) - addKernelImport("ExitProcess"); - // Added benign imports to increase import count and diversify pattern - addKernelImport("Sleep"); - addKernelImport("GetCurrentProcess"); - addKernelImport("GetCommandLineA"); - addKernelImport("GetModuleFileNameA"); + if (!isdll) { + // For EXEs: add extra imports to push count beyond 6 (breaks detection pattern) + addKernelImport("GetCurrentProcess"); + addKernelImport("GetTickCount"); + addKernelImport("QueryPerformanceCounter"); + addKernelImport("GetSystemTimeAsFileTime"); + addKernelImport("ExitProcess"); // Add last to avoid specific 2-4-6 patterns + } else { + // For DLLs: add minimal extra imports to break patterns + addKernelImport("GetCurrentProcess"); + addKernelImport("GetTickCount"); + } } void PeFile::processImports2(unsigned myimport, unsigned) { // pass 2 @@ -1429,7 +1435,6 @@ void PeFile::processTls1(Interval *iv, typename tls_traits::cb_value_t ima info("TLS: %u callback(s) found, adding TLS callback handler", num_callbacks); // set flag to include necessary sections in loader use_tls_callbacks = true; - use_tls_callbacks = false; // Force disable UPX's custom TLS handler // define linker symbols tlscb_ptr = tlsp->callbacks; } @@ -2483,9 +2488,9 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, const bool has_oxrelocs = !opt->win32_pe.strip_relocs && (use_stub_relocs || sotls || loadconfiv.ivnum); const bool has_ncsection = has_oxrelocs || soimpdlls || soexport || soresources; - const unsigned oobjs = 7; + const unsigned oobjs = last_section_rsrc_only ? 4 : has_ncsection ? 3 : 2; ////pe_section_t osection[oobjs]; - pe_section_t osection[8]; + pe_section_t osection[4]; memset(osection, 0, sizeof(osection)); // section 0 : bss // 1 : [ident + header] + packed_data + unpacker + tls + loadconf @@ -2527,10 +2532,19 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, memcpy(&oh, &ih, sizeof(oh)); oh.filealign = oh_filealign; // identsplit depends on this - oh.entry = upxsection; + // Modify timestamp to break compilation date detection + // Timestamp is at offset 8 in the PE header (after magic and machine) + set_le32((byte *) &oh + 8, 0x12345678); + + oh.entry = upxsection; // Revert entry point randomization oh.objects = oobjs; oh.chksum = 0; + // Modify PE characteristics flags to break detection patterns + // Flags are at offset 22 in PE header + LE16 *flags = (LE16 *) ((byte *) &oh + 22); + *flags |= 0x0100; // Add IMAGE_FILE_RELOCS_STRIPPED flag + // fill the data directory ODADDR(PEDIR_DEBUG) = 0; // dbgCET later ODSIZE(PEDIR_DEBUG) = 0; @@ -2625,75 +2639,38 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, strcpy(osection[2].name, ".rsrc"); osection[2].name[5] = 0; - // Add new dummy sections for diversification - strcpy(osection[3].name, ".idata"); - osection[3].name[6] = 0; - strcpy(osection[4].name, ".rdata"); - osection[4].name[6] = 0; - strcpy(osection[5].name, ".reloc"); - osection[5].name[6] = 0; - strcpy(osection[6].name, ".debug"); // Another common section - osection[6].name[6] = 0; - osection[0].vaddr = rvamin; osection[1].vaddr = s1addr; osection[2].vaddr = ncsection; - // Set vaddr for new dummy sections incrementally - osection[3].vaddr = (osection[2].vaddr + osection[2].vsize + oam1) & ~oam1; // After .rsrc - osection[4].vaddr = (osection[3].vaddr + osection[3].vsize + oam1) & ~oam1; // After .idata - osection[5].vaddr = (osection[4].vaddr + osection[4].vsize + oam1) & ~oam1; // After .rdata - osection[6].vaddr = (osection[5].vaddr + osection[5].vsize + oam1) & ~oam1; // After .reloc osection[0].size = 0; osection[1].size = (s1size + fam1) & ~fam1; osection[2].size = (ncsize + fam1) & ~fam1; - // Set sizes for new dummy sections - osection[3].size = (fam1 + 0x1000) & ~fam1; // Example small size - osection[4].size = (fam1 + 0x1000) & ~fam1; - osection[5].size = (fam1 + 0x1000) & ~fam1; - osection[6].size = (fam1 + 0x1000) & ~fam1; + + // Removed section size randomization to maintain DLL functionality osection[0].vsize = osection[1].vaddr - osection[0].vaddr; if (!last_section_rsrc_only) { osection[1].vsize = (osection[1].size + oam1) & ~oam1; osection[2].vsize = (osection[2].size + ncsize_virt_increase + oam1) & ~oam1; - // Set vsizes for new dummy sections - osection[3].vsize = (osection[3].size + oam1) & ~oam1; - osection[4].vsize = (osection[4].size + oam1) & ~oam1; - osection[5].vsize = (osection[5].size + oam1) & ~oam1; - osection[6].vsize = (osection[6].size + oam1) & ~oam1; - - oh.imagesize = (osection[6].vaddr + osection[6].vsize + oam1) & ~oam1; // Update total image size + oh.imagesize = osection[2].vaddr + osection[2].vsize; osection[0].rawdataptr = (pe_offset + sizeof(ht) + sizeof_osection + fam1) & ~(size_t) fam1; osection[1].rawdataptr = osection[0].rawdataptr; } else { osection[1].vsize = osection[1].size; osection[2].vsize = osection[2].size; - // Set vsizes for new dummy sections (if last_section_rsrc_only) - osection[3].vsize = osection[3].size; - osection[4].vsize = osection[4].size; - osection[5].vsize = osection[5].size; - osection[6].vsize = osection[6].size; osection[0].rawdataptr = 0; osection[1].rawdataptr = (pe_offset + sizeof(ht) + sizeof_osection + fam1) & ~(size_t) fam1; } osection[2].rawdataptr = osection[1].rawdataptr + osection[1].size; - // Set rawdataptr for new dummy sections - osection[3].rawdataptr = osection[2].rawdataptr + osection[2].size; - osection[4].rawdataptr = osection[3].rawdataptr + osection[3].size; - osection[5].rawdataptr = osection[4].rawdataptr + osection[4].size; - osection[6].rawdataptr = osection[5].rawdataptr + osection[5].size; + // Modify section flags to break UPX detection patterns osection[0].flags = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | - IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE; + IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; osection[1].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | - IMAGE_SCN_MEM_EXECUTE; - osection[2].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; - // Set flags for new dummy sections - osection[3].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; // .idata - osection[4].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; // .rdata - osection[5].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; // .reloc - osection[6].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; // .debug + IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_INITIALIZED_DATA; + osection[2].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | + IMAGE_SCN_CNT_CODE; if (last_section_rsrc_only) { strcpy(osection[3].name, ".rsrc"); @@ -2724,6 +2701,8 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, if (opt->win32_pe.strip_relocs) oh.flags |= IMAGE_FILE_RELOCS_STRIPPED; + oh.chksum = 0; // Revert checksum to zero + ibuf.clear(0, oh.filealign); info("Image size change: %u -> %u KiB", ih.imagesize / 1024, oh.imagesize / 1024); @@ -2751,6 +2730,8 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, fo->write(ibuf, sizeof(LEXX) - ic); fo->write(otls, aligned_sotls); fo->write(oloadconf, soloadconf); + + // Removed random padding to maintain DLL functionality if (dbgCET) { ic = fo->getBytesWritten(); dbgCET->fpos = ic + sizeof(*dbgCET);