An executable file parsing library, written in Kotlin Multiplatform.
Currently, this library can:
PE | ELF | Mach-O | |
---|---|---|---|
Read headers | ✅ | ✅ | ✅ |
Read import/export symbols | ✅ | ✅ | 🚧 |
Read sections | ✅ | ✅ | ✅ |
Read resources | ✅ | N/A | N/A |
Reading in VA | ✅ | ✅ | ✅ |
- Kotlin/Native: File access
- SBOM: Go
- SBOM: GraalVM Native Image
This project is currently in the early stages of development. This means it is still evolving and may undergo frequent updates and changes.
Due to the current status of Kotlin/Multiplatform, it can be expected that for a period of time following the stable release, binary compatibility guarantees will only be provided for Kotlin/JVM.
All targets supported.
This project contains several modules on Maven Central:
- space.iseki.executables:executables-files contains the code shared by pe, elf, and macho
dependencies {
implementation("space.iseki.executables:executables-files:0.0.21")
}
Since the project is in Kotlin Multiplatform, for Maven user you have to specify the platform explicitly.
(The -jvm
suffix)
<dependency>
<groupId>space.iseki.executables</groupId>
<artifactId>executables-files-jvm</artifactId>
<version>0.0.21</version>
</dependency>
import java.nio.file.Path
import kotlinx.serialization.json.Json
import space.iseki.executables.pe.PEFile
fun main() {
val file = Path.of("C:\\System32\\notepad.exe")
PEFile.open(file).use { peFile: PEFile ->
println(peFile.coffHeader)
println(peFile.summary)
println(Json.encodeToString(peFile.summary))
println(peFile.versionInfo)
}
}
import java.nio.file.Path
import space.iseki.executables.common.FileFormat
fun main() {
val file = Path.of("C:\\System32\\notepad.exe")
println(FileFormat.detect(file))
}
This API also works for ELF files.
import java.nio.file.Path
import space.iseki.executables.pe.PEFile
fun main() {
val file = Path.of("C:\\System32\\notepad.exe")
PEFile.open(file).use { peFile ->
// Get all imported DLLs and functions
peFile.importSymbols.forEach { symbol ->
println("Imported: ${symbol.file}::${symbol.name}")
if (symbol.isOrdinal) {
println(" - Ordinal: ${symbol.ordinal}")
}
}
}
}
This API also works for ELF files.
import java.nio.file.Path
import space.iseki.executables.pe.PEFile
fun main() {
val file = Path.of("C:\\System32\\kernel32.dll")
PEFile.open(file).use { peFile ->
// Get all exported functions
val exportSymbols = peFile.exportSymbols
println("Number of exported functions: ${exportSymbols.size}")
// Print the first 10 exported functions
exportSymbols.take(10).forEach { symbol ->
println(" - ${symbol.name}, Ordinal: ${symbol.ordinal}")
if (symbol.isForwarder) {
println(" Forwards to: ${symbol.forwarderString}")
}
}
}
}
Since PE splits the symbol table into import/export, this API is ELF specified.
import java.nio.file.Path
import space.iseki.executables.elf.ELFFile
fun main() {
val file = Path.of("/bin/ls") // ELF file on Linux system
ELFFile.open(file).use { elfFile ->
// Get all symbols
elfFile.symbols.forEach { symbol ->
val name = symbol.name ?: "<unnamed>"
println(" - $name: Name=${symbol.name}, Binding=${symbol.binding}")
}
}
}
- PE Format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
- PE VS_VERSIONINFO: https://learn.microsoft.com/en-us/windows/win32/menurc/vs-versioninfo
- ELF Format: https://refspecs.linuxfoundation.org/elf/elf.pdf
- Macho Format: https://github.com/apple/darwin-xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h