Hi,

this is a followup to the "Testing for Big Endian Architectures" thread on the clamav-users list in January.

I ran into the same test failures on big endian architectures when upgrading ClamAV to 1.0.1 for openSUSE. In addition to the fixes for the peinfo->dirs[1] array from the Debian patch I found some more members of peinfo and sub-structures that appeared to be missing endianness correction in pe.c. But they apparently didn't break any existing test. Some of them were already tagged with comments telling that endianness corrections are still missing here.

Find below an enhanced patch that also covers these cases, but I am not sure if I found them all.

Additionally I wonder if it wouldn't be better to put all these conversions into one place and call them after populating peinfo instead of scattering them across the whole file whenever one of the affected field gets read.

cu
Reinhard

--- libclamav/pe.c.orig
+++ libclamav/pe.c
@@ -2422,22 +2422,20 @@ static cl_error_t hash_imptbl(cli_ctx *c

     /* If the PE doesn't have an import table then skip it. This is an
      * uncommon case but can happen. */
-    if (peinfo->dirs[1].VirtualAddress == 0 || peinfo->dirs[1].Size == 0) {
+    if (EC32(peinfo->dirs[1].VirtualAddress) == 0 || 
EC32(peinfo->dirs[1].Size) == 0) {
         cli_dbgmsg("scan_pe: import table data dir does not exist (skipping .imp 
scanning)\n");
         status = CL_BREAK;
         goto done;
     }

-    // TODO Add EC32 wrappers
-    impoff = cli_rawaddr(peinfo->dirs[1].VirtualAddress, peinfo->sections, 
peinfo->nsections, &err, fsize, peinfo->hdr_size);
-    if (err || impoff + peinfo->dirs[1].Size > fsize) {
+    impoff = cli_rawaddr(EC32(peinfo->dirs[1].VirtualAddress), peinfo->sections, 
peinfo->nsections, &err, fsize, peinfo->hdr_size);
+    if (err || impoff + EC32(peinfo->dirs[1].Size) > fsize) {
         cli_dbgmsg("scan_pe: invalid rva for import table data\n");
         status = CL_BREAK;
         goto done;
     }

-    // TODO Add EC32 wrapper
-    impdes = (const struct pe_image_import_descriptor *)fmap_need_off(map, 
impoff, peinfo->dirs[1].Size);
+    impdes = (const struct pe_image_import_descriptor *)fmap_need_off(map, 
impoff, EC32(peinfo->dirs[1].Size));
     if (impdes == NULL) {
         cli_dbgmsg("scan_pe: failed to acquire fmap buffer\n");
         status = CL_EREAD;
@@ -2447,7 +2445,7 @@ static cl_error_t hash_imptbl(cli_ctx *c

     /* Safety: We can trust peinfo->dirs[1].Size only because 
`fmap_need_off()` (above)
      * would have failed if the size exceeds the end of the fmap. */
-    left = peinfo->dirs[1].Size;
+    left = EC32(peinfo->dirs[1].Size);

     if (genhash[CLI_HASH_MD5]) {
         hashctx[CLI_HASH_MD5] = cl_hash_init("md5");
@@ -2546,7 +2544,7 @@ static cl_error_t hash_imptbl(cli_ctx *c

 done:
     if (needed_impoff) {
-        fmap_unneed_off(map, impoff, peinfo->dirs[1].Size);
+        fmap_unneed_off(map, impoff, EC32(peinfo->dirs[1].Size));
     }

     for (type = CLI_HASH_MD5; type < CLI_HASH_AVAIL_TYPES; type++) {
@@ -3177,8 +3175,7 @@ int cli_scanpe(cli_ctx *ctx)
     }

     /* W32.Polipos.A */
-    // TODO Add endianness correction to SizeOfStackReserve access
-    while (polipos && !peinfo->is_dll && peinfo->nsections > 2 && peinfo->nsections < 13 && peinfo->e_lfanew <= 0x800 
&& (EC16(peinfo->pe_opt.opt32.Subsystem) == 2 || EC16(peinfo->pe_opt.opt32.Subsystem) == 3) && EC16(peinfo->file_hdr.Machine) == 0x14c && 
peinfo->pe_opt.opt32.SizeOfStackReserve >= 0x80000) {
+    while (polipos && !peinfo->is_dll && peinfo->nsections > 2 && peinfo->nsections < 13 && peinfo->e_lfanew <= 0x800 
&& (EC16(peinfo->pe_opt.opt32.Subsystem) == 2 || EC16(peinfo->pe_opt.opt32.Subsystem) == 3) && EC16(peinfo->file_hdr.Machine) == 0x14c && 
EC32(peinfo->pe_opt.opt32.SizeOfStackReserve) >= 0x80000) {
         uint32_t jump, jold, *jumps = NULL;
         const uint8_t *code;
         unsigned int xsjs = 0;
@@ -3250,7 +3247,7 @@ int cli_scanpe(cli_ctx *ctx)

     /* Trojan.Swizzor.Gen */
     if (SCAN_HEURISTICS && (DCONF & PE_CONF_SWIZZOR) && peinfo->nsections > 1 && fsize > 
64 * 1024 && fsize < 4 * 1024 * 1024) {
-        if (peinfo->dirs[2].Size) {
+        if (EC32(peinfo->dirs[2].Size)) {
             struct swizz_stats *stats = cli_calloc(1, sizeof(*stats));
             unsigned int m            = 1000;
             ret                       = CL_CLEAN;
@@ -3903,8 +3900,7 @@ int cli_scanpe(cli_ctx *ctx)
         if (cli_memstr(UPX_LZMA2, 20, epbuff + 0x2f, 20)) {
             uint32_t strictdsize = cli_readint32(epbuff + 0x21), skew = 0;
             if (ssize > 0x15 && epbuff[0] == '\x60' && epbuff[1] == '\xbe') {
-                // TODO Add EC32
-                skew = cli_readint32(epbuff + 2) - peinfo->sections[i + 1].rva - 
peinfo->pe_opt.opt32.ImageBase;
+                skew = cli_readint32(epbuff + 2) - peinfo->sections[i + 1].rva - 
EC32(peinfo->pe_opt.opt32.ImageBase);
                 if (skew != 0x15)
                     skew = 0;
             }
@@ -3915,8 +3911,7 @@ int cli_scanpe(cli_ctx *ctx)
             uint32_t strictdsize = cli_readint32(epbuff + 0x2b), skew = 0;
             uint32_t properties = cli_readint32(epbuff + 0x41);
             if (ssize > 0x15 && epbuff[0] == '\x60' && epbuff[1] == '\xbe') {
-                // TODO Add EC32
-                skew = cli_readint32(epbuff + 2) - peinfo->sections[i + 1].rva - 
peinfo->pe_opt.opt32.ImageBase;
+                skew = cli_readint32(epbuff + 2) - peinfo->sections[i + 1].rva - 
EC32(peinfo->pe_opt.opt32.ImageBase);
                 if (skew != 0x15)
                     skew = 0;
             }
@@ -5097,7 +5092,7 @@ cl_error_t cli_peheader(fmap_t *map, str

     for (i = 0; falign != 0x200 && i < (size_t)peinfo->nsections; i++) {
         /* file alignment fallback mode - blah */
-        if (falign && section_hdrs[i].SizeOfRawData && 
EC32(section_hdrs[i].PointerToRawData) % falign && !(EC32(section_hdrs[i].PointerToRawData) % 
0x200)) {
+        if (falign && EC32(section_hdrs[i].SizeOfRawData) && 
EC32(section_hdrs[i].PointerToRawData) % falign && !(EC32(section_hdrs[i].PointerToRawData) % 
0x200)) {
             cli_dbgmsg("cli_peheader: Encountered section with unexpected alignment 
- triggering fallback mode\n");
             falign = 0x200;
         }
@@ -5292,13 +5287,13 @@ cl_error_t cli_peheader(fmap_t *map, str
         cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", peinfo->ep, peinfo->ep);
     }

-    if (is_dll || peinfo->ndatadirs < 3 || !peinfo->dirs[2].Size)
+    if (is_dll || peinfo->ndatadirs < 3 || !EC32(peinfo->dirs[2].Size))
         peinfo->res_addr = 0;
     else
         peinfo->res_addr = EC32(peinfo->dirs[2].VirtualAddress);

     while (opts & CLI_PEHEADER_OPT_EXTRACT_VINFO &&
-           peinfo->ndatadirs >= 3 && peinfo->dirs[2].Size) {
+           peinfo->ndatadirs >= 3 && EC32(peinfo->dirs[2].Size)) {
         struct vinfo_list vlist;
         const uint8_t *vptr, *baseptr;
         uint32_t rva, res_sz;


--
SUSE Software Solutions Germany GmbH (HRB 36809, AG Nürnberg)
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Martje Boudien Moerman
_______________________________________________

clamav-devel mailing list
clamav-devel@lists.clamav.net
https://lists.clamav.net/mailman/listinfo/clamav-devel

Please submit your patches to our Github: 
https://github.com/Cisco-Talos/clamav-devel/pulls

Help us build a comprehensive ClamAV guide:
https://github.com/vrtadmin/clamav-faq

http://www.clamav.net/contact.html#ml

Reply via email to