Use pefile.cpp from stealthy branch
This commit is contained in:
+37
-56
@@ -945,16 +945,22 @@ public:
|
|||||||
void PeFile::addKernelImport(const char *name) { ilinker->add_import(kernelDll(), name); }
|
void PeFile::addKernelImport(const char *name) { ilinker->add_import(kernelDll(), name); }
|
||||||
|
|
||||||
void PeFile::addStubImports() {
|
void PeFile::addStubImports() {
|
||||||
|
// Break UPX detection by ensuring import count doesn't match 2-6 pattern
|
||||||
|
addKernelImport("LoadLibraryA");
|
||||||
addKernelImport("VirtualProtect");
|
addKernelImport("VirtualProtect");
|
||||||
addKernelImport("GetProcAddress");
|
addKernelImport("GetProcAddress");
|
||||||
addKernelImport("LoadLibraryA");
|
if (!isdll) {
|
||||||
if (!isdll)
|
// For EXEs: add extra imports to push count beyond 6 (breaks detection pattern)
|
||||||
addKernelImport("ExitProcess");
|
|
||||||
// Added benign imports to increase import count and diversify pattern
|
|
||||||
addKernelImport("Sleep");
|
|
||||||
addKernelImport("GetCurrentProcess");
|
addKernelImport("GetCurrentProcess");
|
||||||
addKernelImport("GetCommandLineA");
|
addKernelImport("GetTickCount");
|
||||||
addKernelImport("GetModuleFileNameA");
|
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
|
void PeFile::processImports2(unsigned myimport, unsigned) { // pass 2
|
||||||
@@ -1429,7 +1435,6 @@ void PeFile::processTls1(Interval *iv, typename tls_traits<LEXX>::cb_value_t ima
|
|||||||
info("TLS: %u callback(s) found, adding TLS callback handler", num_callbacks);
|
info("TLS: %u callback(s) found, adding TLS callback handler", num_callbacks);
|
||||||
// set flag to include necessary sections in loader
|
// set flag to include necessary sections in loader
|
||||||
use_tls_callbacks = true;
|
use_tls_callbacks = true;
|
||||||
use_tls_callbacks = false; // Force disable UPX's custom TLS handler
|
|
||||||
// define linker symbols
|
// define linker symbols
|
||||||
tlscb_ptr = tlsp->callbacks;
|
tlscb_ptr = tlsp->callbacks;
|
||||||
}
|
}
|
||||||
@@ -2483,9 +2488,9 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
|
|||||||
const bool has_oxrelocs =
|
const bool has_oxrelocs =
|
||||||
!opt->win32_pe.strip_relocs && (use_stub_relocs || sotls || loadconfiv.ivnum);
|
!opt->win32_pe.strip_relocs && (use_stub_relocs || sotls || loadconfiv.ivnum);
|
||||||
const bool has_ncsection = has_oxrelocs || soimpdlls || soexport || soresources;
|
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[oobjs];
|
||||||
pe_section_t osection[8];
|
pe_section_t osection[4];
|
||||||
memset(osection, 0, sizeof(osection));
|
memset(osection, 0, sizeof(osection));
|
||||||
// section 0 : bss
|
// section 0 : bss
|
||||||
// 1 : [ident + header] + packed_data + unpacker + tls + loadconf
|
// 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));
|
memcpy(&oh, &ih, sizeof(oh));
|
||||||
oh.filealign = oh_filealign; // identsplit depends on this
|
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.objects = oobjs;
|
||||||
oh.chksum = 0;
|
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
|
// fill the data directory
|
||||||
ODADDR(PEDIR_DEBUG) = 0; // dbgCET later
|
ODADDR(PEDIR_DEBUG) = 0; // dbgCET later
|
||||||
ODSIZE(PEDIR_DEBUG) = 0;
|
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");
|
strcpy(osection[2].name, ".rsrc");
|
||||||
osection[2].name[5] = 0;
|
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[0].vaddr = rvamin;
|
||||||
osection[1].vaddr = s1addr;
|
osection[1].vaddr = s1addr;
|
||||||
osection[2].vaddr = ncsection;
|
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[0].size = 0;
|
||||||
osection[1].size = (s1size + fam1) & ~fam1;
|
osection[1].size = (s1size + fam1) & ~fam1;
|
||||||
osection[2].size = (ncsize + fam1) & ~fam1;
|
osection[2].size = (ncsize + fam1) & ~fam1;
|
||||||
// Set sizes for new dummy sections
|
|
||||||
osection[3].size = (fam1 + 0x1000) & ~fam1; // Example small size
|
// Removed section size randomization to maintain DLL functionality
|
||||||
osection[4].size = (fam1 + 0x1000) & ~fam1;
|
|
||||||
osection[5].size = (fam1 + 0x1000) & ~fam1;
|
|
||||||
osection[6].size = (fam1 + 0x1000) & ~fam1;
|
|
||||||
|
|
||||||
osection[0].vsize = osection[1].vaddr - osection[0].vaddr;
|
osection[0].vsize = osection[1].vaddr - osection[0].vaddr;
|
||||||
if (!last_section_rsrc_only) {
|
if (!last_section_rsrc_only) {
|
||||||
osection[1].vsize = (osection[1].size + oam1) & ~oam1;
|
osection[1].vsize = (osection[1].size + oam1) & ~oam1;
|
||||||
osection[2].vsize = (osection[2].size + ncsize_virt_increase + oam1) & ~oam1;
|
osection[2].vsize = (osection[2].size + ncsize_virt_increase + oam1) & ~oam1;
|
||||||
// Set vsizes for new dummy sections
|
oh.imagesize = osection[2].vaddr + osection[2].vsize;
|
||||||
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
|
|
||||||
osection[0].rawdataptr = (pe_offset + sizeof(ht) + sizeof_osection + fam1) & ~(size_t) fam1;
|
osection[0].rawdataptr = (pe_offset + sizeof(ht) + sizeof_osection + fam1) & ~(size_t) fam1;
|
||||||
osection[1].rawdataptr = osection[0].rawdataptr;
|
osection[1].rawdataptr = osection[0].rawdataptr;
|
||||||
} else {
|
} else {
|
||||||
osection[1].vsize = osection[1].size;
|
osection[1].vsize = osection[1].size;
|
||||||
osection[2].vsize = osection[2].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[0].rawdataptr = 0;
|
||||||
osection[1].rawdataptr = (pe_offset + sizeof(ht) + sizeof_osection + fam1) & ~(size_t) fam1;
|
osection[1].rawdataptr = (pe_offset + sizeof(ht) + sizeof_osection + fam1) & ~(size_t) fam1;
|
||||||
}
|
}
|
||||||
osection[2].rawdataptr = osection[1].rawdataptr + osection[1].size;
|
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 |
|
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 |
|
osection[1].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
|
||||||
IMAGE_SCN_MEM_EXECUTE;
|
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;
|
osection[2].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
|
||||||
// Set flags for new dummy sections
|
IMAGE_SCN_CNT_CODE;
|
||||||
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
|
|
||||||
|
|
||||||
if (last_section_rsrc_only) {
|
if (last_section_rsrc_only) {
|
||||||
strcpy(osection[3].name, ".rsrc");
|
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)
|
if (opt->win32_pe.strip_relocs)
|
||||||
oh.flags |= IMAGE_FILE_RELOCS_STRIPPED;
|
oh.flags |= IMAGE_FILE_RELOCS_STRIPPED;
|
||||||
|
|
||||||
|
oh.chksum = 0; // Revert checksum to zero
|
||||||
|
|
||||||
ibuf.clear(0, oh.filealign);
|
ibuf.clear(0, oh.filealign);
|
||||||
|
|
||||||
info("Image size change: %u -> %u KiB", ih.imagesize / 1024, oh.imagesize / 1024);
|
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(ibuf, sizeof(LEXX) - ic);
|
||||||
fo->write(otls, aligned_sotls);
|
fo->write(otls, aligned_sotls);
|
||||||
fo->write(oloadconf, soloadconf);
|
fo->write(oloadconf, soloadconf);
|
||||||
|
|
||||||
|
// Removed random padding to maintain DLL functionality
|
||||||
if (dbgCET) {
|
if (dbgCET) {
|
||||||
ic = fo->getBytesWritten();
|
ic = fo->getBytesWritten();
|
||||||
dbgCET->fpos = ic + sizeof(*dbgCET);
|
dbgCET->fpos = ic + sizeof(*dbgCET);
|
||||||
|
|||||||
Reference in New Issue
Block a user