Last active
February 27, 2021 11:02
-
-
Save rakisaionji/4684d9079c685e4ad0a5f51a30ed44a2 to your computer and use it in GitHub Desktop.
Building IAT table from x86dbg exported databases and idata binary.
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
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