static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int *fu, unsigned int fc, const uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd, int detect_encrypted, zip_cb zcb) { const uint8_t *lh, *zip; char name[256]; uint32_t csize, usize; if(!(lh = fmap_need_off(map, loff, SIZEOF_LH))) { cli_dbgmsg("cli_unzip: lh - out of file\n"); return 0; } if(LH_magic != 0x04034b50) { if (!ch) cli_dbgmsg("cli_unzip: lh - wrkcomplete\n"); else cli_dbgmsg("cli_unzip: lh - bad magic\n"); fmap_unneed_off(map, loff, SIZEOF_LH); return 0; } zip = lh + SIZEOF_LH; zsize-=SIZEOF_LH; if(zsize<=LH_flen) { cli_dbgmsg("cli_unzip: lh - fname out of file\n"); fmap_unneed_off(map, loff, SIZEOF_LH); return 0; } if(ctx->engine->cdb || cli_debug_flag) { uint32_t nsize = (LH_flen>=sizeof(name))?sizeof(name)-1:LH_flen; const char *src; if(nsize && (src = fmap_need_ptr_once(map, zip, nsize))) { memcpy(name, zip, nsize); name[nsize]='\0'; } else name[0] = '\0'; } zip+=LH_flen; zsize-=LH_flen; cli_dbgmsg("cli_unzip: lh - ZMDNAME:%d:%s:%u:%u:%x:%u:%u:%u\n", ((LH_flags & F_ENCR)!=0), name, LH_usize, LH_csize, LH_crc32, LH_method, fc, ctx->recursion); /* ZMDfmt virname:encrypted(0-1):filename(exact|*):usize(exact|*):csize(exact|*):crc32(exact|*):method(exact|*):fileno(exact|*):maxdepth(exact|*) */ if(cli_matchmeta(ctx, name, LH_csize, LH_usize, (LH_flags & F_ENCR)!=0, fc, LH_crc32, NULL) == CL_VIRUS) { *ret = CL_VIRUS; return 0; } if(LH_flags & F_MSKED) { cli_dbgmsg("cli_unzip: lh - header has got unusable masked data\n"); /* FIXME: need to find/craft a sample */ fmap_unneed_off(map, loff, SIZEOF_LH); return 0; } if(detect_encrypted && (LH_flags & F_ENCR) && DETECT_ENCRYPTED) { cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n"); cli_append_virus(ctx, "Heuristics.Encrypted.Zip"); *ret = CL_VIRUS; fmap_unneed_off(map, loff, SIZEOF_LH); return 0; } if(LH_flags & F_USEDD) { cli_dbgmsg("cli_unzip: lh - has data desc\n"); if(!ch) { fmap_unneed_off(map, loff, SIZEOF_LH); return 0; } else { usize = CH_usize; csize = CH_csize; } } else { usize = LH_usize; csize = LH_csize; } if(zsize<=LH_elen) { cli_dbgmsg("cli_unzip: lh - extra out of file\n"); fmap_unneed_off(map, loff, SIZEOF_LH); return 0; } zip+=LH_elen; zsize-=LH_elen; if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */ cli_dbgmsg("cli_unzip: lh - skipping empty file\n"); } else { if(zsize<csize) { cli_dbgmsg("cli_unzip: lh - stream out of file\n"); fmap_unneed_off(map, loff, SIZEOF_LH); return 0; } if(LH_flags & F_ENCR) { cli_dbgmsg("cli_unzip: lh - skipping encrypted file\n"); } else { if(fmap_need_ptr_once(map, zip, csize)) *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb); } zip+=csize; zsize-=csize; } fmap_unneed_off(map, loff, SIZEOF_LH); /* unneed now. block is guaranteed to exists till the next need */ if(LH_flags & F_USEDD) { if(zsize<12) { cli_dbgmsg("cli_unzip: lh - data desc out of file\n"); return 0; } zsize-=12; if(fmap_need_ptr_once(map, zip, 4)) { if(cli_readint32(zip)==0x08074b50) { if(zsize<4) { cli_dbgmsg("cli_unzip: lh - data desc out of file\n"); return 0; } zip+=4; } } zip+=12; } return zip-lh; }
void fmap_unneed_ptr(fmap_t *m, void *ptr, size_t len) { fmap_unneed_off(m, (char *)ptr - (char *)m - m->hdrsz, len); }