static unsigned int chdr(fmap_t *map, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd, zip_request_t *request) { char name[256]; int last = 0; const uint8_t *ch; if(!(ch = fmap_need_off(map, coff, SIZEOF_CH)) || CH_magic != 0x02014b50) { if(ch) fmap_unneed_ptr(map, ch, SIZEOF_CH); cli_dbgmsg("cli_unzip: ch - wrkcomplete\n"); return 0; } coff+=SIZEOF_CH; cli_dbgmsg("cli_unzip: ch - flags %x - method %x - csize %x - usize %x - flen %x - elen %x - clen %x - disk %x - off %x\n", CH_flags, CH_method, CH_csize, CH_usize, CH_flen, CH_elen, CH_clen, CH_dsk, CH_off); if(zsize-coff<=CH_flen) { cli_dbgmsg("cli_unzip: ch - fname out of file\n"); last=1; } name[0]='\0'; if((cli_debug_flag && !last) || request) { unsigned int size = (CH_flen>=sizeof(name))?sizeof(name)-1:CH_flen; const char *src = fmap_need_off_once(map, coff, size); if(src) { memcpy(name, src, size); name[size]='\0'; cli_dbgmsg("cli_unzip: ch - fname: %s\n", name); } } coff+=CH_flen; if(zsize-coff<=CH_elen && !last) { cli_dbgmsg("cli_unzip: ch - extra out of file\n"); last=1; } coff+=CH_elen; if(zsize-coff<CH_clen && !last) { cli_dbgmsg("cli_unzip: ch - comment out of file\n"); last = 1; } coff+=CH_clen; if (!request) { if(CH_off<zsize-SIZEOF_LH) { lhdr(map, CH_off, zsize-CH_off, fu, fc, ch, ret, ctx, tmpd, 1, zip_scan_cb); } else cli_dbgmsg("cli_unzip: ch - local hdr out of file\n"); } else { size_t len = MIN(sizeof(name)-1, request->namelen); if (!last && !strncmp(request->name, name, len)) { request->found = 1; request->loff = CH_off; } } fmap_unneed_ptr(map, ch, SIZEOF_CH); return (last?0:coff); }
const uint8_t* cli_bcapi_buffer_pipe_read_get(struct cli_bc_ctx *ctx , int32_t id, uint32_t size) { struct bc_buffer *b = get_buffer(ctx, id); if (!b || size > cli_bcapi_buffer_pipe_read_avail(ctx, id) || !size) return NULL; if (b->data) return b->data + b->read_cursor; return fmap_need_off(ctx->fmap, b->read_cursor, size); }
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_need_ptr(fmap_t *m, void *ptr, size_t len) { return fmap_need_off(m, (char *)ptr - (char *)m - m->hdrsz, len); }