mirror of
https://github.com/TangentFoxy/love-pe.git
synced 2025-07-28 10:12:16 +00:00
Huge work on the resources extractor
This commit is contained in:
152
icon-changer.lua
152
icon-changer.lua
@@ -10,6 +10,25 @@ local bit = require("bit")
|
|||||||
|
|
||||||
local bor,band,lshift,rshift,tohex = bit.bor,bit.band,bit.lshift,bit.rshift,bit.tohex
|
local bor,band,lshift,rshift,tohex = bit.bor,bit.band,bit.lshift,bit.rshift,bit.tohex
|
||||||
|
|
||||||
|
local resourcesTypes = {
|
||||||
|
"Cursors",
|
||||||
|
"Bitmaps",
|
||||||
|
"Icons",
|
||||||
|
"Menus",
|
||||||
|
"Dialogs",
|
||||||
|
"String Tables",
|
||||||
|
"Font Directories",
|
||||||
|
"Fonts",
|
||||||
|
"Accelerators",
|
||||||
|
"Unformatted Resource Datas",
|
||||||
|
"Message Tables",
|
||||||
|
"Group Cursors",
|
||||||
|
"13",
|
||||||
|
"Group Icons",
|
||||||
|
"15",
|
||||||
|
"Version Information"
|
||||||
|
}
|
||||||
|
|
||||||
--==Internal Functions==--
|
--==Internal Functions==--
|
||||||
|
|
||||||
local function decodeNumber(str,bigEndian)
|
local function decodeNumber(str,bigEndian)
|
||||||
@@ -27,6 +46,109 @@ local function decodeNumber(str,bigEndian)
|
|||||||
return num
|
return num
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function convertUTF16(str16)
|
||||||
|
return str16--return str16:gsub("..","%1")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function convertRVA2Offset(RVA,Sections)
|
||||||
|
for id, Section in ipairs(Sections) do
|
||||||
|
if (Section.VirtualAddress <= RVA) and (RVA < (Section.VirtualAddress + Section.VirtualSize)) then
|
||||||
|
return Section.PointerToRawData + (RVA - Section.VirtualAddress)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error("FAILED "..tohex(RVA))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function readResourceDirectoryTable(exeFile,Sections,RootOffset,Level)
|
||||||
|
local Tree = {}
|
||||||
|
|
||||||
|
print("---readResourceDirectoryTable",RootOffset)
|
||||||
|
|
||||||
|
local Characteristics = decodeNumber(exeFile:read(4))
|
||||||
|
local TimeDateStamp = decodeNumber(exeFile:read(4))
|
||||||
|
local MajorVersion = decodeNumber(exeFile:read(2))
|
||||||
|
local MinorVersion = decodeNumber(exeFile:read(2))
|
||||||
|
local NumberOfNameEntries = decodeNumber(exeFile:read(2))
|
||||||
|
local NumberOfIDEntries = decodeNumber(exeFile:read(2))
|
||||||
|
|
||||||
|
print("Entries:", NumberOfNameEntries+NumberOfIDEntries)
|
||||||
|
|
||||||
|
--Parse Entries
|
||||||
|
for i=1,NumberOfNameEntries+NumberOfIDEntries do
|
||||||
|
print("Entry #"..i)
|
||||||
|
|
||||||
|
local Name = decodeNumber(exeFile:read(4))
|
||||||
|
local Offset = decodeNumber(exeFile:read(4))
|
||||||
|
|
||||||
|
print("Offset",tohex(Offset))
|
||||||
|
|
||||||
|
local ReturnOffset = exeFile:tell()
|
||||||
|
|
||||||
|
--Parse name/id for entry
|
||||||
|
if band(Name,0x80000000) ~= 0 then
|
||||||
|
print("String Name")
|
||||||
|
--Name is a string RVA
|
||||||
|
local NameOffset = convertRVA2Offset(RootOffset + band(Name,0x7FFFFFFF), Sections)
|
||||||
|
|
||||||
|
exeFile:seek(NameOffset)
|
||||||
|
|
||||||
|
local NameLength = decodeNumber(exeFile:read(2))
|
||||||
|
--Decode UTF-16LE string
|
||||||
|
--Name = exeFile:read(NameLength*2)
|
||||||
|
Name = string.char(math.random(65,90),math.random(65,90),math.random(65,90),math.random(65,90))
|
||||||
|
|
||||||
|
else
|
||||||
|
--Name is an ID
|
||||||
|
Name = band(Name,0xFFFF)
|
||||||
|
print("Number Name",Name)
|
||||||
|
|
||||||
|
if Level == 0 then
|
||||||
|
if resourcesTypes[Name] then
|
||||||
|
Name = resourcesTypes[Name]
|
||||||
|
print("# New name",Name)
|
||||||
|
else
|
||||||
|
print("Unkown type")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if band(Offset,0x80000000) ~= 0 then
|
||||||
|
print("Another Directory")
|
||||||
|
--Another directory
|
||||||
|
exeFile:seek(RootOffset + band(Offset,0x7FFFFFFF))
|
||||||
|
|
||||||
|
Tree[Name] = readResourceDirectoryTable(exeFile,Sections,RootOffset,Level+1)
|
||||||
|
else
|
||||||
|
print("Data Offset",RootOffset + band(Offset,0x7FFFFFFF))
|
||||||
|
--Data offset
|
||||||
|
exeFile:seek(RootOffset + band(Offset,0x7FFFFFFF))
|
||||||
|
|
||||||
|
local DataRVA = decodeNumber(exeFile:read(4))
|
||||||
|
local DataSize = decodeNumber(exeFile:read(4))
|
||||||
|
local DataCodepage = decodeNumber(exeFile:read(4))
|
||||||
|
|
||||||
|
print("Data",tohex(DataRVA),DataSize)
|
||||||
|
|
||||||
|
local ok, DataOffset = pcall(convertRVA2Offset,DataRVA,Sections)
|
||||||
|
|
||||||
|
if ok then
|
||||||
|
print("RVA OK")
|
||||||
|
exeFile:seek(DataOffset)
|
||||||
|
Tree[Name.."_P_"..tohex(DataCodepage)] = convertUTF16(exeFile:read(DataSize))
|
||||||
|
else
|
||||||
|
print("RVA Failed",DataOffset)
|
||||||
|
Tree[Name] = ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
exeFile:seek(ReturnOffset)
|
||||||
|
end
|
||||||
|
|
||||||
|
print("--End of tree")
|
||||||
|
|
||||||
|
return Tree
|
||||||
|
end
|
||||||
|
|
||||||
--==User API==--
|
--==User API==--
|
||||||
|
|
||||||
local icapi = {}
|
local icapi = {}
|
||||||
@@ -110,23 +232,29 @@ function icapi.extractIcon(exeFile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--Calculate the file offset to the resources data directory
|
--Calculate the file offset to the resources data directory
|
||||||
local ResourcesOffset
|
local ResourcesOffset = convertRVA2Offset(DataDirectories[3][1],Sections)
|
||||||
do
|
|
||||||
local RVA = DataDirectories[3][1]
|
|
||||||
for id, Section in ipairs(Sections) do
|
|
||||||
if (Section.VirtualAddress <= RVA) and (RVA < (Section.VirtualAddress + Section.VirtualSize)) then
|
|
||||||
ResourcesOffset = Section.PointerToRawData + (RVA - Section.VirtualAddress)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not ResourcesOffset then return error("Failed to calculate ResourcesOffset") end
|
|
||||||
|
|
||||||
--Seek into the resources data !
|
--Seek into the resources data !
|
||||||
exeFile:seek(ResourcesOffset)
|
exeFile:seek(ResourcesOffset)
|
||||||
|
|
||||||
print("Offset",ResourcesOffset)
|
print("Offset",ResourcesOffset)
|
||||||
|
|
||||||
|
local ResourcesTree = readResourceDirectoryTable(exeFile,Sections,ResourcesOffset,0)
|
||||||
|
|
||||||
|
local function writeTree(tree,path)
|
||||||
|
for k,v in pairs(tree) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
love.filesystem.createDirectory(path..k)
|
||||||
|
writeTree(v,path..k.."/")
|
||||||
|
else
|
||||||
|
love.filesystem.write(path..k,v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
writeTree(ResourcesTree,"/")
|
||||||
|
|
||||||
|
return "MEH"
|
||||||
end
|
end
|
||||||
|
|
||||||
return icapi
|
return icapi
|
Reference in New Issue
Block a user