Skip to content

Instantly share code, notes, and snippets.

@rakisaionji
Last active February 27, 2021 11:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rakisaionji/4684d9079c685e4ad0a5f51a30ed44a2 to your computer and use it in GitHub Desktop.
Save rakisaionji/4684d9079c685e4ad0a5f51a30ed44a2 to your computer and use it in GitHub Desktop.
Building IAT table from x86dbg exported databases and idata binary.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace iatpecker
{
class Program
{
struct ImportRecord
{
public string Module;
public string Function;
}
static List<long> dictDiscards = new List<long>();
static List<ImportRecord> dictPriority = new List<ImportRecord>();
static Dictionary<long, ImportRecord> dictImports = new Dictionary<long, ImportRecord>();
static void LoadPriorityList(string fileName)
{
String readingLine;
using (var fileStream = File.OpenRead(fileName))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true))
{
while ((readingLine = streamReader.ReadLine()) != null)
{
var importParam = readingLine.Split(',');
if (importParam.Length < 2) continue;
var importRecord = default(ImportRecord);
importRecord.Module = importParam[0].Trim().ToLower();
importRecord.Function = importParam[1].Trim();
var queryPriority = dictPriority.Where(
r => r.Module.ToLower().Equals(importRecord.Module)
&& r.Function.Equals(importRecord.Function));
if (queryPriority.Count() == 0) dictPriority.Add(importRecord);
}
}
}
static void LoadImportsLists(string importsDir)
{
String readingLine, importModule;
var importCsvs = Directory.GetFiles(importsDir, "*.csv", SearchOption.AllDirectories);
foreach (var importCsv in importCsvs)
{
string moduleName;
var importCsvInfo = new FileInfo(importCsv);
using (var fileStream = File.OpenRead(importCsv))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true))
{
if ((readingLine = streamReader.ReadLine()) != null)
{
var fileName = importCsvInfo.Name;
moduleName = fileName.Substring(0, fileName.Length - 4).ToLower();
if (!moduleName.EndsWith(".dll")) importModule = String.Concat(moduleName, ".dll");
else importModule = moduleName;
}
else
{
importModule = "";
continue;
}
while ((readingLine = streamReader.ReadLine()) != null)
{
var importParam = readingLine.Split(',');
if (importParam.Length < 4) continue;
if (!importParam[1].Trim().ToLower().Equals("export")) continue;
var importOrdinal = importParam[2].Trim();
if (importOrdinal.Equals("0")) continue;
var importAddress = Convert.ToInt64(importParam[0], 16);
var importFunction = importParam[3].Trim();
if (dictImports.ContainsKey(importAddress))
{
if (!dictDiscards.Contains(importAddress)) dictDiscards.Add(importAddress);
var queryPriority = dictPriority.Where(
r => r.Module.Equals(importModule)
&& (r.Function.Equals(importFunction)
|| r.Function.Equals(String.Format("Ordinal#{0}", importOrdinal))));
if (queryPriority.Count() > 0)
{
dictImports.Remove(importAddress);
// In case of Ordinal import reference
var query = dictPriority.Where(
r => r.Module.Equals(importModule)
&& r.Function.Equals(importFunction));
if (queryPriority.Count() == 0)
{
var importRecord2 = default(ImportRecord);
importRecord2.Module = importModule;
importRecord2.Function = importFunction;
dictPriority.Add(importRecord2);
}
}
else
{
Console.WriteLine("Duplicate import entry : 0x{0,-16:X16} {1}::{2}()",
importAddress, moduleName, importFunction);
continue;
}
}
var importRecord = default(ImportRecord);
importRecord.Module = importModule;
importRecord.Function = importFunction;
dictImports.Add(importAddress, importRecord);
}
}
}
}
static void MakeIatTableFile(string iatBinary, string iatOutput, long iatBase, long iatStart, long iatEnd, bool is64bit = false)
{
using (var inputFile = File.OpenRead(iatBinary))
using (var outputFile = File.CreateText(iatOutput))
using (var inputStream = new BinaryReader(inputFile))
{
inputFile.Seek(iatStart - iatBase, SeekOrigin.Begin);
outputFile.WriteLine("{0,-18} {1,-18} {2,-20} {3}", "IAT", "Call", "Module", "Function");
outputFile.WriteLine("------------------ ------------------ -------------------- --------------------");
var position = iatStart;
while (position < iatEnd)
{
var address = (is64bit) ? inputStream.ReadInt64() : Convert.ToInt64(inputStream.ReadUInt32());
if (address != 0)
{
if (dictImports.ContainsKey(address))
{
var dictImport = dictImports[address];
outputFile.WriteLine("0x{0,-16:X16} 0x{1,-16:X16} {2,-20} {3}",
position, address, dictImport.Module, dictImport.Function);
if (dictDiscards.Contains(address))
{
var function = dictImport.Function;
var query = dictPriority.Where(
r => r.Module.Equals(dictImport.Module)
&& r.Function.Equals(function));
if (query.Count() == 0) function = "...";
Console.WriteLine("Duplicate address found : 0x{0,-16:X16} 0x{1,-16:X16} {2,-20} {3}",
position, address, dictImport.Module, function);
}
}
else
{
Console.WriteLine("Import entry not found : 0x{0,-16:X16} 0x{1,-16:X16} {2,-20} {3}",
position, address, "???", "??????");
}
}
position += (is64bit) ? 8 : 4;
}
}
}
static void Main(string[] args)
{
var iatbin = @"idata.bin";
var iatfile = @"iattable.txt";
var iatpriority = @"iatpriority.txt";
var importsDir = @"imports\";
var is64bit = false; // 32-bit
var iatbase = 0x02177000L;
var iatstart = 0x0217885CL;
var iatend = 0x02179E5CL;
if (!String.IsNullOrEmpty(iatpriority))
{
if (File.Exists(iatpriority))
{
LoadPriorityList(iatpriority);
}
else
{
Console.WriteLine("Warning : Functions Priority List does not exists");
}
}
if (Directory.Exists(importsDir))
{
LoadImportsLists(importsDir);
if (File.Exists(iatbin))
{
MakeIatTableFile(iatbin, iatfile, iatbase, iatstart, iatend, is64bit);
}
else
{
Console.WriteLine("Critical Error : Imports Data does not exists");
}
}
else
{
Console.WriteLine("Critical Error : Imports Directory not found");
}
Console.ReadKey();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment