-
Notifications
You must be signed in to change notification settings - Fork 2
LUA script, convert DUMPBIN exports to fasmg
Rickey Bowers Jr edited this page Feb 9, 2021
·
4 revisions
Kind of general solution to consume the DUMPBIN /export output.
- standard names are given their identity symbolic name
- ordinal exports are prefixed with the DLL ex: "my.dll.Ordinal#"
- mangled exports are also named like an ordinal export
(often these need a custom naming scheme) - SystemFunction# are given unique symbolic names ex: "my.dll.SystemFunction#"
function file_exists(file)
local f = io.open(file, "rb")
if f then f:close() end
return f ~= nil
end
if not file_exists(arg[1]) then
print("usage: lua54.exe " .. arg[0] .. ' "<filename>"')
print("\tunable to use: " .. arg[1])
return
end
-- to generate file to process use: dumpbin /EXPORTS My.DLL >My.exports
-- (not compatible with objdump)
out,baseName,ordinal,header = "","",-1,true
for line in io.lines(arg[1]) do
if header then
if string.find(line,"Dump of file ")==1 then
baseName = string.match(line,"[^\\/]+%.[^.]+$")
elseif string.find(line,"File Type: ")==1 then
if not string.find(line,"DLL") then return end
elseif string.find(line," time date stamp")==13 then
-- TODO: output time date stamp ; file version ; hash ; comment to identify DLL version
elseif string.find(line," ordinal hint RVA name")==1 then
-- setup for next phase of table read
header,skip = false,0
-- must have filename for DLL
if string.len(baseName) < 1 then return end
out = "import '" .. baseName .. "',\\\n"
end
else
if string.len(line) > 0 then
ordinal = 0+string.match(line,"%d+")
funString = string.match(line,"[%p%w]+",27)
if funString == "[NONAME]" then
-- must import with ordinal number
out = out .. string.format("%s.Ordinal%d,%d,\\\n", baseName, ordinal, ordinal)
elseif string.find(funString,"SystemFunction")==1 then
-- try to insure label is unique (many DLLs have SystemFunction's)
out = out .. string.format("%s.%s,'%s',\\\n", baseName, funString, funString)
elseif string.match(funString,"^?.*Z$") then
-- decorated names need a personal touch until a demangler is programmed
out = out .. string.format("%s.Ordinal%d,'%s',\\\n", baseName, ordinal, funString)
else
-- most will default to labels the same as their import string
out = out .. string.format("%s,'%s',\\\n", funString, funString)
end
else
skip = skip + 1
if skip > 1 then
-- TODO: trim final ",\\\n" from out
io.write(out)
return
end
end
end
end
One way to use the above script (dumpbin_to_fasmg.lua) is from CMD prompt:
@REM pass in the search path to process or single file
for %%G in (%*) do (
dumpbin /EXPORTS "%%G" >"%%~nG.exports"
lua54 dumpbin_to_fasmg.lua "%%~nG.exports" >"%%~nG.fasmg"
del "%%~nG.exports"
)
Some care should be taken using DLLs directly. There are DLLs that export addresses for things other than functions. For example, COM interface GUIDs. Additionally, some APIs have their own functions for returning different versions of interfaces. We see this in modern graphics APIs.