Skip to content

Instantly share code, notes, and snippets.

@hasherezade
Last active January 6, 2023 02:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasherezade/f6fafac2b7e452a36410c2c5583f9790 to your computer and use it in GitHub Desktop.
Save hasherezade/f6fafac2b7e452a36410c2c5583f9790 to your computer and use it in GitHub Desktop.
PE-sieve scan in Golang
package main
import (
"fmt"
"syscall"
"unsafe"
)
var (
peSieveDll = syscall.NewLazyDLL("pe-sieve64.dll")
peSieveScanEx = peSieveDll.NewProc("PESieve_scan_ex")
)
const (
ERROR_SCAN_FAILURE = ^uint32(0)
MAX_PATH = 260
)
type PEsieveRtype int32
const (
ReportNone PEsieveRtype = iota
ReportScanned
ReportDumped
ReportAll
)
type ParamString struct {
Length uint32
Buffer *byte
}
type DotnetPolicy int32
const (
PeDnetNone DotnetPolicy = iota
PeDnetSkipMapping
PeDnetSkipShc
PeDnetSkipHooks
PeDnetSkipAll
PeDnetCount
)
type ImprecMode int32
const (
PeImprecNone ImprecMode = iota
PeImprecAuto
PeImprecUnerase
PeImprecRebuild0
PeImprecRebuild1
PeImprecRebuild2
PeImprecModesCount
)
type OutputFilter int32
const (
OutFull OutputFilter = iota
OutNoDumps
OutNoDir
OutFiltersCount
)
type IatScanMode int32
const (
PeIatsNone IatScanMode = iota
PeIatsCleanSysFiltered
PeIatsAllSysFiltered
PeIatsUnfiltered
PeIatsModesCount
)
type DataScanMode int32
const (
PeDataNoScan DataScanMode = iota
PeDataScanDotnet
PeDataScanNoDep
PeDataScanAlways
PeDataScanInaccessible
PeDataScanInaccessibleOnly
PeDataCount
)
type DumpMode int32
const (
PeDumpAuto DumpMode = iota
PeDumpVirtual
PeDumpUnmap
PeDumpRealign
PeDumpModesCount
)
type JsonLevel int32
const (
JsonBasic JsonLevel = iota
JsonDetails
JsonDetails2
JsonLvlCount
)
type PEsieveParams struct {
Pid uint32
TDotnetPolicy DotnetPolicy
TImprecMode ImprecMode
Quiet bool
TOutputFilter OutputFilter
Nohooks bool
Shellcode bool
Threads bool
Iat IatScanMode
Data DataScanMode
Minidump bool
TDumpMode DumpMode
JsonOutput bool
MakeReflection bool
UseCache bool
TJsonLevel JsonLevel
OutputDir [MAX_PATH + 1]byte
ModulesIgnored ParamString
}
type PEsieveReport struct {
Pid uint32
IsManaged bool
Is64bit bool
IsReflection bool
Scanned uint32
Suspicious uint32
Replaced uint32
HdrMod uint32
UnreachableFile uint32
Patched uint32
IatHooked uint32
Implanted uint32
ImplantedPe uint32
ImplantedShc uint32
Other uint32
Skipped uint32
Errors uint32
}
func main() {
// Set up the scan parameters
pp := PEsieveParams{
Pid: uint32(syscall.Getpid()), // scan current process
Threads: true,
Shellcode: true,
Quiet: true,
}
pr := PEsieveReport{}
const rtype = ReportAll
// Prepare the buffer for the output report
const bufSize uint = 0x1000
jsonBuf := make([]byte, bufSize)
neededSize := uint32(0)
// Perform the scan:
ret, _, out2 := peSieveScanEx.Call(
uintptr(unsafe.Pointer(&pr)), // first pass the return variable
uintptr(unsafe.Pointer(&pp)), // then pass the typical arguments of the function
uintptr(rtype),
uintptr(unsafe.Pointer(&jsonBuf[0])),
uintptr(bufSize),
uintptr(unsafe.Pointer(&neededSize)),
)
if neededSize > uint32(bufSize) {
// The supplied buffer was too small to fit in the whole JSON report
fmt.Printf("Couldn't retrieve the full buffer. Needed size: %x\n", neededSize)
}
// Print the obtained report:
var reportStr = string(jsonBuf[:neededSize])
fmt.Println(reportStr)
// Some additional returned stuff:
if (uintptr(unsafe.Pointer(&pr)) == ret) {
fmt.Println("Returned val OK")
} else {
fmt.Printf("Returned val invalid: %x vs %x\n", unsafe.Pointer(&pr) , ret)
}
fmt.Println("Info:", out2)
fmt.Printf("Summary for PID %d:\n", pr.Pid)
fmt.Printf("Scanned: %d\n", pr.Scanned)
fmt.Printf("Detected: %d\n", pr.Suspicious)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment