Skip to content

Instantly share code, notes, and snippets.

@nathan-osman
Created August 26, 2015 04:01
Show Gist options
  • Save nathan-osman/5b25da083ad5c6557e89 to your computer and use it in GitHub Desktop.
Save nathan-osman/5b25da083ad5c6557e89 to your computer and use it in GitHub Desktop.
Display a list of imports in a PE file
// 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