/* test file extract API */ int entrypoint(void) { unsigned char buf[4]; /* fixme:compiler assumes LE here = {1, 2, 3, 4}; */ uint32_t x, i; uint64_t y; *(uint32_t*)buf = le32_to_host(0x04030201); for (i=0;i<3;i++) { extract_new(i); if (write(buf, sizeof(buf)) != sizeof(buf)) return 0xbad1; /* switch input to extracted file */ if (input_switch(1) != 0) return 0xbad2; if (seek(0, SEEK_END) != 4) return 0xbad3; if (seek(0, SEEK_SET) != 0) return 0xbad4; x = 0x5a5a5a5a; if (read(&x, sizeof(x)) != sizeof(x)) return 0xbad5; if (cli_readint32(&x) != 0x04030201) return 0xbad6; /* switch back to normal file */ if (input_switch(0) != 0) return 0xbad7; if (seek(0, SEEK_SET) != 0) return 0xbad8; if (read(&x, sizeof(x)) != sizeof(x)) return 0xbad9; x = le32_to_host(x); if (x != 0x44434241) return 0xbad10; /* write to extracted file again */ if (write(buf, sizeof(buf)) != sizeof(buf)) return 0xbad11; /* switch input to extracted file */ if (input_switch(1) != 0) return 0xbad12; if (seek(0, SEEK_END) != 8) return 0xbad13; if (seek(0, SEEK_SET) != 0) return 0xbad14; if (read(&y, sizeof(y)) != sizeof(y)) return 0xbad15; y = le64_to_host(y); if (y != 0x0403020104030201UL) return 0xbad16; if (input_switch(0) != 0) return 0xbad17; } return 0xf00d; }
void mbr_convert_to_host(struct mbr_boot_record *record) { struct mbr_partition_entry *entry; unsigned i; for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) { entry = &record->entries[i]; entry->firstLBA = le32_to_host(entry->firstLBA); entry->numLBA = le32_to_host(entry->numLBA); } record->signature = be16_to_host(record->signature); }
static uint32_t riff_endian_convert_32(uint32_t value, int big_endian) { if (big_endian) return be32_to_host(value); else return le32_to_host(value); }
int32_t cli_bcapi_matchicon(struct cli_bc_ctx *ctx , const uint8_t* grp1, int32_t grp1len, const uint8_t* grp2, int32_t grp2len) { int ret; char group1[128], group2[128]; const char **oldvirname; struct cli_exe_info info; if (!ctx->hooks.pedata->ep) { cli_dbgmsg("bytecode: matchicon only works with PE files\n"); return -1; } if ((size_t) grp1len > sizeof(group1)-1 || (size_t) grp2len > sizeof(group2)-1) return -1; oldvirname = ((cli_ctx*)ctx->ctx)->virname; ((cli_ctx*)ctx->ctx)->virname = NULL; memcpy(group1, grp1, grp1len); memcpy(group2, grp2, grp2len); group1[grp1len] = 0; group2[grp2len] = 0; memset(&info, 0, sizeof(info)); if (ctx->bc->kind == BC_PE_UNPACKER || ctx->bc->kind == BC_PE_ALL) { if(le16_to_host(ctx->hooks.pedata->file_hdr.Characteristics) & 0x2000 || !ctx->hooks.pedata->dirs[2].Size) info.res_addr = 0; else info.res_addr = le32_to_host(ctx->hooks.pedata->dirs[2].VirtualAddress); } else info.res_addr = ctx->resaddr; /* from target_info */ info.section = (struct cli_exe_section*)ctx->sections; info.nsections = ctx->hooks.pedata->nsections; info.hdr_size = ctx->hooks.pedata->hdr_size; cli_dbgmsg("bytecode matchicon %s %s\n", group1, group2); ret = matchicon(ctx->ctx, &info, group1[0] ? group1 : NULL, group2[0] ? group2 : NULL); ((cli_ctx*)ctx->ctx)->virname = oldvirname; return ret; }
static int gpt_prtn_intxn(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize) { prtn_intxn_list_t prtncheck; struct gpt_partition_entry gpe; unsigned i, pitxn; int ret = CL_CLEAN, tmp = CL_CLEAN; off_t pos; size_t maplen; uint32_t max_prtns = 0; int virus_found = 0; maplen = (*ctx->fmap)->real_len; /* convert endian to host to check partition table */ hdr.tableStartLBA = le64_to_host(hdr.tableStartLBA); hdr.tableNumEntries = le32_to_host(hdr.tableNumEntries); prtn_intxn_list_init(&prtncheck); /* check engine maxpartitions limit */ if (hdr.tableNumEntries < ctx->engine->maxpartitions) { max_prtns = hdr.tableNumEntries; } else { max_prtns = ctx->engine->maxpartitions; } pos = hdr.tableStartLBA * sectorsize; for (i = 0; i < max_prtns; ++i) { /* read in partition entry */ if (fmap_readn(*ctx->fmap, &gpe, pos, sizeof(gpe)) != sizeof(gpe)) { cli_dbgmsg("cli_scangpt: Invalid GPT partition entry\n"); prtn_intxn_list_free(&prtncheck); return CL_EFORMAT; } /* convert the endian to host */ gpe.firstLBA = le64_to_host(gpe.firstLBA); gpe.lastLBA = le64_to_host(gpe.lastLBA); if (gpe.firstLBA == 0) { /* empty partition, invalid */ } else if ((gpe.firstLBA > gpe.lastLBA) || (gpe.firstLBA < hdr.firstUsableLBA) || (gpe.lastLBA > hdr.lastUsableLBA)) { /* partition exists outside bounds specified by header or invalid */ } else if (((gpe.lastLBA+1) * sectorsize) > maplen) { /* partition exists outside bounds of the file map */ } else { tmp = prtn_intxn_list_check(&prtncheck, &pitxn, gpe.firstLBA, gpe.lastLBA - gpe.firstLBA + 1); if (tmp != CL_CLEAN) { if (tmp == CL_VIRUS) { cli_dbgmsg("cli_scangpt: detected intersection with partitions " "[%u, %u]\n", pitxn, i); ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION); if (ret == CL_VIRUS) virus_found = 1; if (SCAN_ALLMATCHES || ret == CL_CLEAN) tmp = 0; else goto leave; } else { ret = tmp; goto leave; } } } /* increment the offsets to next partition entry */ pos += hdr.tableEntrySize; } leave: prtn_intxn_list_free(&prtncheck); if (virus_found) return CL_VIRUS; return ret; }
static int gpt_validate_header(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize) { uint32_t crc32_calc, crc32_ref; uint64_t tableLastLBA, lastLBA; size_t maplen, ptable_start, ptable_len; unsigned char *ptable; maplen = (*ctx->fmap)->real_len; /* checking header crc32 checksum */ crc32_ref = le32_to_host(hdr.headerCRC32); hdr.headerCRC32 = 0; /* checksum is calculated with field = 0 */ crc32_calc = crc32(0, (unsigned char*)&hdr, sizeof(hdr)); if (crc32_calc != crc32_ref) { cli_dbgmsg("cli_scangpt: GPT header checksum mismatch\n"); gpt_parsemsg("%x != %x\n", crc32_calc, crc32_ref); return CL_EFORMAT; } /* convert endian to host to check partition table */ hdr.signature = be64_to_host(hdr.signature); hdr.revision = be32_to_host(hdr.revision); hdr.headerSize = le32_to_host(hdr.headerSize); hdr.headerCRC32 = crc32_ref; hdr.reserved = le32_to_host(hdr.reserved); hdr.currentLBA = le64_to_host(hdr.currentLBA); hdr.backupLBA = le64_to_host(hdr.backupLBA); hdr.firstUsableLBA = le64_to_host(hdr.firstUsableLBA); hdr.lastUsableLBA = le64_to_host(hdr.lastUsableLBA); hdr.tableStartLBA = le64_to_host(hdr.tableStartLBA); hdr.tableNumEntries = le32_to_host(hdr.tableNumEntries); hdr.tableEntrySize = le32_to_host(hdr.tableEntrySize); hdr.tableCRC32 = le32_to_host(hdr.tableCRC32);; ptable_start = hdr.tableStartLBA * sectorsize; ptable_len = hdr.tableNumEntries * hdr.tableEntrySize; tableLastLBA = (hdr.tableStartLBA + (ptable_len / sectorsize)) - 1; lastLBA = (maplen / sectorsize) - 1; /** HEADER CHECKS **/ gpt_printSectors(ctx, sectorsize); /* check signature */ if (hdr.signature != GPT_SIGNATURE) { cli_dbgmsg("cli_scangpt: Invalid GPT header signature %llx\n", (long long unsigned)hdr.signature); return CL_EFORMAT; } /* check header size */ if (hdr.headerSize != sizeof(hdr)) { cli_dbgmsg("cli_scangpt: GPT header size does not match stated size\n"); return CL_EFORMAT; } /* check reserved value == 0 */ if (hdr.reserved != GPT_HDR_RESERVED) { cli_dbgmsg("cli_scangpt: GPT header reserved is not expected value\n"); return CL_EFORMAT; } /* check that sectors are in a valid configuration */ if (!((hdr.currentLBA == GPT_PRIMARY_HDR_LBA && hdr.backupLBA == lastLBA) || (hdr.currentLBA == lastLBA && hdr.backupLBA == GPT_PRIMARY_HDR_LBA))) { cli_dbgmsg("cli_scangpt: GPT secondary header is not last LBA\n"); return CL_EFORMAT; } if (hdr.firstUsableLBA > hdr.lastUsableLBA) { cli_dbgmsg("cli_scangpt: GPT first usable sectors is after last usable sector\n"); return CL_EFORMAT; } if (hdr.firstUsableLBA <= GPT_PRIMARY_HDR_LBA || hdr.lastUsableLBA >= lastLBA) { cli_dbgmsg("cli_scangpt: GPT usable sectors intersects header sector\n"); return CL_EFORMAT; } if ((hdr.tableStartLBA <= hdr.firstUsableLBA && tableLastLBA >= hdr.firstUsableLBA) || (hdr.tableStartLBA >= hdr.firstUsableLBA && hdr.tableStartLBA <= hdr.lastUsableLBA)) { cli_dbgmsg("cli_scangpt: GPT usable sectors intersects partition table\n"); return CL_EFORMAT; } if (hdr.tableStartLBA <= GPT_PRIMARY_HDR_LBA || tableLastLBA >= lastLBA) { cli_dbgmsg("cli_scangpt: GPT partition table intersects header sector\n"); return CL_EFORMAT; } /* check that valid table entry size */ if (hdr.tableEntrySize != sizeof(struct gpt_partition_entry)) { cli_dbgmsg("cli_scangpt: cannot parse gpt with partition entry sized %u\n", hdr.tableEntrySize); return CL_EFORMAT; } /* check valid table */ if ((ptable_start + ptable_len) > maplen) { cli_dbgmsg("cli_scangpt: GPT partition table extends over fmap limit\n"); return CL_EFORMAT; } /** END HEADER CHECKS **/ /* checking partition table crc32 checksum */ ptable = (unsigned char*)fmap_need_off_once((*ctx->fmap), ptable_start, ptable_len); crc32_calc = crc32(0, ptable, ptable_len); if (crc32_calc != hdr.tableCRC32) { cli_dbgmsg("cli_scangpt: GPT partition table checksum mismatch\n"); gpt_parsemsg("%x != %x\n", crc32_calc, hdr.tableCRC32); return CL_EFORMAT; } return CL_SUCCESS; }
static int gpt_scan_partitions(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize) { struct gpt_partition_entry gpe; int ret = CL_CLEAN, detection = CL_CLEAN; size_t maplen, part_size = 0; off_t pos = 0, part_off = 0; unsigned i = 0, j = 0; uint32_t max_prtns = 0; /* convert endian to host */ hdr.signature = be64_to_host(hdr.signature); hdr.revision = be32_to_host(hdr.revision); hdr.headerSize = le32_to_host(hdr.headerSize); hdr.headerCRC32 = le32_to_host(hdr.headerCRC32); hdr.reserved = le32_to_host(hdr.reserved); hdr.currentLBA = le64_to_host(hdr.currentLBA); hdr.backupLBA = le64_to_host(hdr.backupLBA); hdr.firstUsableLBA = le64_to_host(hdr.firstUsableLBA); hdr.lastUsableLBA = le64_to_host(hdr.lastUsableLBA); hdr.tableStartLBA = le64_to_host(hdr.tableStartLBA); hdr.tableNumEntries = le32_to_host(hdr.tableNumEntries); hdr.tableEntrySize = le32_to_host(hdr.tableEntrySize); hdr.tableCRC32 = le32_to_host(hdr.tableCRC32); /* print header info for the debug */ cli_dbgmsg("GPT Header:\n"); cli_dbgmsg("Signature: 0x%llx\n", (long long unsigned)hdr.signature); cli_dbgmsg("Revision: %x\n", hdr.revision); gpt_printGUID(hdr.DiskGUID, "DISK GUID"); cli_dbgmsg("Partition Entry Count: %u\n", hdr.tableNumEntries); cli_dbgmsg("Partition Entry Size: %u\n", hdr.tableEntrySize); maplen = (*ctx->fmap)->real_len; /* check engine maxpartitions limit */ if (hdr.tableNumEntries < ctx->engine->maxpartitions) { max_prtns = hdr.tableNumEntries; } else { max_prtns = ctx->engine->maxpartitions; } /* use the partition tables to pass partitions to cli_map_scan */ pos = hdr.tableStartLBA * sectorsize; for (i = 0; i < max_prtns; ++i) { /* read in partition entry */ if (fmap_readn(*ctx->fmap, &gpe, pos, sizeof(gpe)) != sizeof(gpe)) { cli_dbgmsg("cli_scangpt: Invalid GPT partition entry\n"); return CL_EFORMAT; } /* convert the endian to host */ gpe.firstLBA = le64_to_host(gpe.firstLBA); gpe.lastLBA = le64_to_host(gpe.lastLBA); gpe.attributes = le64_to_host(gpe.attributes); for (j = 0; j < 36; ++j) { gpe.name[i] = le16_to_host(gpe.name[i]); } /* check that partition is not empty and within a valid location */ if (gpe.firstLBA == 0) { /* empty partition, invalid */ } else if ((gpe.firstLBA > gpe.lastLBA) || (gpe.firstLBA < hdr.firstUsableLBA) || (gpe.lastLBA > hdr.lastUsableLBA)) { cli_dbgmsg("cli_scangpt: GPT partition exists outside specified bounds\n"); gpt_parsemsg("%llu < %llu, %llu > %llu\n", gpe.firstLBA, hdr.firstUsableLBA, gpe.lastLBA, hdr.lastUsableLBA); /* partition exists outside bounds specified by header or invalid */ } else if (((gpe.lastLBA+1) * sectorsize) > maplen) { /* partition exists outside bounds of the file map */ } else { /* print partition entry data for debug */ cli_dbgmsg("GPT Partition Entry %u:\n", i); gpt_printName(gpe.name, "Name"); gpt_printGUID(gpe.typeGUID, "Type GUID"); gpt_printGUID(gpe.uniqueGUID, "Unique GUID"); cli_dbgmsg("Attributes: %llx\n", (long long unsigned)gpe.attributes); cli_dbgmsg("Blocks: [%llu(%llu) -> %llu(%llu)]\n", (long long unsigned)gpe.firstLBA, (long long unsigned)(gpe.firstLBA * sectorsize), (long long unsigned)gpe.lastLBA, (long long unsigned)((gpe.lastLBA+1) * sectorsize)); /* send the partition to cli_map_scan */ part_off = gpe.firstLBA * sectorsize; part_size = (gpe.lastLBA - gpe.firstLBA + 1) * sectorsize; ret = cli_map_scan(*ctx->fmap, part_off, part_size, ctx, CL_TYPE_PART_ANY); if (ret != CL_CLEAN) { if (SCAN_ALLMATCHES && (ret == CL_VIRUS)) detection = CL_VIRUS; else return ret; } } /* increment the offsets to next partition entry */ pos += hdr.tableEntrySize; } if (i >= ctx->engine->maxpartitions) { cli_dbgmsg("cli_scangpt: max partitions reached\n"); } return detection; }
int cli_scanswf(cli_ctx *ctx) { struct swf_file_hdr file_hdr; fmap_t *map = *ctx->fmap; unsigned int bitpos, bitbuf, getbits_n, nbits, getword_1, getword_2, getdword_1, getdword_2; const char *pt; unsigned char get_c; size_t offset = 0; unsigned int val, foo, tag_hdr, tag_type, tag_len; unsigned long int bits; cli_dbgmsg("in cli_scanswf()\n"); if(fmap_readn(map, &file_hdr, offset, sizeof(file_hdr)) != sizeof(file_hdr)) { cli_dbgmsg("SWF: Can't read file header\n"); return CL_CLEAN; } offset += sizeof(file_hdr); /* ** SWF stores the integer bytes with the least significate byte first */ file_hdr.filesize = le32_to_host (file_hdr.filesize); cli_dbgmsg("SWF: Version: %u\n", file_hdr.version); cli_dbgmsg("SWF: File size: %u\n", file_hdr.filesize); if(!strncmp(file_hdr.signature, "CWS", 3)) { cli_dbgmsg("SWF: zlib compressed file\n"); return scancws(ctx, &file_hdr); } else if(!strncmp(file_hdr.signature, "ZWS", 3)) { cli_dbgmsg("SWF: LZMA compressed file\n"); return scanzws(ctx, &file_hdr); } else if(!strncmp(file_hdr.signature, "FWS", 3)) { cli_dbgmsg("SWF: Uncompressed file\n"); } else { cli_dbgmsg("SWF: Not a SWF file\n"); return CL_CLEAN; } INITBITS; GETBITS(nbits, 5); cli_dbgmsg("SWF: FrameSize RECT size bits: %u\n", nbits); { uint32_t xMin = 0, xMax = 0, yMin = 0, yMax = 0; GETBITS(xMin, nbits); /* Should be zero */ GETBITS(xMax, nbits); GETBITS(yMin, nbits); /* Should be zero */ GETBITS(yMax, nbits); cli_dbgmsg("SWF: FrameSize xMin %u xMax %u yMin %u yMax %u\n", xMin, xMax, yMin, yMax); } GETWORD(foo); GETWORD(val); cli_dbgmsg("SWF: Frames total: %d\n", val); /* Skip Flash tag walk unless debug mode */ if(!cli_debug_flag) { return CL_CLEAN; } while(offset < map->len) { GETWORD(tag_hdr); tag_type = tag_hdr >> 6; if(tag_type == 0) break; tag_len = tag_hdr & 0x3f; if(tag_len == 0x3f) GETDWORD(tag_len); pt = tagname(tag_type); cli_dbgmsg("SWF: %s\n", pt ? pt : "UNKNOWN TAG"); cli_dbgmsg("SWF: Tag length: %u\n", tag_len); if (tag_len > map->len) { cli_dbgmsg("SWF: Invalid tag length.\n"); return CL_EFORMAT; } if ((offset + tag_len) < offset) { cli_warnmsg("SWF: Tag length too large.\n"); break; } if(!pt) { offset += tag_len; continue; } switch(tag_type) { case TAG_SCRIPTLIMITS: { unsigned int recursion, timeout; GETWORD(recursion); GETWORD(timeout); cli_dbgmsg("SWF: scriptLimits recursion %u timeout %u\n", recursion, timeout); break; } case TAG_FILEATTRIBUTES: GETDWORD(val); cli_dbgmsg("SWF: File attributes:\n"); if(val & SWF_ATTR_USENETWORK) cli_dbgmsg(" * Use network\n"); if(val & SWF_ATTR_RELATIVEURLS) cli_dbgmsg(" * Relative URLs\n"); if(val & SWF_ATTR_SUPPRESSCROSSDOMAINCACHE) cli_dbgmsg(" * Suppress cross domain cache\n"); if(val & SWF_ATTR_ACTIONSCRIPT3) cli_dbgmsg(" * ActionScript 3.0\n"); if(val & SWF_ATTR_HASMETADATA) cli_dbgmsg(" * Has metadata\n"); if(val & SWF_ATTR_USEDIRECTBLIT) cli_dbgmsg(" * Use hardware acceleration\n"); if(val & SWF_ATTR_USEGPU) cli_dbgmsg(" * Use GPU\n"); break; default: offset += tag_len; continue; } } return CL_CLEAN; }