Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Parsing data from the PE Headers

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Tutorials -> LUA Tutorials
View previous topic :: View next topic  
Author Message
juntalis
Newbie cheater
Reputation: 2

Joined: 13 Mar 2013
Posts: 11

PostPosted: Sat Apr 16, 2016 4:42 am    Post subject: Parsing data from the PE Headers Reply with quote

I wrote a script a while back that required me to change some logic depending on the executable's checksum, so I decided to write up a quick example:

Code:

--- Reverse a keyed table of numeric values and add the resulting pairs
-- to the original table.
-- @tparam {[string]=int,...} kvargs target keyed table
local function enum(kvargs)
   local result = {}
   local key = next(kvargs)
   while key ~= nil do
      local value = kvargs[key]
      result[key] = value
      result[value] = key
      key = next(kvargs, key)
   end
   return result
end

---
-- Potential values for OptionalHeader.Subsystem
-- @table IMAGE_SUBSYSTEM
-- @tfield[value=0x00] int UNKNOWN Value of IMAGE_SUBSYSTEM_UNKNOWN
-- @tfield[value=0x01] int NATIVE Value of IMAGE_SUBSYSTEM_NATIVE
-- @tfield[value=0x02] int WINDOWS_GUI Value of IMAGE_SUBSYSTEM_WINDOWS_GUI
-- @tfield[value=0x03] int WINDOWS_CUI Value of IMAGE_SUBSYSTEM_WINDOWS_CUI
-- @tfield[value=0x05] int OS2_CUI Value of IMAGE_SUBSYSTEM_OS2_CUI
-- @tfield[value=0x07] int POSIX_CUI Value of IMAGE_SUBSYSTEM_POSIX_CUI
-- @tfield[value=0x08] int NATIVE_WINDOWS Value of IMAGE_SUBSYSTEM_NATIVE_WINDOWS
-- @tfield[value=0x09] int WINDOWS_CE_GUI Value of IMAGE_SUBSYSTEM_WINDOWS_CE_GUI
-- @tfield[value=0x0A] int EFI_APPLICATION Value of IMAGE_SUBSYSTEM_EFI_APPLICATION
-- @tfield[value=0x0B] int EFI_BOOT_SERVICE_DRIVER Value of IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
-- @tfield[value=0x0C] int EFI_RUNTIME_DRIVER Value of IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
-- @tfield[value=0x0D] int EFI_ROM Value of IMAGE_SUBSYSTEM_EFI_ROM
-- @tfield[value=0x0E] int XBOX Value of IMAGE_SUBSYSTEM_XBOX
-- @tfield[value=0x10] int WINDOWS_BOOT_APPLICATION Value of IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
IMAGE_SUBSYSTEM = enum {
   UNKNOWN                  = 0x00, -- IMAGE_SUBSYSTEM_UNKNOWN
   NATIVE                   = 0x01, -- IMAGE_SUBSYSTEM_NATIVE
   WINDOWS_GUI              = 0x02, -- IMAGE_SUBSYSTEM_WINDOWS_GUI
   WINDOWS_CUI              = 0x03, -- IMAGE_SUBSYSTEM_WINDOWS_CUI
   OS2_CUI                  = 0x05, -- IMAGE_SUBSYSTEM_OS2_CUI
   POSIX_CUI                = 0x07, -- IMAGE_SUBSYSTEM_POSIX_CUI
   NATIVE_WINDOWS           = 0x08, -- IMAGE_SUBSYSTEM_NATIVE_WINDOWS
   WINDOWS_CE_GUI           = 0x09, -- IMAGE_SUBSYSTEM_WINDOWS_CE_GUI
   EFI_APPLICATION          = 0x0A, -- IMAGE_SUBSYSTEM_EFI_APPLICATION
   EFI_BOOT_SERVICE_DRIVER  = 0x0B, -- IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
   EFI_RUNTIME_DRIVER       = 0x0C, -- IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
   EFI_ROM                  = 0x0D, -- IMAGE_SUBSYSTEM_EFI_ROM
   XBOX                     = 0x0E, -- IMAGE_SUBSYSTEM_XBOX
   WINDOWS_BOOT_APPLICATION = 0x10  -- IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
}

do
   --- Local cache
   local _L = {
      lpNtHdrs = {},
      maGetters = {},
   }
   
   --- Field offsets
   local NT_HEADER_FADDR_OFFSET = 0x3C -- IMAGE_DOS_HEADER.e_lfanew
   local OPTIONAL_HEADER_OFFSET = 0x18 -- IMAGE_NT_HEADERS.OptionalHeader
   local IMAGE_CHECKSUM_OFFSET  = 0x40 -- IMAGE_OPTIONAL_HEADER.CheckSum
   local IMAGE_SUBSYSTEM_OFFSET = 0x44 -- IMAGE_OPTIONAL_HEADER.Subsystem

   local readDword = readInteger
   local function readWord(address)
      local bytes = readBytes(address, 2, true)
      return byteTableToWord(bytes)
   end

   local function moduleAddressGetter(module)
      -- Check the cache. If non-existent, generate our
      -- handler and cache it.
      if not _L.maGetters[module] then
         local prefix = module .. '+'
         _L.maGetters[module] = function(offset)
            if type(offset) == 'number' then
               offset = string.format('%X', offset)
            end
            return getAddress(prefix .. offset)
         end
      end
      return _L.maGetters[module]
   end

   local function getNtHeader(module)
      -- Module name is case-insensitive
      module = string.lower(module)
      
      -- Check the cache. If non-existent, resolve the address
      -- of our NT_HEADER and cache it.
      if not _L.lpNtHdrs[module] then
         local moduleAddress = moduleAddressGetter(module)
         local address = moduleAddress(NT_HEADER_FADDR_OFFSET)
         local offset = readDword(address)
         _L.lpNtHdrs[module] = moduleAddress(offset)
      end
      return _L.lpNtHdrs[module]
   end
   
   local function getOptionalHeader(module)
      return getNtHeader(module) + OPTIONAL_HEADER_OFFSET
   end
   
   --- Get value of IMAGE_NT_HEADERS.OptionalHeader.CheckSum
   local function getCheckSum(module)
      local address = getOptionalHeader(module) + IMAGE_CHECKSUM_OFFSET
      local checksum = readDword(address)
      return string.format('%08X', checksum)
   end
   
   --- Get value of IMAGE_NT_HEADERS.OptionalHeader.Subsystem
   local function getSubsystem(module)
      local address = getOptionalHeader(module)
      local subsystem = readWord(address + IMAGE_SUBSYSTEM_OFFSET)
      return IMAGE_SUBSYSTEM[subsystem], subsystem
   end

   _G.getModuleCheckSum = getCheckSum
   _G.getModuleSubsystem = getSubsystem
end

local moduleName = 'mygame.exe'
print('CheckSum', '=>', getModuleCheckSum(moduleName))
print('Subsystem', '=>', string.format('%s [%02X]', getModuleSubsystem(moduleName)))


Example output:
Code:

CheckSum => 02C2154E
Subsystem => WINDOWS_GUI [02]


If I ever find the time and motivation, I'd like to write a more sophisticated example that parses the section headers and registers symbols according to their virtual addresses. (ex: mygame__rdata_section)
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Tutorials -> LUA Tutorials All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites