Skip to content

Instantly share code, notes, and snippets.

@timsonner
Last active June 11, 2023 08:54
Show Gist options
  • Select an option

  • Save timsonner/1f7ee60b3ebfe010a154c2e397ea0f7d to your computer and use it in GitHub Desktop.

Select an option

Save timsonner/1f7ee60b3ebfe010a154c2e397ea0f7d to your computer and use it in GitHub Desktop.
GoLang. Messing with PE injection.
package main
import (
"encoding/binary"
"log"
"os"
"reflect"
"unsafe"
)
func main() {
// Open the original PE file
originalFile, err := os.Open("original.exe")
if err != nil {
log.Fatal(err)
}
defer originalFile.Close()
// Get the size of the file
fileInfo, err := originalFile.Stat()
if err != nil {
log.Fatal(err)
}
fileSize := fileInfo.Size()
// Create a buffer to hold the file contents
buffer := make([]byte, fileSize)
// Read the file into the buffer
_, err = originalFile.Read(buffer)
if err != nil {
log.Fatal(err)
}
// Create a deep copy of the buffer using unsafe
copyBuffer := make([]byte, len(buffer))
copy(copyBuffer, buffer)
// Convert the byte slices to unsafe pointers
originalPointer := (*reflect.SliceHeader)(unsafe.Pointer(&buffer)).Data
copyPointer := (*reflect.SliceHeader)(unsafe.Pointer(&copyBuffer)).Data
// Calculate the size of the memory block to copy
copySize := uintptr(len(buffer))
// Allocate a new memory block for the copied data
copyMemory := unsafe.Pointer(uintptr(copyPointer))
// Copy the data from the original memory block to the new memory block
unsafe.Copy(copyMemory, unsafe.Pointer(uintptr(originalPointer)))
// Use the deep copied buffer as needed
// Access PE headers
dosHeader := (*IMAGE_DOS_HEADER)(unsafe.Pointer(copyPointer))
ntHeader := (*IMAGE_NT_HEADERS)(unsafe.Pointer(copyPointer + uintptr(dosHeader.E_lfanew)))
fileHeader := (*IMAGE_FILE_HEADER)(unsafe.Pointer(&ntHeader.FileHeader))
optionalHeader := (*IMAGE_OPTIONAL_HEADER)(unsafe.Pointer(&ntHeader.OptionalHeader))
// Access entry point
entryPoint := optionalHeader.AddressOfEntryPoint
// Access PE sections
sectionTable := (*[1 << 16]IMAGE_SECTION_HEADER)(unsafe.Pointer(copyPointer + uintptr(dosHeader.E_lfanew) + unsafe.Sizeof(*ntHeader)))[0:fileHeader.NumberOfSections]
// Access relocation tables
baseRelocation := (*IMAGE_BASE_RELOCATION)(unsafe.Pointer(copyPointer + uintptr(sectionTable[0].PointerToRelocations)))
numEntries := (baseRelocation.SizeOfBlock - uint32(unsafe.Sizeof(*baseRelocation))) / uint32(unsafe.Sizeof(IMAGE_RELOCATION_ENTRY{}))
relocationEntries := (*[1 << 16]IMAGE_RELOCATION_ENTRY)(unsafe.Pointer(uintptr(unsafe.Pointer(baseRelocation)) + unsafe.Sizeof(*baseRelocation)))[0:numEntries]
// Iterate over the relocation entries
for i := 0; i < int(numEntries); i++ {
entry := relocationEntries[i]
// Process each relocation entry as needed
}
// Access import tables
importDescriptor := (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Pointer(copyPointer + uintptr(sectionTable[0].PointerToImports)))
for importDescriptor.Name != 0 {
importModuleName := (*string)(unsafe.Pointer(copyPointer + uintptr(importDescriptor.Name)))
// Access other import details if needed
importDescriptor++
}
// Access export table
exportDirectory := (*IMAGE_EXPORT_DIRECTORY)(unsafe.Pointer(copyPointer + uintptr(sectionTable[0].PointerToExports)))
exportNames := (*[1 << 16]uint32)(unsafe.Pointer(copyPointer + uintptr(exportDirectory.AddressOfNames)))
for i := uint32(0); i < exportDirectory.NumberOfNames; i++ {
exportName := (*string)(unsafe.Pointer(copyPointer + uintptr(exportNames[i])))
// Access other export details if needed
}
// Clean up the deep copied buffer
copyBuffer = nil
}
// Structures representing the PE file format
type IMAGE_DOS_HEADER struct {
E_magic uint16
E _lfanew int32
}
type IMAGE_NT_HEADERS struct {
Signature uint32
FileHeader IMAGE_FILE_HEADER
OptionalHeader IMAGE_OPTIONAL_HEADER
}
type IMAGE_FILE_HEADER struct {
Machine uint16
NumberOfSections uint16
TimeDateStamp uint32
PointerToSymbolTable uint32
NumberOfSymbols uint32
SizeOfOptionalHeader uint16
Characteristics uint16
}
type IMAGE_OPTIONAL_HEADER struct {
Magic uint16
MajorLinkerVersion byte
MinorLinkerVersion byte
SizeOfCode uint32
SizeOfInitializedData uint32
SizeOfUninitializedData uint32
AddressOfEntryPoint uint32
BaseOfCode uint32
BaseOfData uint32
ImageBase uint32
SectionAlignment uint32
FileAlignment uint32
MajorOperatingSystemVersion uint16
MinorOperatingSystemVersion uint16
MajorImageVersion uint16
MinorImageVersion uint16
MajorSubsystemVersion uint16
MinorSubsystemVersion uint16
Win32VersionValue uint32
SizeOfImage uint32
SizeOfHeaders uint32
CheckSum uint32
Subsystem uint16
DllCharacteristics uint16
SizeOfStackReserve uint32
SizeOfStackCommit uint32
SizeOfHeapReserve uint32
SizeOfHeapCommit uint32
LoaderFlags uint32
NumberOfRvaAndSizes uint32
DataDirectory [16]IMAGE_DATA_DIRECTORY
}
type IMAGE_DATA_DIRECTORY struct {
VirtualAddress uint32
Size uint32
}
type IMAGE_SECTION_HEADER struct {
Name [8]byte
VirtualSize uint32
VirtualAddress uint32
SizeOfRawData uint32
PointerToRawData uint32
PointerToRelocations uint32
PointerToLineNumbers uint32
NumberOfRelocations uint16
NumberOfLineNumbers uint16
Characteristics uint32
}
type IMAGE_BASE_RELOCATION struct {
VirtualAddress uint32
SizeOfBlock uint32
// Additional relocation entries follow the struct
}
type IMAGE_RELOCATION_ENTRY struct {
Data uint16
}
type IMAGE_IMPORT_DESCRIPTOR struct {
OriginalFirstThunk uint32
TimeDateStamp uint32
ForwarderChain uint32
Name uint32
FirstThunk uint32
}
type IMAGE_EXPORT_DIRECTORY struct {
Characteristics uint32
TimeDateStamp uint32
MajorVersion uint16
MinorVersion uint16
Name uint32
Base uint32
NumberOfFunctions uint32
NumberOfNames uint32
AddressOfFunctions uint32
AddressOfNames uint32
AddressOfNameOrdinals uint32
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment