module Data.Pecoff ( Pecoff(..)
, PecoffSection(..)
, IMAGE_SUBSYSTEM(..)
, IMAGE_SCN_CHARACTERISTICS(..)
, IMAGE_DLL_CHARACTERISTICS(..)
, IMAGE_FILE_CHARACTERISTICS(..)
, IMAGE_FILE_MACHINE(..)
, parsePecoff
) where
import Data.Char
import Data.Bits
import Data.Word
import Data.Binary.Get
import Control.Monad
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C
import qualified Data.ByteString.Lazy as L
data IMAGE_SUBSYSTEM
= IMAGE_SUBSYSTEM_UNKNOWN
| IMAGE_SUBSYSTEM_NATIVE
| IMAGE_SUBSYSTEM_WINDOWS_GUI
| IMAGE_SUBSYSTEM_WINDOWS_CUI
| IMAGE_SUBSYSTEM_OS2_CUI
| IMAGE_SUBSYSTEM_POSIX_CUI
| IMAGE_SUBSYSTEM_NATIVE_WINDOWS
| IMAGE_SUBSYSTEM_WINDOWS_CE_GUI
| IMAGE_SUBSYSTEM_EFI_APPLICATION
| IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
| IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
| IMAGE_SUBSYSTEM_EFI_ROM
| IMAGE_SUBSYSTEM_XBOX
deriving (Show, Eq)
imageSubsystem 0 = IMAGE_SUBSYSTEM_UNKNOWN
imageSubsystem 1 = IMAGE_SUBSYSTEM_NATIVE
imageSubsystem 2 = IMAGE_SUBSYSTEM_WINDOWS_GUI
imageSubsystem 3 = IMAGE_SUBSYSTEM_WINDOWS_CUI
imageSubsystem 5 = IMAGE_SUBSYSTEM_OS2_CUI
imageSubsystem 7 = IMAGE_SUBSYSTEM_POSIX_CUI
imageSubsystem 8 = IMAGE_SUBSYSTEM_NATIVE_WINDOWS
imageSubsystem 9 = IMAGE_SUBSYSTEM_WINDOWS_CE_GUI
imageSubsystem 10 = IMAGE_SUBSYSTEM_EFI_APPLICATION
imageSubsystem 11 = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
imageSubsystem 12 = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
imageSubsystem 13 = IMAGE_SUBSYSTEM_EFI_ROM
imageSubsystem 14 = IMAGE_SUBSYSTEM_XBOX
imageSubsystem n = error ("hrm " ++ show n)
data IMAGE_SCN_CHARACTERISTICS
= IMAGE_SCN_TYPE_NO_PAD
| IMAGE_SCN_CNT_CODE
| IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_CNT_UNINITIALIZED_DATA
| IMAGE_SCN_LNK_OTHER
| IMAGE_SCN_LNK_INFO
| IMAGE_SCN_LNK_REMOVE
| IMAGE_SCN_LNK_COMDAT
| IMAGE_SCN_GPREL
| IMAGE_SCN_MEM_PURGEABLE
| IMAGE_SCN_MEM_16BIT
| IMAGE_SCN_MEM_LOCKED
| IMAGE_SCN_MEM_PRELOAD
| IMAGE_SCN_ALIGN_1BYTES
| IMAGE_SCN_ALIGN_2BYTES
| IMAGE_SCN_ALIGN_4BYTES
| IMAGE_SCN_ALIGN_8BYTES
| IMAGE_SCN_ALIGN_16BYTES
| IMAGE_SCN_ALIGN_32BYTES
| IMAGE_SCN_ALIGN_64BYTES
| IMAGE_SCN_ALIGN_128BYTES
| IMAGE_SCN_ALIGN_256BYTES
| IMAGE_SCN_ALIGN_512BYTES
| IMAGE_SCN_ALIGN_1024BYTES
| IMAGE_SCN_ALIGN_2048BYTES
| IMAGE_SCN_ALIGN_4096BYTES
| IMAGE_SCN_ALIGN_8192BYTES
| IMAGE_SCN_LNK_NRELOC_OVFL
| IMAGE_SCN_MEM_DISCARDABLE
| IMAGE_SCN_MEM_NOT_CACHED
| IMAGE_SCN_MEM_NOT_PAGED
| IMAGE_SCN_MEM_SHARED
| IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_WRITE
deriving (Show, Eq)
imageScnCharacteristics n = imageScnAlign_ ((n .&. 0x00f00000) `shiftR` 20) ++ imageScnCharacteristics_ n 32
where imageScnAlign_ 0x0 = []
imageScnAlign_ 0x1 = [IMAGE_SCN_ALIGN_1BYTES]
imageScnAlign_ 0x2 = [IMAGE_SCN_ALIGN_2BYTES]
imageScnAlign_ 0x3 = [IMAGE_SCN_ALIGN_4BYTES]
imageScnAlign_ 0x4 = [IMAGE_SCN_ALIGN_8BYTES]
imageScnAlign_ 0x5 = [IMAGE_SCN_ALIGN_16BYTES]
imageScnAlign_ 0x6 = [IMAGE_SCN_ALIGN_32BYTES]
imageScnAlign_ 0x7 = [IMAGE_SCN_ALIGN_64BYTES]
imageScnAlign_ 0x8 = [IMAGE_SCN_ALIGN_128BYTES]
imageScnAlign_ 0x9 = [IMAGE_SCN_ALIGN_256BYTES]
imageScnAlign_ 0xa = [IMAGE_SCN_ALIGN_512BYTES]
imageScnAlign_ 0xb = [IMAGE_SCN_ALIGN_1024BYTES]
imageScnAlign_ 0xc = [IMAGE_SCN_ALIGN_2048BYTES]
imageScnAlign_ 0xd = [IMAGE_SCN_ALIGN_4096BYTES]
imageScnAlign_ 0xe = [IMAGE_SCN_ALIGN_8192BYTES]
imageScnCharacteristics_ n 0 = []
imageScnCharacteristics_ n 4 | testBit n 3 = IMAGE_SCN_TYPE_NO_PAD : imageScnCharacteristics_ n 3
imageScnCharacteristics_ n 6 | testBit n 5 = IMAGE_SCN_CNT_CODE : imageScnCharacteristics_ n 5
imageScnCharacteristics_ n 7 | testBit n 6 = IMAGE_SCN_CNT_INITIALIZED_DATA : imageScnCharacteristics_ n 6
imageScnCharacteristics_ n 8 | testBit n 7 = IMAGE_SCN_CNT_UNINITIALIZED_DATA : imageScnCharacteristics_ n 7
imageScnCharacteristics_ n 9 | testBit n 8 = IMAGE_SCN_LNK_OTHER : imageScnCharacteristics_ n 8
imageScnCharacteristics_ n 10 | testBit n 9 = IMAGE_SCN_LNK_INFO : imageScnCharacteristics_ n 9
imageScnCharacteristics_ n 12 | testBit n 11 = IMAGE_SCN_LNK_REMOVE : imageScnCharacteristics_ n 11
imageScnCharacteristics_ n 13 | testBit n 12 = IMAGE_SCN_LNK_COMDAT : imageScnCharacteristics_ n 12
imageScnCharacteristics_ n 16 | testBit n 15 = IMAGE_SCN_GPREL : imageScnCharacteristics_ n 15
imageScnCharacteristics_ n 18 | testBit n 17 = IMAGE_SCN_MEM_PURGEABLE : IMAGE_SCN_MEM_16BIT : imageScnCharacteristics_ n 17
imageScnCharacteristics_ n 19 | testBit n 18 = IMAGE_SCN_MEM_LOCKED : imageScnCharacteristics_ n 18
imageScnCharacteristics_ n 20 | testBit n 19 = IMAGE_SCN_MEM_PRELOAD : imageScnCharacteristics_ n 19
imageScnCharacteristics_ n 25 | testBit n 24 = IMAGE_SCN_LNK_NRELOC_OVFL : imageScnCharacteristics_ n 24
imageScnCharacteristics_ n 26 | testBit n 25 = IMAGE_SCN_MEM_DISCARDABLE : imageScnCharacteristics_ n 25
imageScnCharacteristics_ n 27 | testBit n 26 = IMAGE_SCN_MEM_NOT_CACHED : imageScnCharacteristics_ n 26
imageScnCharacteristics_ n 28 | testBit n 27 = IMAGE_SCN_MEM_NOT_PAGED : imageScnCharacteristics_ n 27
imageScnCharacteristics_ n 29 | testBit n 28 = IMAGE_SCN_MEM_SHARED : imageScnCharacteristics_ n 28
imageScnCharacteristics_ n 30 | testBit n 29 = IMAGE_SCN_MEM_EXECUTE : imageScnCharacteristics_ n 29
imageScnCharacteristics_ n 31 | testBit n 30 = IMAGE_SCN_MEM_READ : imageScnCharacteristics_ n 30
imageScnCharacteristics_ n 32 | testBit n 31 = IMAGE_SCN_MEM_WRITE : imageScnCharacteristics_ n 31
imageScnCharacteristics_ n i = imageScnCharacteristics_ n (i1)
data IMAGE_DLL_CHARACTERISTICS
= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
| IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY
| IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
| IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION
| IMAGE_DLL_CHARACTERISTICS_NO_SEH
| IMAGE_DLL_CHARACTERISTICS_NO_BIND
| IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER
| IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE
deriving (Show, Eq)
imageDllCharacteristics n = imageDllCharacteristics_ n 16
where imageDllCharacteristics_ n 0 = []
imageDllCharacteristics_ n 7 | testBit n 6 = IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE : imageDllCharacteristics_ n 6
imageDllCharacteristics_ n 8 | testBit n 7 = IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY : imageDllCharacteristics_ n 7
imageDllCharacteristics_ n 9 | testBit n 8 = IMAGE_DLL_CHARACTERISTICS_NX_COMPAT : imageDllCharacteristics_ n 8
imageDllCharacteristics_ n 10 | testBit n 9 = IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION : imageDllCharacteristics_ n 9
imageDllCharacteristics_ n 11 | testBit n 10 = IMAGE_DLL_CHARACTERISTICS_NO_SEH : imageDllCharacteristics_ n 10
imageDllCharacteristics_ n 12 | testBit n 11 = IMAGE_DLL_CHARACTERISTICS_NO_BIND : imageDllCharacteristics_ n 11
imageDllCharacteristics_ n 14 | testBit n 13 = IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER : imageDllCharacteristics_ n 13
imageDllCharacteristics_ n 16 | testBit n 15 = IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE : imageDllCharacteristics_ n 15
imageDllCharacteristics_ n i = imageDllCharacteristics_ n (i1)
data IMAGE_FILE_CHARACTERISTICS
= IMAGE_FILE_RELOCS_STRIPPED
| IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_LINE_NUMS_STRIPPED
| IMAGE_FILE_LOCAL_SYMS_STIRPPED
| IMAGE_FILE_AGGRESSIVE_WS_TRIM
| IMAGE_FILE_LARGE_ADDRESS_AWARE
| IMAGE_FILE_BYTES_REVERSED_LO
| IMAGE_FILE_32BIT_MACHINE
| IMAGE_FILE_DEBUG_STRIPPED
| IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
| IMAGE_FILE_NET_RUN_FROM_SWAP
| IMAGE_FILE_SYSTEM
| IMAGE_FILE_DLL
| IMAGE_FILE_UP_SYSTEM_ONLY
| IMAGE_FILE_BYTES_REVERSED_HI
deriving (Show, Eq)
imageFileCharacteristics n = imageFileCharacteristics_ n 16
where imageFileCharacteristics_ n 0 = []
imageFileCharacteristics_ n 1 | testBit n 0 = IMAGE_FILE_RELOCS_STRIPPED : imageFileCharacteristics_ n 0
imageFileCharacteristics_ n 2 | testBit n 1 = IMAGE_FILE_EXECUTABLE_IMAGE : imageFileCharacteristics_ n 1
imageFileCharacteristics_ n 3 | testBit n 2 = IMAGE_FILE_LINE_NUMS_STRIPPED : imageFileCharacteristics_ n 2
imageFileCharacteristics_ n 4 | testBit n 3 = IMAGE_FILE_LOCAL_SYMS_STIRPPED : imageFileCharacteristics_ n 3
imageFileCharacteristics_ n 5 | testBit n 4 = IMAGE_FILE_AGGRESSIVE_WS_TRIM : imageFileCharacteristics_ n 4
imageFileCharacteristics_ n 6 | testBit n 5 = IMAGE_FILE_LARGE_ADDRESS_AWARE : imageFileCharacteristics_ n 5
imageFileCharacteristics_ n 8 | testBit n 7 = IMAGE_FILE_BYTES_REVERSED_LO : imageFileCharacteristics_ n 7
imageFileCharacteristics_ n 9 | testBit n 8 = IMAGE_FILE_32BIT_MACHINE : imageFileCharacteristics_ n 8
imageFileCharacteristics_ n 10 | testBit n 9 = IMAGE_FILE_DEBUG_STRIPPED : imageFileCharacteristics_ n 9
imageFileCharacteristics_ n 11 | testBit n 10 = IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP : imageFileCharacteristics_ n 10
imageFileCharacteristics_ n 12 | testBit n 11 = IMAGE_FILE_NET_RUN_FROM_SWAP : imageFileCharacteristics_ n 11
imageFileCharacteristics_ n 13 | testBit n 12 = IMAGE_FILE_SYSTEM : imageFileCharacteristics_ n 12
imageFileCharacteristics_ n 14 | testBit n 13 = IMAGE_FILE_DLL : imageFileCharacteristics_ n 13
imageFileCharacteristics_ n 15 | testBit n 14 = IMAGE_FILE_UP_SYSTEM_ONLY : imageFileCharacteristics_ n 14
imageFileCharacteristics_ n 16 | testBit n 15 = IMAGE_FILE_BYTES_REVERSED_HI : imageFileCharacteristics_ n 15
imageFileCharacteristics_ n i = imageFileCharacteristics_ n (i1)
data IMAGE_FILE_MACHINE
= IMAGE_FILE_MACHINE_UNKNOWN
| IMAGE_FILE_MACHINE_AM33
| IMAGE_FILE_MACHINE_AMD64
| IMAGE_FILE_MACHINE_ARM
| IMAGE_FILE_MACHINE_EBC
| IMAGE_FILE_MACHINE_I386
| IMAGE_FILE_MACHINE_IA64
| IMAGE_FILE_MACHINE_M32R
| IMAGE_FILE_MACHINE_MIPS16
| IMAGE_FILE_MACHINE_MIPSFPU
| IMAGE_FILE_MACHINE_MIPSFPU16
| IMAGE_FILE_MACHINE_POWERPC
| IMAGE_FILE_MACHINE_POWERPCFP
| IMAGE_FILE_MACHINE_R4000
| IMAGE_FILE_MACHINE_SH3
| IMAGE_FILE_MACHINE_SH3DSP
| IMAGE_FILE_MACHINE_SH4
| IMAGE_FILE_MACHINE_SH5
| IMAGE_FILE_MACHINE_THUMB
| IMAGE_FILE_MACHINE_WCEMIPSV2
deriving (Show, Eq)
imageFileMachine 0x0000 = IMAGE_FILE_MACHINE_UNKNOWN
imageFileMachine 0x01d3 = IMAGE_FILE_MACHINE_AM33
imageFileMachine 0x8664 = IMAGE_FILE_MACHINE_AMD64
imageFileMachine 0x01c0 = IMAGE_FILE_MACHINE_ARM
imageFileMachine 0x0ebc = IMAGE_FILE_MACHINE_EBC
imageFileMachine 0x014c = IMAGE_FILE_MACHINE_I386
imageFileMachine 0x0200 = IMAGE_FILE_MACHINE_IA64
imageFileMachine 0x9041 = IMAGE_FILE_MACHINE_M32R
imageFileMachine 0x0266 = IMAGE_FILE_MACHINE_MIPS16
imageFileMachine 0x0366 = IMAGE_FILE_MACHINE_MIPSFPU
imageFileMachine 0x0466 = IMAGE_FILE_MACHINE_MIPSFPU16
imageFileMachine 0x01f0 = IMAGE_FILE_MACHINE_POWERPC
imageFileMachine 0x01f1 = IMAGE_FILE_MACHINE_POWERPCFP
imageFileMachine 0x0166 = IMAGE_FILE_MACHINE_R4000
imageFileMachine 0x01a2 = IMAGE_FILE_MACHINE_SH3
imageFileMachine 0x01a3 = IMAGE_FILE_MACHINE_SH3DSP
imageFileMachine 0x01a6 = IMAGE_FILE_MACHINE_SH4
imageFileMachine 0x01a8 = IMAGE_FILE_MACHINE_SH5
imageFileMachine 0x01c2 = IMAGE_FILE_MACHINE_THUMB
imageFileMachine 0x0169 = IMAGE_FILE_MACHINE_WCEMIPSV2
data PecoffReader = PecoffReader
{ isPE32Plus :: Bool
, getAddress :: Get Word64
}
pecoffReader 0x020b = PecoffReader True getWord64le
pecoffReader 0x010b = PecoffReader False (liftM fromIntegral getWord32le)
pecoffReader _ = error "Invalid magic number for image file optional header."
data Pecoff = Pecoff
{ pMachine :: IMAGE_FILE_MACHINE
, pFileCharacteristics :: [IMAGE_FILE_CHARACTERISTICS]
, pEntryPointAddress :: Word64
, pImageBase :: Word64
, pSubsystem :: IMAGE_SUBSYSTEM
, pDllCharacteristics :: [IMAGE_DLL_CHARACTERISTICS]
, pSections :: [PecoffSection]
} deriving (Show, Eq)
getImageFileHeader = do
machine <- liftM imageFileMachine getWord16le
numsect <- liftM fromIntegral getWord16le
tmstamp <- getWord32le
symtoff <- getWord32le
symtcnt <- getWord32le
szopthd <- getWord16le
attribs <- liftM imageFileCharacteristics getWord16le
return (machine, numsect, attribs)
getImageFileOptionalHeader = do
magic <- getWord16le
pr <- return $ pecoffReader magic
majorLinkerVersion <- getWord8
minorLinkerVersion <- getWord8
sizeOfCode <- getWord32le
sizeOfInitializedData <- getWord32le
sizeOfUninitializedData <- getWord32le
addressOfEntryPoint <- liftM fromIntegral getWord32le
baseOfCode <- getWord32le
baseOfData <- if isPE32Plus pr then return 0 else getWord32le
imageBase <- getAddress pr
sectionAlignment <- getWord32le
fileAlignment <- getWord32le
majorOSVersion <- getWord16le
minorOSVersion <- getWord16le
majorImageVersion <- getWord16le
minorImageVersion <- getWord16le
majorSubSystemVersion <- getWord16le
minorSubSystemVersion <- getWord16le
win32VersionValue <- getWord32le
sizeOfImage <- getWord32le
sizeOfHeaders <- getWord32le
checksum <- getWord32le
subsystem <- liftM imageSubsystem $ getWord16le
dllCharacteristics <- liftM imageDllCharacteristics $ getWord16le
sizeOfStackReserve <- getAddress pr
sizeOfStackCommit <- getAddress pr
sizeOfHeapReserve <- getAddress pr
sizeOfHeapCommit <- getAddress pr
loaderFlags <- getWord32le
numberOfRvaAndSizes <- liftM fromIntegral $ getWord32le
imageDataDirectory <- sequence $ replicate numberOfRvaAndSizes (liftM2 (,) getWord32le getWord32le)
skip (8 * (16 numberOfRvaAndSizes))
let exportTable = if length imageDataDirectory > 0 then Just (imageDataDirectory !! 0) else Nothing
importTable = if length imageDataDirectory > 1 then Just (imageDataDirectory !! 1) else Nothing
resourceTable = if length imageDataDirectory > 2 then Just (imageDataDirectory !! 2) else Nothing
exceptionTable = if length imageDataDirectory > 3 then Just (imageDataDirectory !! 3) else Nothing
certificateTable = if length imageDataDirectory > 4 then Just (imageDataDirectory !! 4) else Nothing
baseRelocationTable = if length imageDataDirectory > 5 then Just (imageDataDirectory !! 5) else Nothing
debug = if length imageDataDirectory > 6 then Just (imageDataDirectory !! 6) else Nothing
architecture = if length imageDataDirectory > 7 then Just (imageDataDirectory !! 7) else Nothing
globalPtr = if length imageDataDirectory > 8 then Just (imageDataDirectory !! 8) else Nothing
tlsTable = if length imageDataDirectory > 9 then Just (imageDataDirectory !! 9) else Nothing
loadConfigTable = if length imageDataDirectory > 10 then Just (imageDataDirectory !! 10) else Nothing
boundImport = if length imageDataDirectory > 11 then Just (imageDataDirectory !! 11) else Nothing
iat = if length imageDataDirectory > 12 then Just (imageDataDirectory !! 12) else Nothing
delayImportDescriptor = if length imageDataDirectory > 13 then Just (imageDataDirectory !! 13) else Nothing
clrRuntimeHeader = if length imageDataDirectory > 14 then Just (imageDataDirectory !! 14) else Nothing
return (pr, addressOfEntryPoint, imageBase, subsystem, dllCharacteristics)
getCharUTF8 = do
let getCharUTF82 b1 = do
b2 <- liftM fromIntegral getWord8 :: Get Word32
if b2 .&. 0xc0 == 0x80 then
return $ ((b1 .&. 0x1f) `shiftL` 6) .|. (b2 .&. 0x3f)
else
fail "Invalid second byte in UTf8 string."
getCharUTF83 b1 = do
b2 <- liftM fromIntegral getWord8 :: Get Word32
b3 <- liftM fromIntegral getWord8 :: Get Word32
if b2 .&. 0xc0 == 0x80 && b3 .&. 0xc0 == 0x80 then
return $ ((b1 .&. 0x0f) `shiftL` 12) .|. ((b2 .&. 0x3f) `shiftL` 6) .|. (b3 .&. 0x3f)
else
fail "Invalid second or third byte in UTf8 string."
getCharUTF84 b1 = do
b2 <- liftM fromIntegral getWord8 :: Get Word32
b3 <- liftM fromIntegral getWord8 :: Get Word32
b4 <- liftM fromIntegral getWord8 :: Get Word32
if b2 .&. 0xc0 == 0x80 && b3 .&. 0xc0 == 0x80 && b4 .&. 0xc0 == 0x80 then
return $ ((b1 .&. 0x07) `shiftL` 18) .|. ((b2 .&. 0x3f) `shiftL` 12) .|. ((b3 .&. 0x3f) `shiftL` 6) .|. (b4 .&. 0x3f)
else
fail "Invalid second or third byte in UTf8 string."
b1 <- liftM fromIntegral getWord8 :: Get Word32
case b1 of
n | n .&. 0x80 == 0x00 -> return $ fromIntegral n
n | n .&. 0xe0 == 0xc0 -> getCharUTF82 n
n | n .&. 0xf0 == 0xe0 -> getCharUTF83 n
n | n .&. 0xf8 == 0xf0 -> getCharUTF84 n
_ -> fail "Invalid first byte in UTF8 string."
getSectionName = liftM (map (chr . fromIntegral)) getSectionName_
where getSectionName_ = do
empty <- isEmpty
if empty then
return []
else do
char <- getCharUTF8
if char == 0 then
return []
else do
rest <- getSectionName_
return (char : rest)
data PecoffSection = PecoffSection
{ psectName :: String
, psectVirtualSize :: Word64
, psectVirtualAddress :: Word64
, psectCharacteristics :: [IMAGE_SCN_CHARACTERISTICS]
, psectRelocations :: B.ByteString
, psectLinenumbers :: B.ByteString
, psectRawData :: B.ByteString
} deriving (Show, Eq)
getSectionHeader pr bs = do
full_name <- getByteString 8
name <- return $ runGet getSectionName $ L.fromChunks[full_name]
virtualSize <- liftM fromIntegral getWord32le
virtualAddress <- liftM fromIntegral getWord32le
sizeOfRawData <- liftM fromIntegral getWord32le
pointerToRawData <- liftM fromIntegral getWord32le
pointerToRelocations <- liftM fromIntegral getWord32le
pointerToLinenumbers <- liftM fromIntegral getWord32le
numberOfRelocations <- liftM fromIntegral getWord16le
numberOfLinenumbers <- liftM fromIntegral getWord16le
characteristics <- liftM imageScnCharacteristics getWord32le
return $ PecoffSection
{ psectName = name
, psectVirtualSize = virtualSize
, psectVirtualAddress = virtualAddress
, psectCharacteristics = characteristics
, psectRelocations = B.take (10 * numberOfRelocations) $ B.drop pointerToRelocations bs
, psectLinenumbers = B.take (6 * numberOfLinenumbers) $ B.drop pointerToLinenumbers bs
, psectRawData = B.take sizeOfRawData $ B.drop pointerToRawData bs
}
getPeOffset = do
magic <- liftM (C.unpack . B.pack) $ sequence [getWord8, getWord8]
if magic == "MZ" then do
skip 0x3a
coffOffset <- liftM fromIntegral getWord32le
return coffOffset
else
fail "Invalid magic number in MSDOS header."
getPecoff bs = do
magic <- liftM (C.unpack . B.pack) $ sequence [getWord8, getWord8, getWord8, getWord8]
if magic /= "PE\0\0" then
fail "Invalid magic number in PE header."
else do
(machine, numsects, fileCharacteristics) <- getImageFileHeader
(pr, addressOfEntryPoint, imageBase, subsystem, dllCharacteristics) <- getImageFileOptionalHeader
sections <- sequence $ replicate numsects (getSectionHeader pr bs)
return $ Pecoff
{ pMachine = machine
, pFileCharacteristics = fileCharacteristics
, pEntryPointAddress = addressOfEntryPoint
, pImageBase = imageBase
, pSubsystem = subsystem
, pDllCharacteristics = dllCharacteristics
, pSections = sections
}
parsePecoff :: B.ByteString -> Pecoff
parsePecoff bs =
let coffOffset = runGet getPeOffset $ L.fromChunks [bs]
coffObject = B.drop coffOffset bs
in runGet (getPecoff coffObject) $ L.fromChunks [coffObject]