int main(int argc, char *argv[]) { PE_FILE pe; FILE *dbfile = NULL, *fp = NULL; QWORD ep_offset, pesize; char value[MAX_MSG]; unsigned char *pe_data; if (argc < 2) { usage(); exit(1); } memset(&config, 0, sizeof(config)); parse_options(argc, argv); // opcoes if ((fp = fopen(argv[argc-1], "rb")) == NULL) EXIT_ERROR("file not found or unreadable"); pe_init(&pe, fp); // inicializa o struct pe if (!ispe(&pe)) EXIT_ERROR("invalid PE file"); if (!pe_get_optional(&pe)) EXIT_ERROR("unable to read optional header"); if (!(ep_offset = rva2ofs(&pe, pe.entrypoint))) EXIT_ERROR("unable to get entrypoint offset"); pesize = pe_get_size(&pe); pe_data = (unsigned char *) xmalloc(pesize); //if (fseek(pe.handle, ep, SEEK_SET)) //EXIT_ERROR("unable to seek to entrypoint offset"); if (!fread(pe_data, pesize, 1, pe.handle)) EXIT_ERROR("unable to read entrypoint data"); if (!loaddb(&dbfile)) fprintf(stderr, "warning: without valid database file, %s will search in generic mode only\n", PROGRAM); // packer by signature if (compare_signature(pe_data, ep_offset, dbfile, value)); // generic detection else if (generic_packer(&pe, ep_offset)) snprintf(value, MAX_MSG, "generic"); else snprintf(value, MAX_MSG, "no packer found"); free(pe_data); output("packer", value); if (dbfile) fclose(dbfile); pe_deinit(&pe); return 0; }
/* find stack cookies, a.k.a canary, buffer security check option in MVS 2010 */ static bool stack_cookies(PE_FILE *pe) { unsigned int i, found = 0; unsigned char buff; const unsigned char mvs2010[] = {0x55, 0x8b, 0xec, 0x83, 0x33, 0xc5, 0x33, 0xcd, 0xe8, 0xc3}; if (!pe) return false; if (!pe->entrypoint) if (!pe_get_optional(pe)) return false; rewind(pe->handle); while (fread(&buff, 1, 1, pe->handle)) { for (i=0; i < sizeof(mvs2010); i++) { if (buff == mvs2010[i] && found == i) found++; } } return (found == sizeof(mvs2010)); }
static bool normal_imagebase(PE_FILE *pe) { if (!pe->imagebase) pe_get_optional(pe); return (pe->imagebase == 0x100000000 || pe->imagebase == 0x1000000 || pe->imagebase == 0x400000); }
int main(int argc, char *argv[]) { PE_FILE pe; FILE *fp = NULL; WORD dllchar = 0; char field[MAX_MSG]; if (argc < 2) { usage(); exit(1); } parse_options(argc, argv); // opcoes if ((fp = fopen(argv[argc-1], "rb")) == NULL) EXIT_ERROR("file not found or unreadable"); pe_init(&pe, fp); // inicializa o struct pe if (!is_pe(&pe)) EXIT_ERROR("not a valid PE file"); if (!pe_get_optional(&pe)) return 1; if (pe.architecture == PE32) dllchar = pe.optional_ptr->_32->DllCharacteristics; else if (pe.architecture == PE64) dllchar = pe.optional_ptr->_64->DllCharacteristics; else return 1; // aslr snprintf(field, MAX_MSG, "ASLR"); output(field, (dllchar & 0x40) ? "yes" : "no"); // dep/nx snprintf(field, MAX_MSG, "DEP/NX"); output(field, (dllchar & 0x100) ? "yes" : "no"); // seh snprintf(field, MAX_MSG, "SEH"); output(field, (dllchar & 0x400) ? "no" : "yes"); // stack cookies snprintf(field, MAX_MSG, "Stack cookies (EXPERIMENTAL)"); output(field, stack_cookies(&pe) ? "yes" : "no"); // libera a memoria pe_deinit(&pe); return 0; }
static IMAGE_SECTION_HEADER *pe_check_fake_entrypoint(PE_FILE *pe, DWORD *ep) { IMAGE_SECTION_HEADER *epsec = NULL; if (!pe->optional_ptr) pe_get_optional(pe); if (!pe->num_sections || !pe->sections_ptr) pe_get_sections(pe); if (!pe->num_sections) return NULL; epsec = pe_rva2section(pe, *ep); if (!epsec) return NULL; if (!(epsec->Characteristics & 0x20)) return epsec; return NULL; }
int main(int argc, char *argv[]) { PE_FILE pe; FILE *fp = NULL; DWORD ep, stub_offset; int callbacks; double entropy; // unsigned int num_sections; if (argc < 2) { usage(); exit(1); } parse_options(argc, argv); // opcoes if ((fp = fopen(argv[argc-1], "rb")) == NULL) EXIT_ERROR("file not found or unreadable"); pe_init(&pe, fp); // inicializa o struct pe if (!is_pe(&pe)) EXIT_ERROR("not a valid PE file"); // File entropy entropy = calculate_entropy_file(&pe); if(entropy < 7.0) snprintf(value, MAX_MSG, "normal (%f)", entropy); else snprintf(value, MAX_MSG, "packed (%f)", entropy); output("file entropy", value); memset(&value, 0, sizeof(value)); if (!pe_get_optional(&pe)) return 1; ep = (pe.optional_ptr->_32 ? pe.optional_ptr->_32->AddressOfEntryPoint : (pe.optional_ptr->_64 ? pe.optional_ptr->_64->AddressOfEntryPoint : 0)); // fake ep if (ep == 0) snprintf(value, MAX_MSG, "null"); else if (pe_check_fake_entrypoint(&pe, &ep)) if (config.verbose) snprintf(value, MAX_MSG, "fake - va: %#x - raw: %#"PRIx64, ep, rva2ofs(&pe, ep)); else snprintf(value, MAX_MSG, "fake"); else if (config.verbose) snprintf(value, MAX_MSG, "normal - va: %#x - raw: %#"PRIx64, ep, rva2ofs(&pe, ep)); else snprintf(value, MAX_MSG, "normal"); output("entrypoint", value); // dos stub memset(&value, 0, sizeof(value)); if (!normal_dos_stub(&pe, &stub_offset)) { if (config.verbose) snprintf(value, MAX_MSG, "suspicious - raw: %#x", stub_offset); else snprintf(value, MAX_MSG, "suspicious"); } else snprintf(value, MAX_MSG, "normal"); output("DOS stub", value); // tls callbacks callbacks = pe_get_tls_callbacks(&pe); if (callbacks == 0) snprintf(value, MAX_MSG, "not found"); else if (callbacks == -1) snprintf(value, MAX_MSG, "found - no functions"); else if (callbacks >0) snprintf(value, MAX_MSG, "found - %d function(s)", callbacks); output("TLS directory", value); memset(&value, 0, sizeof(value)); // section analysis print_strange_sections(&pe); // no imagebase if (!normal_imagebase(&pe)) { if (config.verbose) snprintf(value, MAX_MSG, "suspicious - %#"PRIx64, pe.imagebase); else snprintf(value, MAX_MSG, "suspicious"); } else { if (config.verbose) snprintf(value, MAX_MSG, "normal - %#"PRIx64, pe.imagebase); else snprintf(value, MAX_MSG, "normal"); } output("imagebase", value); // invalid timestamp IMAGE_COFF_HEADER coff; if (!pe_get_coff(&pe, &coff)) EXIT_ERROR("unable to read coff header"); print_timestamp(&coff.TimeDateStamp); pe_deinit(&pe); return 0; }
int main(int argc, char *argv[]) { PE_FILE pe; FILE *fp = NULL; if (argc < 2) { usage(); exit(1); } parse_options(argc, argv); // opcoes if ((fp = fopen(argv[argc-1], "rb")) == NULL) EXIT_ERROR("file not found or unreadable"); pe_init(&pe, fp); // inicializa o struct pe if (!is_pe(&pe)) EXIT_ERROR("not a valid PE file"); // dos header if (config.dos || config.all_headers || config.all) { IMAGE_DOS_HEADER dos; if (pe_get_dos(&pe, &dos)) print_dos_header(&dos); else { EXIT_ERROR("unable to read DOS header"); } } // coff/file header if (config.coff || config.all_headers || config.all) { IMAGE_COFF_HEADER coff; if (pe_get_coff(&pe, &coff)) print_coff_header(&coff); else { EXIT_ERROR("unable to read COFF file header"); } } // optional header if (config.opt || config.all_headers || config.all) { if (pe_get_optional(&pe)) print_optional_header(&pe); else { EXIT_ERROR("unable to read Optional (Image) file header"); } } // directories if (config.dirs || config.all) { if (pe_get_directories(&pe)) print_directories(&pe); else { EXIT_ERROR("unable to read the Directories entry from Optional header"); } } // imports if (config.imports || config.all) { if (pe_get_directories(&pe)) print_imports(&pe); else { EXIT_ERROR("unable to read the Directories entry from Optional header"); } } // exports if (config.exports || config.all) { if (pe_get_directories(&pe)) print_exports(&pe); else { EXIT_ERROR("unable to read directories from optional header"); } } // sections if (config.all_sections || config.all) { if (pe_get_sections(&pe)) print_sections(&pe); else { EXIT_ERROR("unable to read sections"); } } // free pe_deinit(&pe); return 0; }