Created
August 26, 2015 04:01
-
-
Save nathan-osman/5b25da083ad5c6557e89 to your computer and use it in GitHub Desktop.
Display a list of imports in a PE file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) 2011 Nathan Osman | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to | |
// deal in the Software without restriction, including without limitation the | |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |
// sell copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in | |
// all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
// IN THE SOFTWARE. | |
#include <iostream> | |
#include <fstream> | |
#include <string.h> | |
using namespace std; | |
// Constants | |
const char program_name[] = "peimportinfo"; | |
void PrintHelp() | |
{ | |
cout << "Usage: " << program_name << " [-l] executable" << endl; | |
cout << " -l display only the imports in the output" << endl; | |
} | |
void PrintHeader() | |
{ | |
cout << "PEImportInfo" << endl; | |
cout << " \"The Import section analyzer for PE executables.\"" << endl << endl; | |
} | |
bool FindImports(ifstream & fin, bool only_imports) | |
{ | |
// All PE files begin with 'MZ', so make sure | |
// that we encounter those two bytes at the beginning | |
// of the file. | |
char magic[2]; | |
fin.read(magic, 2); | |
if(magic[0] != 'M' && magic[1] != 'Z') | |
{ | |
if(!only_imports) cout << "Error: file does not begin with 'MZ'." << endl; | |
return false; | |
} | |
// Skip to offset 60 and get the value for e_lfanew | |
// which is the offset of the PE header | |
fin.seekg(60, ios::beg); | |
long pe_hdr_offset; | |
fin.read((char *)&pe_hdr_offset, sizeof(long)); | |
// Now seek to that offset in the file + 128 | |
// (the offset to the import data directory entry) | |
fin.seekg(pe_hdr_offset + 128, ios::beg); | |
if(!only_imports) cout << "Finding data directory in PE header." << endl; | |
// Grab the address and length of the entry | |
long entry_address, num_entries; | |
fin.read((char *)&entry_address, sizeof(long)); | |
fin.read((char *)&num_entries, sizeof(long)); | |
num_entries /= 20; | |
if(!only_imports) cout << "Import table found at offset " << entry_address << " with " << num_entries << " entries." << endl; | |
// Jump to that position | |
fin.seekg(entry_address, ios::beg); | |
return true; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
// Make sure at least one argument was supplied | |
if(argc < 2 || argc > 3) | |
{ | |
PrintHeader(); | |
PrintHelp(); | |
return 1; | |
} | |
bool only_imports = false; | |
char * filename = argv[1]; | |
// Check for the -l option | |
if(argc == 3 and !strcmp("-l", argv[1])) | |
{ | |
only_imports = true; | |
filename = argv[2]; | |
} | |
// Print the header | |
if(!only_imports) PrintHeader(); | |
// Make an attempt to open the file | |
if(!only_imports) cout << "Opening file for reading..."; | |
ifstream fin; | |
fin.open(filename, ios::in); | |
if(fin.fail()) | |
{ | |
if(!only_imports) cout << "failed." << endl; | |
return 1; | |
} | |
else if(!only_imports) cout << "done." << endl; | |
// Now find the imports of the executable | |
if(FindImports(fin, only_imports)) | |
{ | |
size_t current_entry_offset = fin.tellg(); | |
// Continue reading through the entries until we | |
// reach an all-zero entry | |
while(true) | |
{ | |
// Read offset + 12 | |
fin.seekg(current_entry_offset + 12, ios::beg); | |
long name_offset; | |
fin.read((char *)&name_offset, sizeof(long)); | |
// Check if we've reached the end | |
if(name_offset == 0) break; | |
// Jump to that offset and read until '\0' | |
fin.seekg(name_offset, ios::beg); | |
// Read and print the name | |
if(!only_imports) cout << " - "; | |
while(true) | |
{ | |
char ch; | |
fin.get(ch); | |
if(ch == '\0') break; | |
else cout << ch; | |
} | |
// Print a newline and on to the next entry | |
cout << endl; | |
current_entry_offset += 20; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment