static void showVersion(pe_ctx_t *ctx, const NODE_PERES *node) { assert(node != NULL); int count = 0; const NODE_PERES *dataEntryNode; uint32_t nameOffset; bool found = false; while (node->lastNode != NULL) { node = node->lastNode; } while (node != NULL) { if (node->nodeType != RDT_DATA_ENTRY) { node = node->nextNode; continue; } count++; //if (count==19) dataEntryNode = lastNodeByType(node, RDT_DATA_ENTRY); if (dataEntryNode == NULL) return; nameOffset = node->rootNode->resource.directoryEntry->DirectoryName.name.NameOffset; if (nameOffset == 16) { found = true; break; } node = node->nextNode; } if (!found) return; const uint64_t offsetData = pe_rva2ofs(ctx, dataEntryNode->resource.dataEntry->offsetToData); const size_t dataEntrySize = dataEntryNode->resource.dataEntry->size; const char *buffer = LIBPE_PTR_ADD(ctx->map_addr, 32 + offsetData); if (!pe_can_read(ctx, buffer, dataEntrySize)) { // TODO: Should we report something? return; } VS_FIXEDFILEINFO *info = (VS_FIXEDFILEINFO *) buffer; char value[MAX_MSG]; //snprintf(value, MAX_MSG, "%d", totalCount); snprintf(value, MAX_MSG, "%u.%u.%u.%u", (unsigned int)(info->dwProductVersionMS & 0xffff0000) >> 16, (unsigned int)info->dwProductVersionMS & 0x0000ffff, (unsigned int)(info->dwProductVersionLS & 0xffff0000) >> 16, (unsigned int)info->dwProductVersionLS & 0x0000ffff); output("File Version", value); }
static void saveResource(pe_ctx_t *ctx, const NODE_PERES *node) { assert(node != NULL); const NODE_PERES *dataEntryNode = lastNodeByType(node, RDT_DATA_ENTRY); if (dataEntryNode == NULL) return; const uint64_t offsetData = pe_rva2ofs(ctx, dataEntryNode->resource.dataEntry->offsetToData); const size_t dataEntrySize = dataEntryNode->resource.dataEntry->size; const char *buffer = LIBPE_PTR_ADD(ctx->map_addr, offsetData); if (LIBPE_IS_PAST_THE_END(ctx, buffer, dataEntrySize)) { // TODO: Should we report something? return; } struct stat statDir; if (stat(resourceDir, &statDir) == -1) mkdir(resourceDir, 0700); char dirName[100]; memset(dirName, 0, sizeof(dirName)); uint32_t nameOffset = node->rootNode->resource.directoryEntry->DirectoryName.name.NameOffset; const RESOURCE_ENTRY *resourceEntry = getResourceEntryByNameOffset(nameOffset); if (resourceEntry != NULL) { snprintf(dirName, sizeof(dirName), "%s/%s", resourceDir, resourceEntry->dirName); } else { snprintf(dirName, sizeof(dirName), "%s", resourceDir); } // TODO(jweyrich): Would it make sense to hardcode `RDT_LEVEL2` rather than use `node->nodeLevel-1` ? const NODE_PERES *nameNode = lastNodeByTypeAndLevel(node, RDT_DIRECTORY_ENTRY, node->nodeLevel - 1); //printf("%d\n", nameNode->resource.directoryEntry->DirectoryName.name.NameOffset); if (stat(dirName, &statDir) == -1) mkdir(dirName, 0700); char relativeFileName[100]; memset(relativeFileName, 0, sizeof(relativeFileName)); snprintf(relativeFileName, sizeof(relativeFileName), "%s/" "%" PRIu32 "%s", dirName, nameNode->resource.directoryEntry->DirectoryName.name.NameOffset, resourceEntry != NULL ? resourceEntry->extension : ".bin"); FILE *fp = fopen(relativeFileName, "wb+"); if (fp == NULL) { // TODO: Should we report something? return; } fwrite(buffer, dataEntrySize, 1, fp); fclose(fp); output("Save On", relativeFileName); }
int main(int argc, char *argv[]) { //PEV_INITIALIZE(); if (argc != 3) { usage(); return EXIT_FAILURE; } parse_options(argc, argv); // opcoes pe_ctx_t ctx; pe_err_e err = pe_load_file(&ctx, argv[2]); if (err != LIBPE_E_OK) { pe_error_print(stderr, err); return EXIT_FAILURE; } uint64_t rva = (uint64_t)strtoll(argv[1], NULL, 0); if (!rva) EXIT_ERROR("invalid RVA"); err = pe_parse(&ctx); if (err != LIBPE_E_OK) { pe_error_print(stderr, err); return EXIT_FAILURE; } if (!pe_is_pe(&ctx)) EXIT_ERROR("not a valid PE file"); printf("%#llx\n", pe_rva2ofs(&ctx, rva)); // libera a memoria pe_unload(&ctx); //PEV_FINALIZE(); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { pev_config_t config; PEV_INITIALIZE(&config); if (argc < 2) { usage(); exit(EXIT_FAILURE); } output_set_cmdline(argc, argv); options_t *options = parse_options(argc, argv); // opcoes const char *path = argv[argc-1]; pe_ctx_t ctx; pe_err_e err = pe_load_file(&ctx, path); if (err != LIBPE_E_OK) { pe_error_print(stderr, err); return EXIT_FAILURE; } err = pe_parse(&ctx); if (err != LIBPE_E_OK) { pe_error_print(stderr, err); return EXIT_FAILURE; } if (!pe_is_pe(&ctx)) EXIT_ERROR("not a valid PE file"); const uint64_t ep_offset = pe_rva2ofs(&ctx, ctx.pe.entrypoint); if (ep_offset == 0) EXIT_ERROR("unable to get entrypoint offset"); FILE *dbfile = NULL; if (!loaddb(&dbfile, options)) fprintf(stderr, "warning: without valid database file, %s will search in generic mode only\n", PROGRAM); char value[MAX_MSG]; // TODO(jweyrich): Create a new API to retrieve map_addr. // TODO(jweyrich): Should we use `LIBPE_PTR_ADD(ctx->map_addr, ep_offset)` instead? const unsigned char *pe_data = ctx.map_addr; // packer by signature if (compare_signature(pe_data, ep_offset, dbfile, value, sizeof(value))) ; // generic detection else if (generic_packer(&ctx, ep_offset)) snprintf(value, MAX_MSG, "generic"); else snprintf(value, MAX_MSG, "no packer found"); output_open_document(); output("packer", value); output_close_document(); if (dbfile != NULL) fclose(dbfile); // libera a memoria free_options(options); // free err = pe_unload(&ctx); if (err != LIBPE_E_OK) { pe_error_print(stderr, err); return EXIT_FAILURE; } PEV_FINALIZE(&config); return EXIT_SUCCESS; }
static NODE_PERES * discoveryNodesPeres(pe_ctx_t *ctx) { #ifdef LIBPE_ENABLE_OUTPUT_COMPAT_WITH_V06 typedef struct { ImageDirectoryEntry entry; const char * const name; } ImageDirectoryEntryName; static const ImageDirectoryEntryName directoryEntryNames[] = { { IMAGE_DIRECTORY_ENTRY_EXPORT, "Export Table" }, // "Export directory", { IMAGE_DIRECTORY_ENTRY_IMPORT, "Import Table" }, // "Import directory", { IMAGE_DIRECTORY_ENTRY_RESOURCE, "Resource Table" }, // "Resource directory", { IMAGE_DIRECTORY_ENTRY_EXCEPTION, "Exception Table" }, // "Exception directory", { IMAGE_DIRECTORY_ENTRY_SECURITY, "Certificate Table" }, // "Security directory", { IMAGE_DIRECTORY_ENTRY_BASERELOC, "Base Relocation Table" }, // "Base relocation table", { IMAGE_DIRECTORY_ENTRY_DEBUG, "Debug" }, // "Debug directory", { IMAGE_DIRECTORY_ENTRY_ARCHITECTURE, "Architecture" }, // "Architecture-specific data", { IMAGE_DIRECTORY_ENTRY_GLOBALPTR, "Global Ptr" }, // "Global pointer", { IMAGE_DIRECTORY_ENTRY_TLS, "Thread Local Storage (TLS)"}, // "Thread local storage (TLS) directory", { IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, "Load Config Table" }, // "Load configuration directory", { IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT, "Bound Import" }, // "Bound import directory", { IMAGE_DIRECTORY_ENTRY_IAT, "Import Address Table (IAT)"}, // "Import address table (IAT)", { IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, "Delay Import Descriptor" }, // "Delay import table", { IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, "CLR Runtime Header" }, // "COM descriptor table" { IMAGE_DIRECTORY_RESERVED, "" } // "Reserved" }; //static const size_t max_directory_entry = LIBPE_SIZEOF_ARRAY(names); #endif const IMAGE_DATA_DIRECTORY * const resourceDirectory = pe_directory_by_entry(ctx, IMAGE_DIRECTORY_ENTRY_RESOURCE); if (resourceDirectory == NULL || resourceDirectory->Size == 0) return NULL; uint64_t resourceDirOffset = pe_rva2ofs(ctx, resourceDirectory->VirtualAddress); char s[MAX_MSG]; if (resourceDirectory->Size != 0) { snprintf(s, MAX_MSG, "%#x (%d bytes)", resourceDirectory->VirtualAddress, resourceDirectory->Size); #ifdef LIBPE_ENABLE_OUTPUT_COMPAT_WITH_V06 output(directory_names[IMAGE_DIRECTORY_ENTRY_RESOURCE], s); // Resource table #else output(pe_directory_name(IMAGE_DIRECTORY_ENTRY_RESOURCE), s); // Resource table #endif //printf("Offset by RVA: 0x%x\n\n", resourceDirOffset); } uintptr_t offset = resourceDirOffset; void *ptr = LIBPE_PTR_ADD(ctx->map_addr, offset); if (LIBPE_IS_PAST_THE_END(ctx, ptr, sizeof(IMAGE_RESOURCE_DIRECTORY))) { // TODO: Should we report something? return NULL; } NODE_PERES *node = malloc_s(sizeof(NODE_PERES)); node->lastNode = NULL; // root node->nodeType = RDT_RESOURCE_DIRECTORY; node->nodeLevel = RDT_LEVEL1; node->resource.resourceDirectory = ptr; //showNode(node); for (int i = 1, offsetDirectory1 = 0; i <= (lastNodeByTypeAndLevel(node, RDT_RESOURCE_DIRECTORY, RDT_LEVEL1)->resource.resourceDirectory->NumberOfNamedEntries + lastNodeByTypeAndLevel(node, RDT_RESOURCE_DIRECTORY, RDT_LEVEL1)->resource.resourceDirectory->NumberOfIdEntries); i++) { offsetDirectory1 += (i == 1) ? 16 : 8; offset = resourceDirOffset + offsetDirectory1; ptr = LIBPE_PTR_ADD(ctx->map_addr, offset); if (LIBPE_IS_PAST_THE_END(ctx, ptr, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) { // TODO: Should we report something? goto _error; } node = createNode(node, RDT_DIRECTORY_ENTRY); NODE_PERES *rootNode = node; node->rootNode = rootNode; node->nodeLevel = RDT_LEVEL1; node->resource.directoryEntry = ptr; //showNode(node); const NODE_PERES * lastDirectoryEntryNodeAtLevel1 = lastNodeByTypeAndLevel(node, RDT_DIRECTORY_ENTRY, RDT_LEVEL1); if (lastDirectoryEntryNodeAtLevel1->resource.directoryEntry->DirectoryData.data.DataIsDirectory) { offset = resourceDirOffset + lastDirectoryEntryNodeAtLevel1->resource.directoryEntry->DirectoryData.data.OffsetToDirectory; ptr = LIBPE_PTR_ADD(ctx->map_addr, offset); if (LIBPE_IS_PAST_THE_END(ctx, ptr, sizeof(IMAGE_RESOURCE_DIRECTORY))) { // TODO: Should we report something? goto _error; } node = createNode(node, RDT_RESOURCE_DIRECTORY); node->rootNode = (NODE_PERES *)lastDirectoryEntryNodeAtLevel1; node->nodeLevel = RDT_LEVEL2; node->resource.resourceDirectory = ptr; //showNode(node); for (int j = 1, offsetDirectory2 = 0; j <= (lastNodeByTypeAndLevel(node, RDT_RESOURCE_DIRECTORY, RDT_LEVEL2)->resource.resourceDirectory->NumberOfNamedEntries + lastNodeByTypeAndLevel(node, RDT_RESOURCE_DIRECTORY, RDT_LEVEL2)->resource.resourceDirectory->NumberOfIdEntries); j++) { offsetDirectory2 += (j == 1) ? 16 : 8; offset = resourceDirOffset + lastNodeByTypeAndLevel(node, RDT_DIRECTORY_ENTRY, RDT_LEVEL1)->resource.directoryEntry->DirectoryData.data.OffsetToDirectory + offsetDirectory2; ptr = LIBPE_PTR_ADD(ctx->map_addr, offset); if (LIBPE_IS_PAST_THE_END(ctx, ptr, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) { // TODO: Should we report something? goto _error; } node = createNode(node, RDT_DIRECTORY_ENTRY); node->rootNode = rootNode; node->nodeLevel = RDT_LEVEL2; node->resource.directoryEntry = ptr; //showNode(node); offset = resourceDirOffset + node->resource.directoryEntry->DirectoryData.data.OffsetToDirectory; // posiciona em 0x72 ptr = LIBPE_PTR_ADD(ctx->map_addr, offset); if (LIBPE_IS_PAST_THE_END(ctx, ptr, sizeof(IMAGE_RESOURCE_DIRECTORY))) { // TODO: Should we report something? goto _error; } node = createNode(node, RDT_RESOURCE_DIRECTORY); node->rootNode = rootNode; node->nodeLevel = RDT_LEVEL3; node->resource.resourceDirectory = ptr; //showNode(node); offset += sizeof(IMAGE_RESOURCE_DIRECTORY); for (int y = 1; y <= (lastNodeByTypeAndLevel(node, RDT_RESOURCE_DIRECTORY, RDT_LEVEL3)->resource.resourceDirectory->NumberOfNamedEntries + lastNodeByTypeAndLevel(node, RDT_RESOURCE_DIRECTORY, RDT_LEVEL3)->resource.resourceDirectory->NumberOfIdEntries); y++) { ptr = LIBPE_PTR_ADD(ctx->map_addr, offset); if (LIBPE_IS_PAST_THE_END(ctx, ptr, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) { // TODO: Should we report something? goto _error; } node = createNode(node, RDT_DIRECTORY_ENTRY); node->rootNode = rootNode; node->nodeLevel = RDT_LEVEL3; node->resource.directoryEntry = ptr; //showNode(node); offset = resourceDirOffset + node->resource.directoryEntry->DirectoryName.name.NameOffset; ptr = LIBPE_PTR_ADD(ctx->map_addr, offset); if (LIBPE_IS_PAST_THE_END(ctx, ptr, sizeof(IMAGE_RESOURCE_DATA_STRING))) { // TODO: Should we report something? goto _error; } node = createNode(node, RDT_DATA_STRING); node->rootNode = rootNode; node->nodeLevel = RDT_LEVEL3; node->resource.dataString = ptr; //showNode(node); offset = resourceDirOffset + node->lastNode->resource.directoryEntry->DirectoryData.data.OffsetToDirectory; ptr = LIBPE_PTR_ADD(ctx->map_addr, offset); if (LIBPE_IS_PAST_THE_END(ctx, ptr, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) { // TODO: Should we report something? goto _error; } node = createNode(node, RDT_DATA_ENTRY); node->rootNode = rootNode; node->nodeLevel = RDT_LEVEL3; node->resource.dataEntry = ptr; //showNode(node); offset += sizeof(IMAGE_RESOURCE_DATA_ENTRY); } } } } return node; _error: if (node != NULL) freeNodes(node); return NULL; }