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); }