diff --git a/external/source/DLLHijackAuditKit/01_StartAudit.bat b/external/source/DLLHijackAuditKit/01_StartAudit.bat new file mode 100644 index 0000000000..6080d42f1c --- /dev/null +++ b/external/source/DLLHijackAuditKit/01_StartAudit.bat @@ -0,0 +1,7 @@ +@set BASE=%~dp0 +@cd %BASE% + +@echo [*] Starting the audit... +@cscript /nologo audit.js + +pause \ No newline at end of file diff --git a/external/source/DLLHijackAuditKit/02_Analyze.bat b/external/source/DLLHijackAuditKit/02_Analyze.bat new file mode 100644 index 0000000000..f45331fba5 --- /dev/null +++ b/external/source/DLLHijackAuditKit/02_Analyze.bat @@ -0,0 +1,5 @@ +@set BASE=%~dp0 +@cd %BASE% +@cscript /nologo analyze.js + +pause \ No newline at end of file diff --git a/external/source/DLLHijackAuditKit/DLLAudit.pmc b/external/source/DLLHijackAuditKit/DLLAudit.pmc new file mode 100644 index 0000000000..e9b856644a Binary files /dev/null and b/external/source/DLLHijackAuditKit/DLLAudit.pmc differ diff --git a/external/source/DLLHijackAuditKit/README.txt b/external/source/DLLHijackAuditKit/README.txt new file mode 100644 index 0000000000..5210aab488 --- /dev/null +++ b/external/source/DLLHijackAuditKit/README.txt @@ -0,0 +1,14 @@ +Execute 01_StartAudit.bat as an administrative user. This will attempt to launch the +handler for all known file types. When this process is complete, access the open +ProcMon window and use the Save option from the File menu. Save the output to this +directory as a file named Logfile.CSV and make sure you choose the CSV file type. + +Once Logfile.CSV has been created, execute 02_Analyze.bat as an administrative user. +This will attempt to validate each result and generate a list of proof-of-concepts +within the Exploit subdirectory. For the best results, manually review the ProcMon +logs to ensure that various corner cases and other related vulnerabilities are not +missed. + +Have fun! + +-HD \ No newline at end of file diff --git a/external/source/DLLHijackAuditKit/analyze.js b/external/source/DLLHijackAuditKit/analyze.js new file mode 100644 index 0000000000..8a86a098ac --- /dev/null +++ b/external/source/DLLHijackAuditKit/analyze.js @@ -0,0 +1,194 @@ +/* DLLHijackAuditKit (C) 2010 Rapid7 LLC */ + +var oFso = new ActiveXObject("Scripting.FileSystemObject"); +var oShl = new ActiveXObject("WScript.Shell"); +var oCWD = oShl.CurrentDirectory + ""; + + +function print_status(msg) { + try { + WScript.StdOut.WriteLine("[*] "+ msg); + } catch(e) {} +} + +function process_list() { + var res = new Array(); + var wbemFlagReturnImmediately = 0x10; + var wbemFlagForwardOnly = 0x20; + var oWMI = GetObject("winmgmts:\\\\localhost\\root\\CIMV2"); + var cPID = oWMI.ExecQuery("SELECT * FROM Win32_Process", "WQL", wbemFlagReturnImmediately | wbemFlagForwardOnly); + var enumItems = new Enumerator(cPID); + for (; !enumItems.atEnd(); enumItems.moveNext()) { + var p = enumItems.item(); + if (p.ExecutablePath && p.ExecutablePath.toLowerCase().indexOf("taskmgr") != -1) continue; + res.push(p.ProcessId); + } + return res; +} + +function replace_payloads(dir, src) { + var base = oFso.GetFolder(dir); + var files = new Enumerator(base.files); + for (; !files.atEnd(); files.moveNext()) { + var entry = files.item().Name.toString().toLowerCase(); + if ( entry.indexOf("exploit.") == -1) { + if (entry.toString().indexOf(".exe") != -1) { + try { oFso.CopyFile(src + "\\runcalc.exe", dir + "\\" + entry); } catch(e) { } + } else { + try { oFso.CopyFile(src + "\\runcalc.dll", dir + "\\" + entry); } catch(e) { } + } + } + } + + var subs = new Enumerator(base.SubFolders); + for (; !subs.atEnd(); subs.moveNext()) { + var entry = (subs.item() + "").toLowerCase(); + replace_payloads(entry, src); + } +} + + +/* Process Logfile.CSV + a) Make a list of applications and their associated DLLs + b) Create a test case for each extension and each DLL + c) Run each test case and look for "exploited.txt" + d) Copy confirmed test cases to a new directory +*/ + + +var procs = process_list(); +print_status("Protecting " + procs.length + " processes"); + + +var apps = new Array(); +var fCSV = oFso.OpenTextFile("Logfile.CSV"); +var line = fCSV.ReadLine(); +var iPath = 4; +var iProc = 1; +var bits = line.split(","); + +// Determine which fields are what index +for (var i=0; i < bits.length; i++) { + if (bits[i].toLowerCase().indexOf("process name") != -1) { + iProc = i; + } + if (bits[i].toLowerCase().indexOf("path") != -1) { + iPath = i; + } +} + +// Parse the CSV into a map of each application's loads +while( ! fCSV.AtEndOfStream ) { + line = fCSV.ReadLine(); + bits = line.replace(/"/g, '').split(",") + + var vApp = bits[iProc].toLowerCase(); + var vPath = bits[iPath].toLowerCase(); + var vExt = vPath.replace(/.*DLLAudit\\ext\\/ig, '').split("\\")[0].toLowerCase(); + var vTgt = vPath.replace(/.*DLLAudit\\ext\\/ig, '').split("\\"); + vTgt.shift(); + + var vDll = vTgt.join("\\").toLowerCase(); + + if (! apps[vApp]) apps[vApp] = new Array(); + if (! apps[vApp][vExt]) apps[vApp][vExt] = new Array(); + apps[vApp][vExt][vDll] = true; +} + + +print_status("Generating and validating test cases..."); +try { oFso.CreateFolder(oCWD + "\\TestCases"); } catch(e) { } +try { oFso.CreateFolder(oCWD + "\\Exploits"); } catch(e) { } + +for (var tApp in apps) { + print_status(" Application: " + tApp); + + var aBase = oCWD + "\\TestCases\\" + tApp; + try { oFso.CreateFolder(aBase); } catch(e) { } + + for (var tExt in apps[tApp]) { + var eBase = aBase + "\\" + tExt; + var aExploited = new Array(); + + try { oFso.CreateFolder(eBase); } catch(e) { } + for (var tDll in apps[tApp][tExt]) { + var tBits = tDll.split("\\"); + var tName = tBits.pop(); + var dBase = eBase + "\\" + tName; + try { oFso.CreateFolder(dBase); } catch(e) { } + + if (aExploited[tName]) continue; + + // tDll may be a subdirectory + DLL + tPath = dBase; + for (var y = 0; y < tBits.length; y++) { + tPath = tPath + "\\" + tBits[y]; + try { oFso.CreateFolder(tPath); } catch(e) { } + } + tPath = tPath + "\\" + tName; + + try { + if (tName.toLowerCase().indexOf(".exe") != -1) { + oFso.CopyFile(oCWD + "\\runtest.exe", tPath); + } else { + oFso.CopyFile(oCWD + "\\runtest.dll", tPath); + } + } catch(e) { } + + // Create the actual test case file + try { + var a = oFso.CreateTextFile(dBase + "\\exploit." + tExt); + a.WriteLine("HOWDY!"); + a.Close(); + } catch(e) { } + + + try { + // Run the test case + oShl.CurrentDirectory = dBase; + oShl.Run("cmd.exe /c start exploit." + tExt, 0); + } catch(e) { } + WScript.Sleep(500); + + var nprocs = process_list(); + var cnt = 0; + while(nprocs.length == procs.length && cnt < 2) { + cnt++; + WScript.Sleep(500); + nprocs = process_list(); + } + + WScript.Sleep(500); + + var killer = "taskkill /F "; + for (var i=0; i < nprocs.length; i++) { + var found = false; + for (var x=0; x < procs.length; x++) { + if (nprocs[i] == procs[x]) { + found = true; + break; + } + } + if (found) continue; + killer = killer + "/PID " + nprocs[i] + " "; + } + oShl.Run(killer, 0, true); + + // Check for the file existence + if (oFso.FileExists(dBase + "\\exploited.txt")) { + + print_status("Successfully exploited " + tApp + " with ." + tExt + " using " + tName); + aExploited[tName] = true; + var xBase = oCWD + "\\Exploits\\" + tApp + "_" + tExt + "_" + tName; + try { oFso.CreateFolder(xBase); } catch(e) { } + try { oFso.CopyFolder(dBase + "\\*.*", xBase + "\\", true); } catch(e) { } + try { oFso.CopyFile(dBase + "\\*.*", xBase + "\\", true); } catch(e) { } + try { oFso.DeleteFile(xBase + "\\exploited.txt"); } catch(e) { } + replace_payloads(xBase, oCWD); + } + + } + + } +} + diff --git a/external/source/DLLHijackAuditKit/audit.js b/external/source/DLLHijackAuditKit/audit.js new file mode 100644 index 0000000000..43eb5c475f --- /dev/null +++ b/external/source/DLLHijackAuditKit/audit.js @@ -0,0 +1,156 @@ +/* DLLHijackAuditKit (C) 2010 Rapid7 LLC */ + +function print_status(msg) { + try { + WScript.StdOut.WriteLine("[*] "+ msg); + } catch(e) {} +} + +function process_list() { + var res = new Array(); + var wbemFlagReturnImmediately = 0x10; + var wbemFlagForwardOnly = 0x20; + var oWMI = GetObject("winmgmts:\\\\localhost\\root\\CIMV2"); + var cPID = oWMI.ExecQuery("SELECT * FROM Win32_Process", "WQL", wbemFlagReturnImmediately | wbemFlagForwardOnly); + var enumItems = new Enumerator(cPID); + for (; !enumItems.atEnd(); enumItems.moveNext()) { + var p = enumItems.item(); + if (p.ExecutablePath && p.ExecutablePath.toLowerCase().indexOf("taskmgr") != -1) continue; + res.push(p.ProcessId); + } + return res; +} + + + +var pause_interval = 100000; + +var oFso = new ActiveXObject("Scripting.FileSystemObject"); +var oShl = new ActiveXObject("WScript.Shell"); +var oLoc = new ActiveXObject("WbemScripting.SWbemLocator"); +var oSvc = oLoc.ConnectServer(null, "root\\default"); +var oReg = oSvc.Get("StdRegProv"); + +var oCWD = oShl.CurrentDirectory + ""; + +var oMethod = oReg.Methods_.Item("EnumKey"); +var oInParam = oMethod.InParameters.SpawnInstance_(); +oInParam.hDefKey = 0x80000002; +oInParam.sSubKeyName = "Software\\Classes"; + +var oOutParam = oReg.ExecMethod_(oMethod.Name, oInParam); +var aNames = oOutParam.sNames.toArray(); + + +try { oFso.CreateFolder("DLLAudit"); } catch(e) { } +try { oFso.CreateFolder("DLLAudit\\ext"); } catch(e) { } + + +if (! oFso.FileExists("procmon.exe")) { + print_status("Downloading procmon.exe from \\\\live.sysinternals.com ...") + try { oFso.CopyFile("\\\\live.sysinternals.com\\Tools\\procmon.exe", "procmon.exe"); } catch(e) {} +} + +if (! oFso.FileExists("procmon.exe")) { + print_status("Failed to download procmon.exe, copy here manually."); + WScript.Quit(); +} + + +print_status("Starting the process monitor..."); +oShl.Run("procmon.exe /AcceptEULA /Quiet /LoadConfig DLLAudit.pmc", 10); +WScript.Sleep(5000); + +var total = 0; +print_status("Creating test cases for each file extension..."); + +for (var i = 0; i < aNames.length; i++) { + if (aNames[i].substr(0,1) != ".") continue; + var ext = aNames[i].substr(1,32).toLowerCase(); + + if (ext == "com") continue; + if (ext == "pif") continue; + if (ext == "exe") continue; + if (ext == "bat") continue; + if (ext == "scr") continue; + if (ext == "dos") continue; + if (ext == "386") continue; + if (ext == "cpl") continue; + if (ext == "sys") continue; + if (ext == "dll") continue; + if (ext == "drv") continue; + if (ext == "rb") continue; + if (ext == "py") continue; + if (ext == "pl") continue; + if (ext == "crds") continue; + if (ext == "crd") continue; + if (ext == "pml") continue; + if (ext == "pmc") continue; + + try { oFso.CreateFolder("DLLAudit\\ext\\" + ext); } catch(e) { } + try { + var a = oFso.CreateTextFile("DLLAudit\\ext\\" + ext + "\\exploit." + ext); + a.WriteLine("HOWDY!"); + a.Close(); + } catch(e) { } + + total++; +} + +print_status("Created " + total + " test cases"); +var procs = process_list(); +print_status("Protecting " + procs.length + " processes"); + +var tries = 0; + +var base = oFso.GetFolder("DLLAudit\\ext"); +var subs = new Enumerator(base.SubFolders); +for (; !subs.atEnd(); subs.moveNext()) { + var path = subs.item() + ""; + var bits = path.split("\\"); + var ext = bits[bits.length - 1]; + + print_status("Auditing extension: " + ext); + oShl.CurrentDirectory = path + "\\"; + + oShl.Run("cmd.exe /c start exploit." + ext, 0); + WScript.Sleep(500); + + var nprocs = process_list(); + var cnt = 0; + while(nprocs.length == procs.length && cnt < 1) { + cnt++; + WScript.Sleep(500); + nprocs = process_list(); + } + + // If an application spawned, give it another second + // This helps with ProcMon memory usage as well + if (nprocs.length > procs.length) { + WScript.Sleep(1000); + } + + var killer = "taskkill /F "; + for (var i=0; i < nprocs.length; i++) { + var found = false; + for (var x=0; x < procs.length; x++) { + if (nprocs[i] == procs[x]) { + found = true; + break; + } + } + if (found) continue; + killer = killer + "/PID " + nprocs[i] + " "; + } + oShl.Run(killer, 0, true); + + tries++; + + if (tries % pause_interval == 0) { + print_status("Completed " + tries + " extensions, hit enter to continue.") + WScript.Stdin.ReadLine(); + print_status("Continuing...") + } +} + +print_status("Data collection phase complete, export Logfile.CSV from ProcMon.") diff --git a/external/source/DLLHijackAuditKit/runcalc.dll b/external/source/DLLHijackAuditKit/runcalc.dll new file mode 100644 index 0000000000..0521dff744 Binary files /dev/null and b/external/source/DLLHijackAuditKit/runcalc.dll differ diff --git a/external/source/DLLHijackAuditKit/runcalc.exe b/external/source/DLLHijackAuditKit/runcalc.exe new file mode 100644 index 0000000000..450df5401c Binary files /dev/null and b/external/source/DLLHijackAuditKit/runcalc.exe differ diff --git a/external/source/DLLHijackAuditKit/runtest.dll b/external/source/DLLHijackAuditKit/runtest.dll new file mode 100644 index 0000000000..918da9b6d4 Binary files /dev/null and b/external/source/DLLHijackAuditKit/runtest.dll differ diff --git a/external/source/DLLHijackAuditKit/runtest.exe b/external/source/DLLHijackAuditKit/runtest.exe new file mode 100644 index 0000000000..093b179bde Binary files /dev/null and b/external/source/DLLHijackAuditKit/runtest.exe differ