mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-11-05 21:56:33 +00:00
2862 lines
112 KiB
Go
2862 lines
112 KiB
Go
//go:build guest_windows
|
|
|
|
package ntapi
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/mirkobrombin/Raven/pkg/arch"
|
|
"github.com/mirkobrombin/Raven/pkg/mmu"
|
|
"github.com/mirkobrombin/Raven/pkg/vfs"
|
|
|
|
ravelog "github.com/mirkobrombin/Raven/pkg/log"
|
|
)
|
|
|
|
// TrapHandler is a function that handles a single NT syscall.
|
|
// It receives the CPU state and returns an NTSTATUS code.
|
|
type TrapHandler func(ctx *TrapContext) uint32
|
|
|
|
// SemanticHandler describes a concrete ABI implementation registered for an
|
|
// exported function. It is used by compatibility audits as well as dispatch.
|
|
type SemanticHandler struct {
|
|
ImplementationID string
|
|
Signature string
|
|
ContractCaseID string
|
|
Handler TrapHandler
|
|
}
|
|
|
|
// TrapContext provides access to guest CPU state and VM subsystems for handlers.
|
|
type TrapContext struct {
|
|
CPU arch.CPU
|
|
Mem *mmu.MMU
|
|
FS *vfs.VFS
|
|
Handles *HandleTable
|
|
Reg *RegistryHive
|
|
State *ProcessState
|
|
Disp *Dispatcher
|
|
Trace bool
|
|
// TraceSyscall logs every Nt*/NtUser*/NtGdi* seam crossing without the
|
|
// per-instruction noise of Trace. This is the lens for the win32k pivot.
|
|
TraceSyscall bool
|
|
flsSlots map[uint32]uint64
|
|
flsNextIdx uint32
|
|
// ReturnOverridden is set by handlers that manage RAX directly,
|
|
// preventing the dispatcher from overwriting it with the handler's return.
|
|
ReturnOverridden bool
|
|
// PCRedirected is set by handlers that redirect the program counter
|
|
// (e.g., sync WndProc dispatch). When set, PE32 stdcall cleanup is skipped
|
|
// because the handler already manages the stack.
|
|
PCRedirected bool
|
|
// maxArgIdx tracks the highest Arg() index accessed for PE32 stdcall cleanup.
|
|
maxArgIdx int
|
|
// i386ArgExtra is added to the PE32 stack arg base. It is 4 when a win32k
|
|
// syscall arrived via the KUSER_SHARED_DATA->SystemCall trampoline (the
|
|
// stub's `call [edx]` pushed one extra return address), and 0 for a direct
|
|
// synth stub. Set per-call by Handle(); reset to 0 otherwise.
|
|
i386ArgExtra uint64
|
|
}
|
|
|
|
// Arg reads a Windows calling convention argument.
|
|
// For x64 (PE32+): RCX, RDX, R8, R9, then stack (with shadow space).
|
|
// For i386 (PE32): all arguments on stack (stdcall/cdecl).
|
|
func (ctx *TrapContext) Arg(n int) uint64 {
|
|
if n > ctx.maxArgIdx {
|
|
ctx.maxArgIdx = n
|
|
}
|
|
if ctx.CPU.GetArch() == arch.ArchI386 {
|
|
// stdcall: args pushed right-to-left, return addr at [ESP]
|
|
// arg0 at [ESP+4], arg1 at [ESP+8], ...
|
|
sp := ctx.CPU.GetSP()
|
|
addr := sp + 4 + ctx.i386ArgExtra + uint64(n)*4 // skip return address(es)
|
|
val, err := ctx.Mem.Read32(addr)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return uint64(val)
|
|
}
|
|
args := ctx.CPU.SyscallArgs() // [RDI, RSI, RDX, R10, R8, R9]
|
|
// Windows x64 ABI: RCX=arg0, RDX=arg1, R8=arg2, R9=arg3
|
|
// We need to read directly from registers since SyscallArgs() is Linux ABI.
|
|
mem := ctx.CPU.GetMem()
|
|
switch n {
|
|
case 0:
|
|
return readReg(mem, ctx.CPU, regRCX)
|
|
case 1:
|
|
return readReg(mem, ctx.CPU, regRDX)
|
|
case 2:
|
|
return readReg(mem, ctx.CPU, regR8)
|
|
case 3:
|
|
return readReg(mem, ctx.CPU, regR9)
|
|
default:
|
|
// Stack arguments: RSP + 0x28 + (n-4)*8
|
|
// (0x28 = return addr + 4 shadow slots)
|
|
sp := ctx.CPU.GetSP()
|
|
addr := sp + 0x28 + uint64(n-4)*8
|
|
val, err := mem.Read64(addr)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
_ = args
|
|
return val
|
|
}
|
|
}
|
|
|
|
// SetReturn sets the return value (RAX) and prevents the dispatcher
|
|
// from overwriting it with the handler's return code.
|
|
func (ctx *TrapContext) SetReturn(val uint64) {
|
|
ctx.CPU.SetSyscallReturn(val)
|
|
ctx.ReturnOverridden = true
|
|
}
|
|
|
|
// FloatArg reads a Windows x64 float argument from XMM0-XMM3.
|
|
func (ctx *TrapContext) FloatArg(n int) float64 {
|
|
if xa, ok := ctx.CPU.(XMMAccess); ok && n >= 0 && n < 4 {
|
|
return math.Float64frombits(xa.ReadXMM(n))
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// SetFloatReturn writes a float64 result to XMM0.
|
|
func (ctx *TrapContext) SetFloatReturn(val float64) {
|
|
if xa, ok := ctx.CPU.(XMMAccess); ok {
|
|
xa.WriteXMM(0, math.Float64bits(val))
|
|
}
|
|
ctx.ReturnOverridden = true
|
|
}
|
|
|
|
// Register constants for direct access.
|
|
const (
|
|
regRAX = 0
|
|
regRCX = 1
|
|
regRDX = 2
|
|
regRBX = 3
|
|
regRSP = 4
|
|
regRBP = 5
|
|
regRSI = 6
|
|
regRDI = 7
|
|
regR8 = 8
|
|
regR9 = 9
|
|
regR10 = 10
|
|
regR11 = 11
|
|
regR12 = 12
|
|
regR13 = 13
|
|
regR14 = 14
|
|
regR15 = 15
|
|
)
|
|
|
|
// readReg reads a register by index from the x64 CPU.
|
|
// The CPU interface doesn't expose individual registers, so we use a workaround:
|
|
// SyscallArgs returns [RDI, RSI, RDX, R10, R8, R9].
|
|
// SyscallNum returns RAX.
|
|
// For RCX and R9 we need the RegisterReader interface.
|
|
func readReg(mem *mmu.MMU, cpu arch.CPU, reg int) uint64 {
|
|
if rr, ok := cpu.(RegisterReader); ok {
|
|
return rr.ReadReg(reg)
|
|
}
|
|
// Fallback using available interface methods
|
|
args := cpu.SyscallArgs() // [RDI, RSI, RDX, R10, R8, R9]
|
|
switch reg {
|
|
case regRAX:
|
|
return cpu.SyscallNum()
|
|
case regRDI:
|
|
return args[0]
|
|
case regRSI:
|
|
return args[1]
|
|
case regRDX:
|
|
return args[2]
|
|
case regR10:
|
|
return args[3]
|
|
case regR8:
|
|
return args[4]
|
|
case regR9:
|
|
return args[5]
|
|
case regRSP:
|
|
return cpu.GetSP()
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// RegisterReader is an optional interface for CPUs that expose register reads.
|
|
type RegisterReader interface {
|
|
ReadReg(idx int) uint64
|
|
}
|
|
|
|
// RegisterWriter is an optional interface for CPUs that expose register writes.
|
|
type RegisterWriter interface {
|
|
WriteReg(idx int, val uint64)
|
|
}
|
|
|
|
// XMMAccess is an optional interface for CPUs that expose XMM register access.
|
|
type XMMAccess interface {
|
|
ReadXMM(idx int) uint64
|
|
WriteXMM(idx int, val uint64)
|
|
}
|
|
|
|
// Dispatcher routes vmcall traps to the appropriate handler based on syscall ID.
|
|
type Dispatcher struct {
|
|
mu sync.RWMutex
|
|
handlers map[uint32]TrapHandler
|
|
handlersByModule map[string]map[string]TrapHandler
|
|
semanticByModule map[string]map[string]SemanticHandler
|
|
nextDynamicID uint32
|
|
hprof *handlerProfiler // optional hot-handler profiler (RAVEN_PROFILE_HANDLERS)
|
|
traceStdcall bool // log guest-range stdcall cleanups (RAVEN_TRACE_STDCALL)
|
|
names map[uint32]string // for trace logging
|
|
ntdll *SynthPE
|
|
win32u *SynthPE
|
|
ctx *TrapContext
|
|
moduleExports map[uint64]map[string]uint64 // baseAddr -> name -> addr
|
|
moduleOrdExports map[uint64]map[uint16]uint64 // baseAddr -> ordinal -> addr
|
|
sysRoot string // path to Windows system DLL directory
|
|
nlsMu sync.Mutex
|
|
nlsCache map[uint32][]byte // cached NLS file data by code page
|
|
cdeclIDs map[uint32]bool // IDs that use cdecl (no callee cleanup)
|
|
cdeclModules map[string]bool // modules whose current and future exports use cdecl
|
|
stdcallArgs map[uint32]int // explicit stdcall cleanup: ID -> arg count
|
|
userCallbacks UserCallbackManager
|
|
}
|
|
|
|
// NewDispatcher creates a trap dispatcher with all registered handlers.
|
|
func NewDispatcher(mem *mmu.MMU, fs *vfs.VFS, handles *HandleTable, reg *RegistryHive, state *ProcessState, ntdll, win32u *SynthPE) *Dispatcher {
|
|
d := &Dispatcher{
|
|
handlers: make(map[uint32]TrapHandler),
|
|
handlersByModule: make(map[string]map[string]TrapHandler),
|
|
semanticByModule: make(map[string]map[string]SemanticHandler),
|
|
names: make(map[uint32]string),
|
|
ntdll: ntdll,
|
|
win32u: win32u,
|
|
moduleExports: make(map[uint64]map[string]uint64),
|
|
moduleOrdExports: make(map[uint64]map[uint16]uint64),
|
|
nlsCache: make(map[uint32][]byte),
|
|
cdeclIDs: make(map[uint32]bool),
|
|
cdeclModules: make(map[string]bool),
|
|
stdcallArgs: make(map[uint32]int),
|
|
ctx: &TrapContext{
|
|
Mem: mem,
|
|
FS: fs,
|
|
Handles: handles,
|
|
Reg: reg,
|
|
State: state,
|
|
},
|
|
}
|
|
d.ctx.Disp = d
|
|
|
|
d.registerNtapiHandlers()
|
|
d.registerWin32kHandlers()
|
|
|
|
// ntdll's CRT/Wine-helper exports use cdecl (the CALLER cleans the stack),
|
|
// unlike the stdcall Nt*/Rtl*/Zw*/Csr*/Dbg*/Ldr* services. They are exactly
|
|
// the lowercase/_-prefixed names. Mark them cdecl so the dispatcher does NOT
|
|
// pop their args - otherwise both callee (us) and caller pop, misaligning the
|
|
// PE32 stack and crashing real DLL init (e.g. user32's SxS lookup calls
|
|
// ntdll!_wcsicmp repeatedly; the drift led to a ret onto the stack).
|
|
for i, name := range ntapiExports {
|
|
if len(name) > 0 && (name[0] == '_' || (name[0] >= 'a' && name[0] <= 'z')) {
|
|
d.cdeclIDs[ntapiIDBase+uint32(i)] = true
|
|
}
|
|
}
|
|
|
|
// Register the DllMain return sentinel
|
|
d.register(DllMainReturnID, "_DllMainReturn", func(ctx *TrapContext) uint32 {
|
|
ctx.CPU.Stop()
|
|
return StatusSuccess
|
|
})
|
|
|
|
return d
|
|
}
|
|
|
|
func (d *Dispatcher) ProcessState() *ProcessState {
|
|
if d == nil || d.ctx == nil {
|
|
return nil
|
|
}
|
|
return d.ctx.State
|
|
}
|
|
|
|
// SetTrace enables/disables trace logging.
|
|
func (d *Dispatcher) SetTrace(trace bool) {
|
|
d.ctx.Trace = trace
|
|
}
|
|
|
|
// SetTraceSyscall enables/disables syscall-seam trace logging: one concise line
|
|
// per Nt*/NtUser*/NtGdi* crossing (handler name + id), without instruction noise.
|
|
func (d *Dispatcher) SetTraceSyscall(on bool) {
|
|
d.ctx.TraceSyscall = on
|
|
}
|
|
|
|
// SetSysRoot sets the path to the Windows system DLL directory for NLS file loading.
|
|
func (d *Dispatcher) SetSysRoot(path string) {
|
|
d.sysRoot = path
|
|
}
|
|
|
|
// loadNlsFile loads an NLS code page file from the sysroot.
|
|
func (d *Dispatcher) loadNlsFile(codePage uint32) ([]byte, error) {
|
|
d.nlsMu.Lock()
|
|
defer d.nlsMu.Unlock()
|
|
if data, ok := d.nlsCache[codePage]; ok {
|
|
return data, nil
|
|
}
|
|
if d.sysRoot == "" {
|
|
return nil, fmt.Errorf("no sysroot configured")
|
|
}
|
|
filename := fmt.Sprintf("c_%d.nls", codePage)
|
|
path := d.sysRoot + "/" + filename
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
d.nlsCache[codePage] = data
|
|
return data, nil
|
|
}
|
|
|
|
// RegisterModuleExports registers a loaded module's exports for LdrGetProcedureAddress.
|
|
func (d *Dispatcher) RegisterModuleExports(baseAddr uint64, exports map[string]uint64, ordExports map[uint16]uint64) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
if len(exports) > 0 {
|
|
d.moduleExports[baseAddr] = exports
|
|
}
|
|
if len(ordExports) > 0 {
|
|
d.moduleOrdExports[baseAddr] = ordExports
|
|
}
|
|
}
|
|
|
|
func IsHiddenNtdllExport(name string) bool {
|
|
return strings.EqualFold(name, "wine_get_version")
|
|
}
|
|
|
|
func (d *Dispatcher) lookupSynthExportLocked(synth *SynthPE, funcName string, ordinal uint16) uint64 {
|
|
if synth == nil {
|
|
return 0
|
|
}
|
|
if synth == d.ntdll || strings.EqualFold(synth.Name, "ntdll.dll") {
|
|
if IsHiddenNtdllExport(funcName) {
|
|
return 0
|
|
}
|
|
if funcName == "" && ordinal != 0 {
|
|
hiddenAddr := synth.Exports["wine_get_version"]
|
|
if hiddenAddr != 0 && synth.ExportOrds[ordinal] == hiddenAddr {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
if funcName != "" {
|
|
if addr := synth.Exports[funcName]; addr != 0 {
|
|
return addr
|
|
}
|
|
}
|
|
if ordinal != 0 {
|
|
return synth.ExportOrds[ordinal]
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (d *Dispatcher) LookupSynthExport(synth *SynthPE, funcName string, ordinal uint16) uint64 {
|
|
d.mu.RLock()
|
|
defer d.mu.RUnlock()
|
|
return d.lookupSynthExportLocked(synth, funcName, ordinal)
|
|
}
|
|
|
|
// LookupExportByModule resolves a function address from a module's export table.
|
|
func (d *Dispatcher) LookupExportByModule(moduleBase uint64, funcName string, ordinal uint16) uint64 {
|
|
d.mu.RLock()
|
|
defer d.mu.RUnlock()
|
|
// Check synthetic ntdll/win32u first
|
|
if d.ntdll != nil && moduleBase == d.ntdll.BaseAddr {
|
|
return d.lookupSynthExportLocked(d.ntdll, funcName, ordinal)
|
|
}
|
|
if d.win32u != nil && moduleBase == d.win32u.BaseAddr {
|
|
return d.lookupSynthExportLocked(d.win32u, funcName, ordinal)
|
|
}
|
|
|
|
// Check registered module exports
|
|
if funcName != "" {
|
|
if exports, ok := d.moduleExports[moduleBase]; ok {
|
|
if addr, ok := exports[funcName]; ok {
|
|
return addr
|
|
}
|
|
}
|
|
}
|
|
if ordinal != 0 {
|
|
if ordExports, ok := d.moduleOrdExports[moduleBase]; ok {
|
|
if addr, ok := ordExports[ordinal]; ok {
|
|
return addr
|
|
}
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// RegisterAutoStubNames registers display names for auto-generated stub DLL
|
|
// trap IDs so they appear in trace output. The synth DLL's StubIDs maps
|
|
// stub guest addresses to trap IDs.
|
|
func (d *Dispatcher) RegisterAutoStubNames(synth *SynthPE) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
for _, id := range synth.StubIDs {
|
|
for name, addr := range synth.Exports {
|
|
if synth.StubIDs[addr] == id {
|
|
d.names[id] = synth.Name + "!" + name
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MarkCdeclRange marks all IDs in the range [base, base+count) as cdecl.
|
|
// Used for msvcrt/ucrtbase functions that use cdecl calling convention.
|
|
func (d *Dispatcher) MarkCdeclRange(base uint32, count int) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
for i := 0; i < count; i++ {
|
|
d.cdeclIDs[base+uint32(i)] = true
|
|
}
|
|
}
|
|
|
|
// MarkCdeclModule marks every current and future synthetic export in a module
|
|
// as cdecl. CRT exports can be materialized lazily by GetProcAddress.
|
|
func (d *Dispatcher) MarkCdeclModule(synth *SynthPE) {
|
|
if synth == nil {
|
|
return
|
|
}
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
if d.cdeclModules == nil {
|
|
d.cdeclModules = make(map[string]bool)
|
|
}
|
|
if d.cdeclIDs == nil {
|
|
d.cdeclIDs = make(map[uint32]bool)
|
|
}
|
|
d.cdeclModules[strings.ToLower(synth.Name)] = true
|
|
for _, id := range synth.StubIDs {
|
|
d.cdeclIDs[id] = true
|
|
}
|
|
}
|
|
|
|
// SetStdcallArgCount explicitly sets the arg count for a specific syscall ID.
|
|
func (d *Dispatcher) SetStdcallArgCount(id uint32, nArgs int) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
d.stdcallArgs[id] = nArgs
|
|
}
|
|
|
|
// SetStdcallArgCountByName looks up a function name in a SynthPE and sets
|
|
// its stdcall arg count.
|
|
func (d *Dispatcher) SetStdcallArgCountByName(synth *SynthPE, name string, nArgs int) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
if addr, ok := synth.Exports[name]; ok {
|
|
if id, ok := synth.StubIDs[addr]; ok {
|
|
d.stdcallArgs[id] = nArgs
|
|
}
|
|
}
|
|
}
|
|
|
|
// ApplyWin32ArgCounts sets stdcall arg counts for all known Win32 APIs in a synth DLL.
|
|
func (d *Dispatcher) ApplyWin32ArgCounts(synth *SynthPE) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
d.applyWin32ArgCountsLocked(synth)
|
|
}
|
|
|
|
func (d *Dispatcher) applyWin32ArgCountsLocked(synth *SynthPE) {
|
|
for name, addr := range synth.Exports {
|
|
if nArgs, ok := win32ArgCounts[name]; ok {
|
|
if id, ok := synth.StubIDs[addr]; ok {
|
|
d.stdcallArgs[id] = nArgs
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// PostRegisterSynthDLL wires up any stubs in synth that were added after the
|
|
// initial handler registration pass (e.g., via AddDynamicExport in loadDLLFromVFS).
|
|
// For each export that lacks a handler or stdcall arg count, it checks
|
|
// module handler registry and win32ArgCounts to fill the gap.
|
|
func (d *Dispatcher) PostRegisterSynthDLL(synth *SynthPE) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
if d.handlersByModule == nil {
|
|
d.handlersByModule = make(map[string]map[string]TrapHandler)
|
|
}
|
|
moduleHandlers := d.handlersByModule[strings.ToLower(synth.Name)]
|
|
for funcName, addr := range synth.Exports {
|
|
id, ok := synth.StubIDs[addr]
|
|
if !ok {
|
|
continue
|
|
}
|
|
if d.names[id] == "" {
|
|
d.names[id] = synth.Name + "!" + funcName
|
|
}
|
|
if _, hasHandler := d.handlers[id]; !hasHandler {
|
|
if h, ok := moduleHandlers[funcName]; ok {
|
|
d.handlers[id] = h
|
|
}
|
|
}
|
|
if _, hasArgs := d.stdcallArgs[id]; !hasArgs {
|
|
if nArgs, ok := win32ArgCounts[funcName]; ok {
|
|
d.stdcallArgs[id] = nArgs
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// win32ArgCounts maps Win32 API function names to their stdcall argument counts.
|
|
// This is used for PE32 stdcall cleanup - the callee must pop the correct
|
|
// number of argument bytes from the stack.
|
|
var win32ArgCounts = map[string]int{
|
|
// --- kernel32.dll ---
|
|
"GetModuleHandleA": 1,
|
|
"GetModuleHandleW": 1,
|
|
"GetModuleHandleExA": 3,
|
|
"GetModuleHandleExW": 3,
|
|
"GetModuleFileNameA": 3,
|
|
"GetModuleFileNameW": 3,
|
|
"GetProcAddress": 2,
|
|
"LoadLibraryA": 1,
|
|
"LoadLibraryW": 1,
|
|
"LoadLibraryExA": 3,
|
|
"LoadLibraryExW": 3,
|
|
"FreeLibrary": 1,
|
|
"GetStartupInfoA": 1,
|
|
"GetStartupInfoW": 1,
|
|
"GetCommandLineA": 0,
|
|
"GetCommandLineW": 0,
|
|
"GetEnvironmentVariableA": 3,
|
|
"GetEnvironmentVariableW": 3,
|
|
"GetEnvironmentStrings": 0,
|
|
"GetEnvironmentStringsA": 0,
|
|
"GetEnvironmentStringsW": 0,
|
|
"FreeEnvironmentStringsA": 1,
|
|
"FreeEnvironmentStringsW": 1,
|
|
"SetEnvironmentVariableA": 2,
|
|
"SetEnvironmentVariableW": 2,
|
|
"ExpandEnvironmentStringsA": 3,
|
|
"ExpandEnvironmentStringsW": 3,
|
|
"GetCurrentDirectoryA": 2,
|
|
"GetCurrentDirectoryW": 2,
|
|
"SetCurrentDirectoryA": 1,
|
|
"SetCurrentDirectoryW": 1,
|
|
"GetSystemDirectoryA": 2,
|
|
"GetSystemDirectoryW": 2,
|
|
"GetWindowsDirectoryA": 2,
|
|
"GetWindowsDirectoryW": 2,
|
|
"GetTempPathA": 2,
|
|
"GetTempPathW": 2,
|
|
"GetTempFileNameA": 4,
|
|
"GetTempFileNameW": 4,
|
|
"GetVersionExA": 1,
|
|
"GetVersionExW": 1,
|
|
"GetVersion": 0,
|
|
"RtlGetNtVersionNumbers": 3,
|
|
"GetTickCount": 0,
|
|
"GetTickCount64": 0,
|
|
"QueryPerformanceCounter": 1,
|
|
"QueryPerformanceFrequency": 1,
|
|
"GetSystemTimeAsFileTime": 1,
|
|
"GetSystemTime": 1,
|
|
"GetLocalTime": 1,
|
|
"SystemTimeToFileTime": 2,
|
|
"FileTimeToSystemTime": 2,
|
|
"FileTimeToLocalFileTime": 2,
|
|
"GetLastError": 0,
|
|
"SetLastError": 1,
|
|
"GetCurrentProcess": 0,
|
|
"GetCurrentProcessId": 0,
|
|
"GetCurrentThread": 0,
|
|
"GetCurrentThreadId": 0,
|
|
"ExitProcess": 1,
|
|
"ExitThread": 1,
|
|
"TerminateProcess": 2,
|
|
"CreateProcessA": 10,
|
|
"CreateProcessW": 10,
|
|
"OpenProcess": 3,
|
|
"CloseHandle": 1,
|
|
"DuplicateHandle": 7,
|
|
"GetHandleInformation": 2,
|
|
"SetHandleInformation": 3,
|
|
"CreateThread": 6,
|
|
"ResumeThread": 1,
|
|
"SuspendThread": 1,
|
|
"Sleep": 1,
|
|
"SleepEx": 2,
|
|
"WaitForSingleObject": 2,
|
|
"WaitForSingleObjectEx": 3,
|
|
"WaitForMultipleObjects": 4,
|
|
"WaitForMultipleObjectsEx": 5,
|
|
"CreateEventA": 4,
|
|
"CreateEventW": 4,
|
|
"SetEvent": 1,
|
|
"ResetEvent": 1,
|
|
"CreateMutexA": 3,
|
|
"CreateMutexW": 3,
|
|
"ReleaseMutex": 1,
|
|
"CreateSemaphoreA": 4,
|
|
"CreateSemaphoreW": 4,
|
|
"ReleaseSemaphore": 3,
|
|
"InitializeCriticalSection": 1,
|
|
"InitializeCriticalSectionAndSpinCount": 2,
|
|
"EnterCriticalSection": 1,
|
|
"LeaveCriticalSection": 1,
|
|
"DeleteCriticalSection": 1,
|
|
"TryEnterCriticalSection": 1,
|
|
"InterlockedIncrement": 1,
|
|
"InterlockedDecrement": 1,
|
|
"InterlockedExchange": 2,
|
|
"InterlockedCompareExchange": 3,
|
|
"TlsAlloc": 0,
|
|
"TlsFree": 1,
|
|
"TlsGetValue": 1,
|
|
"TlsSetValue": 2,
|
|
"FlsAlloc": 1,
|
|
"FlsFree": 1,
|
|
"FlsGetValue": 1,
|
|
"FlsSetValue": 2,
|
|
"GetStdHandle": 1,
|
|
"SetStdHandle": 2,
|
|
"ReadFile": 5,
|
|
"WriteFile": 5,
|
|
"CreateFileA": 7,
|
|
"CreateFileW": 7,
|
|
"DeleteFileA": 1,
|
|
"DeleteFileW": 1,
|
|
"MoveFileA": 2,
|
|
"MoveFileW": 2,
|
|
"MoveFileExA": 3,
|
|
"MoveFileExW": 3,
|
|
"CopyFileA": 3,
|
|
"CopyFileW": 3,
|
|
"GetFileSize": 2,
|
|
"GetFileSizeEx": 2,
|
|
"GetFileType": 1,
|
|
"SetFilePointer": 4,
|
|
"SetFilePointerEx": 4,
|
|
"FlushFileBuffers": 1,
|
|
"SetEndOfFile": 1,
|
|
"GetFileAttributesA": 1,
|
|
"GetFileAttributesW": 1,
|
|
"GetFileAttributesExA": 3,
|
|
"GetFileAttributesExW": 3,
|
|
"SetFileAttributesA": 2,
|
|
"SetFileAttributesW": 2,
|
|
"FindFirstFileA": 2,
|
|
"FindFirstFileW": 2,
|
|
"FindNextFileA": 2,
|
|
"FindNextFileW": 2,
|
|
"FindClose": 1,
|
|
"CreateDirectoryA": 2,
|
|
"CreateDirectoryW": 2,
|
|
"RemoveDirectoryA": 1,
|
|
"RemoveDirectoryW": 1,
|
|
"GetFullPathNameA": 4,
|
|
"GetFullPathNameW": 4,
|
|
"GetLongPathNameA": 3,
|
|
"GetLongPathNameW": 3,
|
|
"GetShortPathNameA": 3,
|
|
"GetShortPathNameW": 3,
|
|
"GetPrivateProfileIntA": 4,
|
|
"GetPrivateProfileIntW": 4,
|
|
"GetPrivateProfileStringA": 6,
|
|
"GetPrivateProfileStringW": 6,
|
|
"WritePrivateProfileStringA": 4,
|
|
"WritePrivateProfileStringW": 4,
|
|
"GetProfileIntA": 3,
|
|
"GetProfileIntW": 3,
|
|
"GetProfileStringA": 5,
|
|
"GetProfileStringW": 5,
|
|
"WriteProfileStringA": 3,
|
|
"WriteProfileStringW": 3,
|
|
"HeapCreate": 3,
|
|
"HeapDestroy": 1,
|
|
"HeapAlloc": 3,
|
|
"HeapReAlloc": 4,
|
|
"HeapFree": 3,
|
|
"HeapSize": 3,
|
|
"GetProcessHeap": 0,
|
|
"GlobalAlloc": 2,
|
|
"GlobalFree": 1,
|
|
"GlobalLock": 1,
|
|
"GlobalUnlock": 1,
|
|
"GlobalReAlloc": 3,
|
|
"GlobalSize": 1,
|
|
"LocalAlloc": 2,
|
|
"LocalFree": 1,
|
|
"LocalLock": 1,
|
|
"LocalUnlock": 1,
|
|
"LocalReAlloc": 3,
|
|
"LocalSize": 1,
|
|
"VirtualAlloc": 4,
|
|
"VirtualFree": 3,
|
|
"VirtualProtect": 4,
|
|
"VirtualQuery": 3,
|
|
"GetSystemInfo": 1,
|
|
"GetNativeSystemInfo": 1,
|
|
"IsProcessorFeaturePresent": 1,
|
|
"GetLocaleInfoA": 4,
|
|
"GetLocaleInfoW": 4,
|
|
"GetUserDefaultLCID": 0,
|
|
"GetSystemDefaultLCID": 0,
|
|
"GetACP": 0,
|
|
"GetOEMCP": 0,
|
|
"IsValidCodePage": 1,
|
|
"GetCPInfo": 2,
|
|
"MultiByteToWideChar": 6,
|
|
"WideCharToMultiByte": 8,
|
|
"LCMapStringA": 6,
|
|
"LCMapStringW": 6,
|
|
"CompareStringA": 6,
|
|
"CompareStringW": 6,
|
|
"GetStringTypeA": 5,
|
|
"GetStringTypeW": 4,
|
|
"GetStringTypeExA": 5,
|
|
"GetStringTypeExW": 5,
|
|
"GetTimeZoneInformation": 1,
|
|
"GetConsoleMode": 2,
|
|
"SetConsoleMode": 2,
|
|
"GetConsoleCP": 0,
|
|
"GetConsoleOutputCP": 0,
|
|
"SetConsoleCP": 1,
|
|
"SetConsoleOutputCP": 1,
|
|
"WriteConsoleA": 5,
|
|
"WriteConsoleW": 5,
|
|
"ReadConsoleA": 5,
|
|
"ReadConsoleW": 5,
|
|
"FillConsoleOutputCharacterA": 5,
|
|
"FillConsoleOutputCharacterW": 5,
|
|
"SetConsoleTitleA": 1,
|
|
"SetConsoleTitleW": 1,
|
|
"AllocConsole": 0,
|
|
"FreeConsole": 0,
|
|
"GetConsoleScreenBufferInfo": 2,
|
|
"SetConsoleTextAttribute": 2,
|
|
"SetConsoleCtrlHandler": 2,
|
|
"SetUnhandledExceptionFilter": 1,
|
|
"UnhandledExceptionFilter": 1,
|
|
"RaiseException": 4,
|
|
"RtlUnwind": 4,
|
|
"IsDebuggerPresent": 0,
|
|
"OutputDebugStringA": 1,
|
|
"OutputDebugStringW": 1,
|
|
"DebugBreak": 0,
|
|
"GetComputerNameA": 2,
|
|
"GetComputerNameW": 2,
|
|
"lstrlenA": 1,
|
|
"lstrlenW": 1,
|
|
"lstrcmpA": 2,
|
|
"lstrcmpW": 2,
|
|
"lstrcmpiA": 2,
|
|
"lstrcmpiW": 2,
|
|
"lstrcpyA": 2,
|
|
"lstrcpyW": 2,
|
|
"lstrcpynA": 3,
|
|
"lstrcpynW": 3,
|
|
"lstrcatA": 2,
|
|
"lstrcatW": 2,
|
|
"FormatMessageA": 7,
|
|
"FormatMessageW": 7,
|
|
"LoadResource": 2,
|
|
"LockResource": 1,
|
|
"SizeofResource": 2,
|
|
"FindResourceA": 3,
|
|
"FindResourceW": 3,
|
|
"FindResourceExA": 4,
|
|
"FindResourceExW": 4,
|
|
"EnumResourceTypesA": 3,
|
|
"EnumResourceTypesW": 3,
|
|
"EnumResourceNamesA": 4,
|
|
"EnumResourceNamesW": 4,
|
|
"BeginUpdateResourceA": 2,
|
|
"BeginUpdateResourceW": 2,
|
|
"UpdateResourceA": 6,
|
|
"UpdateResourceW": 6,
|
|
"EndUpdateResourceA": 2,
|
|
"EndUpdateResourceW": 2,
|
|
"SetErrorMode": 1,
|
|
"GetDriveTypeA": 1,
|
|
"GetDriveTypeW": 1,
|
|
"GetDiskFreeSpaceA": 5,
|
|
"GetDiskFreeSpaceW": 5,
|
|
"GetLogicalDrives": 0,
|
|
"GetVolumeInformationA": 8,
|
|
"GetVolumeInformationW": 8,
|
|
"CreateFileMappingA": 6,
|
|
"CreateFileMappingW": 6,
|
|
"MapViewOfFile": 5,
|
|
"UnmapViewOfFile": 1,
|
|
"DeviceIoControl": 8,
|
|
"GetOverlappedResult": 4,
|
|
"CreatePipe": 4,
|
|
"PeekNamedPipe": 6,
|
|
"ConnectNamedPipe": 2,
|
|
"DisconnectNamedPipe": 1,
|
|
"CreateNamedPipeA": 8,
|
|
"CreateNamedPipeW": 8,
|
|
"GetDateFormatA": 6,
|
|
"GetDateFormatW": 6,
|
|
"GetTimeFormatA": 6,
|
|
"GetTimeFormatW": 6,
|
|
"GetNumberFormatA": 6,
|
|
"GetNumberFormatW": 6,
|
|
"IsDBCSLeadByte": 1,
|
|
"EnumSystemLocalesA": 2,
|
|
"EnumSystemLocalesW": 2,
|
|
"AddAtomA": 1,
|
|
"AddAtomW": 1,
|
|
"FindAtomA": 1,
|
|
"FindAtomW": 1,
|
|
"GetAtomNameA": 3,
|
|
"GetAtomNameW": 3,
|
|
"DeleteAtom": 1,
|
|
"GlobalAddAtomA": 1,
|
|
"GlobalAddAtomW": 1,
|
|
"GlobalFindAtomA": 1,
|
|
"GlobalFindAtomW": 1,
|
|
"GlobalGetAtomNameA": 3,
|
|
"GlobalGetAtomNameW": 3,
|
|
"GlobalDeleteAtom": 1,
|
|
"SetFileTime": 4,
|
|
"GetFileTime": 4,
|
|
"CompareFileTime": 2,
|
|
"GetProcessAffinityMask": 3,
|
|
"SetProcessAffinityMask": 2,
|
|
"SetThreadAffinityMask": 2,
|
|
"GetThreadPriority": 1,
|
|
"SetThreadPriority": 2,
|
|
"GetPriorityClass": 1,
|
|
"SetPriorityClass": 2,
|
|
"CreateToolhelp32Snapshot": 2,
|
|
"Process32First": 2,
|
|
"Process32Next": 2,
|
|
"Process32FirstW": 2,
|
|
"Process32NextW": 2,
|
|
"Thread32First": 2,
|
|
"Thread32Next": 2,
|
|
"Module32First": 2,
|
|
"Module32Next": 2,
|
|
"Module32FirstW": 2,
|
|
"Module32NextW": 2,
|
|
"Heap32ListFirst": 2,
|
|
"Heap32ListNext": 2,
|
|
"GetThreadContext": 2,
|
|
"SetThreadContext": 2,
|
|
"ReadProcessMemory": 5,
|
|
"WriteProcessMemory": 5,
|
|
"GetExitCodeProcess": 2,
|
|
"GetExitCodeThread": 2,
|
|
"InitializeSListHead": 1,
|
|
"InterlockedFlushSList": 1,
|
|
"InterlockedPopEntrySList": 1,
|
|
"InterlockedPushEntrySList": 2,
|
|
"QueryDepthSList": 1,
|
|
"EncodePointer": 1,
|
|
"DecodePointer": 1,
|
|
"IsWow64Process": 2,
|
|
|
|
// --- user32.dll ---
|
|
"RegisterClassA": 1,
|
|
"RegisterClassW": 1,
|
|
"RegisterClassExA": 1,
|
|
"RegisterClassExW": 1,
|
|
"UnregisterClassA": 2,
|
|
"UnregisterClassW": 2,
|
|
"CreateWindowExA": 12,
|
|
"CreateWindowExW": 12,
|
|
"DestroyWindow": 1,
|
|
"ShowWindow": 2,
|
|
"UpdateWindow": 1,
|
|
"MoveWindow": 6,
|
|
"SetWindowPos": 7,
|
|
"BeginDeferWindowPos": 1,
|
|
"DeferWindowPos": 8,
|
|
"EndDeferWindowPos": 1,
|
|
"GetEffectiveClientRect": 3,
|
|
"GetWindowRect": 2,
|
|
"GetClientRect": 2,
|
|
"AdjustWindowRect": 3,
|
|
"AdjustWindowRectEx": 4,
|
|
"SetWindowTextA": 2,
|
|
"SetWindowTextW": 2,
|
|
"GetWindowTextA": 3,
|
|
"GetWindowTextW": 3,
|
|
"GetWindowTextLengthA": 1,
|
|
"GetWindowTextLengthW": 1,
|
|
"GetWindowLongA": 2,
|
|
"GetWindowLongW": 2,
|
|
"SetWindowLongA": 3,
|
|
"SetWindowLongW": 3,
|
|
"GetClassLongA": 2,
|
|
"GetClassLongW": 2,
|
|
"SetClassLongA": 3,
|
|
"SetClassLongW": 3,
|
|
"GetClassNameA": 3,
|
|
"GetClassNameW": 3,
|
|
"GetParent": 1,
|
|
"SetParent": 2,
|
|
"FindWindowA": 2,
|
|
"FindWindowW": 2,
|
|
"FindWindowExA": 4,
|
|
"FindWindowExW": 4,
|
|
"IsWindow": 1,
|
|
"IsWindowVisible": 1,
|
|
"IsWindowEnabled": 1,
|
|
"EnableWindow": 2,
|
|
"GetForegroundWindow": 0,
|
|
"SetForegroundWindow": 1,
|
|
"GetActiveWindow": 0,
|
|
"SetActiveWindow": 1,
|
|
"GetFocus": 0,
|
|
"SetFocus": 1,
|
|
"GetCapture": 0,
|
|
"SetCapture": 1,
|
|
"ReleaseCapture": 0,
|
|
"GetDesktopWindow": 0,
|
|
"GetDC": 1,
|
|
"GetDCEx": 3,
|
|
"GetWindowDC": 1,
|
|
"ReleaseDC": 2,
|
|
"BeginPaint": 2,
|
|
"EndPaint": 2,
|
|
"InvalidateRect": 3,
|
|
"ValidateRect": 2,
|
|
"RedrawWindow": 4,
|
|
"GetUpdateRect": 3,
|
|
"GetMessageA": 4,
|
|
"GetMessageW": 4,
|
|
"PeekMessageA": 5,
|
|
"PeekMessageW": 5,
|
|
"TranslateMessage": 1,
|
|
"DispatchMessageA": 1,
|
|
"DispatchMessageW": 1,
|
|
"PostMessageA": 4,
|
|
"PostMessageW": 4,
|
|
"SendMessageA": 4,
|
|
"SendMessageW": 4,
|
|
"InSendMessage": 0,
|
|
"InSendMessageEx": 1,
|
|
"ReplyMessage": 1,
|
|
"QuerySendMessage": 0,
|
|
"PostQuitMessage": 1,
|
|
"DefWindowProcA": 4,
|
|
"DefWindowProcW": 4,
|
|
"CallWindowProcA": 5,
|
|
"CallWindowProcW": 5,
|
|
"MessageBoxA": 4,
|
|
"MessageBoxW": 4,
|
|
"MessageBoxExA": 5,
|
|
"MessageBoxExW": 5,
|
|
"DialogBoxParamA": 5,
|
|
"DialogBoxParamW": 5,
|
|
"CreateDialogParamA": 5,
|
|
"CreateDialogParamW": 5,
|
|
"EndDialog": 2,
|
|
"GetDlgItem": 2,
|
|
"GetDlgItemTextA": 4,
|
|
"GetDlgItemTextW": 4,
|
|
"SetDlgItemTextA": 3,
|
|
"SetDlgItemTextW": 3,
|
|
"GetDlgItemInt": 4,
|
|
"SetDlgItemInt": 4,
|
|
"SendDlgItemMessageA": 5,
|
|
"SendDlgItemMessageW": 5,
|
|
"CheckDlgButton": 3,
|
|
"IsDlgButtonChecked": 2,
|
|
"CheckRadioButton": 4,
|
|
"GetDlgCtrlID": 1,
|
|
"IsDialogMessageA": 2,
|
|
"IsDialogMessageW": 2,
|
|
"MapDialogRect": 2,
|
|
"LoadIconA": 2,
|
|
"LoadIconW": 2,
|
|
"LoadCursorA": 2,
|
|
"LoadCursorW": 2,
|
|
"LoadImageA": 6,
|
|
"LoadImageW": 6,
|
|
"LoadBitmapA": 2,
|
|
"LoadBitmapW": 2,
|
|
"SetCursor": 1,
|
|
"GetCursor": 0,
|
|
"ShowCursor": 1,
|
|
"GetCursorPos": 1,
|
|
"SetCursorPos": 2,
|
|
"ClipCursor": 1,
|
|
"GetSystemMetrics": 1,
|
|
"SystemParametersInfoA": 4,
|
|
"SystemParametersInfoW": 4,
|
|
"LoadStringA": 4,
|
|
"LoadStringW": 4,
|
|
"LoadMenuA": 2,
|
|
"LoadMenuW": 2,
|
|
"CreateMenu": 0,
|
|
"CreatePopupMenu": 0,
|
|
"DestroyMenu": 1,
|
|
"GetMenu": 1,
|
|
"SetMenu": 2,
|
|
"GetSubMenu": 2,
|
|
"GetMenuItemCount": 1,
|
|
"GetMenuItemID": 2,
|
|
"GetMenuState": 3,
|
|
"GetMenuStringA": 5,
|
|
"GetMenuStringW": 5,
|
|
"AppendMenuA": 4,
|
|
"AppendMenuW": 4,
|
|
"InsertMenuA": 5,
|
|
"InsertMenuW": 5,
|
|
"InsertMenuItemA": 4,
|
|
"InsertMenuItemW": 4,
|
|
"DeleteMenu": 3,
|
|
"RemoveMenu": 3,
|
|
"EnableMenuItem": 3,
|
|
"CheckMenuItem": 3,
|
|
"CheckMenuRadioItem": 5,
|
|
"DrawMenuBar": 1,
|
|
"TrackPopupMenu": 7,
|
|
"TrackPopupMenuEx": 6,
|
|
"GetMenuInfo": 2,
|
|
"SetMenuInfo": 2,
|
|
"GetMenuItemInfoA": 4,
|
|
"GetMenuItemInfoW": 4,
|
|
"SetMenuItemInfoA": 4,
|
|
"SetMenuItemInfoW": 4,
|
|
"LoadAcceleratorsA": 2,
|
|
"LoadAcceleratorsW": 2,
|
|
"TranslateAcceleratorA": 3,
|
|
"TranslateAcceleratorW": 3,
|
|
"DestroyAcceleratorTable": 1,
|
|
"SetTimer": 4,
|
|
"KillTimer": 2,
|
|
"SetWindowsHookExA": 4,
|
|
"SetWindowsHookExW": 4,
|
|
"UnhookWindowsHookEx": 1,
|
|
"CallNextHookEx": 4,
|
|
"MapVirtualKeyA": 2,
|
|
"MapVirtualKeyW": 2,
|
|
"MapVirtualKeyExA": 3,
|
|
"MapVirtualKeyExW": 3,
|
|
"GetKeyState": 1,
|
|
"GetAsyncKeyState": 1,
|
|
"GetKeyboardState": 1,
|
|
"SetKeyboardState": 1,
|
|
"ToAscii": 5,
|
|
"ToUnicode": 6,
|
|
"VkKeyScanA": 1,
|
|
"VkKeyScanW": 1,
|
|
"GetKeyNameTextA": 3,
|
|
"GetKeyNameTextW": 3,
|
|
"SetRect": 5,
|
|
"SetRectEmpty": 1,
|
|
"CopyRect": 2,
|
|
"InflateRect": 3,
|
|
"OffsetRect": 3,
|
|
"IntersectRect": 3,
|
|
"UnionRect": 3,
|
|
"SubtractRect": 3,
|
|
"IsRectEmpty": 1,
|
|
"PtInRect": 3,
|
|
"EqualRect": 2,
|
|
"FillRect": 3,
|
|
"FrameRect": 3,
|
|
"DrawEdge": 4,
|
|
"DrawFrameControl": 4,
|
|
"DrawTextA": 5,
|
|
"DrawTextW": 5,
|
|
"DrawTextExA": 6,
|
|
"DrawTextExW": 6,
|
|
"ClientToScreen": 2,
|
|
"ScreenToClient": 2,
|
|
"MapWindowPoints": 4,
|
|
"GetSysColor": 1,
|
|
"GetSysColorBrush": 1,
|
|
"SetSysColors": 3,
|
|
"MsgWaitForMultipleObjects": 5,
|
|
"MsgWaitForMultipleObjectsEx": 5,
|
|
"WaitMessage": 0,
|
|
"RegisterWindowMessageA": 1,
|
|
"RegisterWindowMessageW": 1,
|
|
"GetClassInfoA": 3,
|
|
"GetClassInfoW": 3,
|
|
"GetClassInfoExA": 3,
|
|
"GetClassInfoExW": 3,
|
|
"ScrollWindow": 5,
|
|
"ScrollWindowEx": 8,
|
|
"GetScrollInfo": 3,
|
|
"SetScrollInfo": 4,
|
|
"GetScrollPos": 2,
|
|
"SetScrollPos": 4,
|
|
"GetScrollRange": 4,
|
|
"SetScrollRange": 5,
|
|
"ShowScrollBar": 3,
|
|
"EnableScrollBar": 3,
|
|
"OpenClipboard": 1,
|
|
"CloseClipboard": 0,
|
|
"EmptyClipboard": 0,
|
|
"GetClipboardData": 1,
|
|
"SetClipboardData": 2,
|
|
"IsClipboardFormatAvailable": 1,
|
|
"RegisterClipboardFormatA": 1,
|
|
"RegisterClipboardFormatW": 1,
|
|
"CountClipboardFormats": 0,
|
|
"EnumClipboardFormats": 1,
|
|
"GetClipboardOwner": 0,
|
|
"CharNextA": 1,
|
|
"CharNextW": 1,
|
|
"CharPrevA": 2,
|
|
"CharPrevW": 2,
|
|
"CharUpperA": 1,
|
|
"CharUpperW": 1,
|
|
"CharLowerA": 1,
|
|
"CharLowerW": 1,
|
|
"CharUpperBuffA": 2,
|
|
"CharUpperBuffW": 2,
|
|
"CharLowerBuffA": 2,
|
|
"CharLowerBuffW": 2,
|
|
"wsprintfA": 0, // cdecl variadic
|
|
"wsprintfW": 0, // cdecl variadic
|
|
"wvsprintfA": 3,
|
|
"wvsprintfW": 3,
|
|
"GetWindow": 2,
|
|
"GetTopWindow": 1,
|
|
"EnumWindows": 2,
|
|
"EnumChildWindows": 3,
|
|
"EnumThreadWindows": 3,
|
|
"IsChild": 2,
|
|
"GetPropA": 2,
|
|
"GetPropW": 2,
|
|
"SetPropA": 3,
|
|
"SetPropW": 3,
|
|
"RemovePropA": 2,
|
|
"RemovePropW": 2,
|
|
"MonitorFromPoint": 2,
|
|
"MonitorFromRect": 2,
|
|
"MonitorFromWindow": 2,
|
|
"GetMonitorInfoA": 2,
|
|
"GetMonitorInfoW": 2,
|
|
"EnumDisplayMonitors": 4,
|
|
"ChangeDisplaySettingsA": 2,
|
|
"ChangeDisplaySettingsW": 2,
|
|
"ChangeDisplaySettingsExA": 5,
|
|
"ChangeDisplaySettingsExW": 5,
|
|
"EnumDisplaySettingsA": 3,
|
|
"EnumDisplaySettingsW": 3,
|
|
"EnumDisplayDevicesA": 4,
|
|
"EnumDisplayDevicesW": 4,
|
|
"CreateIconFromResource": 4,
|
|
"CreateIconFromResourceEx": 7,
|
|
"DestroyIcon": 1,
|
|
"DestroyCursor": 1,
|
|
"DrawIconEx": 9,
|
|
"GetIconInfo": 2,
|
|
"CopyIcon": 1,
|
|
"GetWindowPlacement": 2,
|
|
"SetWindowPlacement": 2,
|
|
"GetComboBoxInfo": 2,
|
|
"GetListBoxInfo": 1,
|
|
"AnimateWindow": 3,
|
|
"FlashWindow": 2,
|
|
"FlashWindowEx": 1,
|
|
"MessageBeep": 1,
|
|
"GetUserObjectInformationA": 5,
|
|
"GetUserObjectInformationW": 5,
|
|
"SendNotifyMessageA": 4,
|
|
"SendNotifyMessageW": 4,
|
|
"SendMessageTimeoutA": 7,
|
|
"SendMessageTimeoutW": 7,
|
|
"BroadcastSystemMessageA": 5,
|
|
"BroadcastSystemMessageW": 5,
|
|
"SetLayeredWindowAttributes": 4,
|
|
"GetLayeredWindowAttributes": 4,
|
|
"UpdateLayeredWindow": 9,
|
|
"PrintWindow": 3,
|
|
"SetWindowRgn": 3,
|
|
"GetWindowRgn": 2,
|
|
"GetProcessWindowStation": 0,
|
|
"GetThreadDesktop": 1,
|
|
|
|
// --- gdi32.dll ---
|
|
"GetDeviceCaps": 2,
|
|
"CreatePen": 3,
|
|
"CreatePenIndirect": 1,
|
|
"ExtCreatePen": 5,
|
|
"CreateSolidBrush": 1,
|
|
"CreateHatchBrush": 2,
|
|
"CreatePatternBrush": 1,
|
|
"CreateBrushIndirect": 1,
|
|
"CreateBitmapIndirect": 1,
|
|
"CreateBitmap": 5,
|
|
"CreateCompatibleBitmap": 3,
|
|
"CreateDIBSection": 6,
|
|
"CreateDIBitmap": 6,
|
|
"SelectObject": 2,
|
|
"DeleteObject": 1,
|
|
"GetObjectA": 3,
|
|
"GetObjectW": 3,
|
|
"GetObjectType": 1,
|
|
"GetCurrentObject": 2,
|
|
"GetStockObject": 1,
|
|
"SetBkColor": 2,
|
|
"GetBkColor": 1,
|
|
"SetBkMode": 2,
|
|
"GetBkMode": 1,
|
|
"SetTextColor": 2,
|
|
"GetTextColor": 1,
|
|
"SetTextAlign": 2,
|
|
"GetTextAlign": 1,
|
|
"TextOutA": 5,
|
|
"TextOutW": 5,
|
|
"ExtTextOutA": 8,
|
|
"ExtTextOutW": 8,
|
|
"GetTextExtentPoint32A": 4,
|
|
"GetTextExtentPoint32W": 4,
|
|
"GetTextExtentExPointA": 7,
|
|
"GetTextExtentExPointW": 7,
|
|
"GetTextMetricsA": 2,
|
|
"GetTextMetricsW": 2,
|
|
"GetTextFaceA": 3,
|
|
"GetTextFaceW": 3,
|
|
"BitBlt": 9,
|
|
"StretchBlt": 11,
|
|
"PatBlt": 5,
|
|
"MaskBlt": 12,
|
|
"TransparentBlt": 11,
|
|
"AlphaBlend": 11,
|
|
"CreateCompatibleDC": 1,
|
|
"CreateDCA": 4,
|
|
"CreateDCW": 4,
|
|
"DeleteDC": 1,
|
|
"AbortDoc": 1,
|
|
"StartDocA": 2,
|
|
"StartDocW": 2,
|
|
"StartPage": 1,
|
|
"EndPage": 1,
|
|
"EndDoc": 1,
|
|
"SaveDC": 1,
|
|
"RestoreDC": 2,
|
|
"SetMapMode": 2,
|
|
"GetMapMode": 1,
|
|
"SetViewportOrgEx": 4,
|
|
"GetViewportOrgEx": 2,
|
|
"SetViewportExtEx": 4,
|
|
"GetViewportExtEx": 2,
|
|
"SetWindowOrgEx": 4,
|
|
"GetWindowOrgEx": 2,
|
|
"SetWindowExtEx": 4,
|
|
"GetWindowExtEx": 2,
|
|
"DPtoLP": 3,
|
|
"LPtoDP": 3,
|
|
"SetROP2": 2,
|
|
"GetROP2": 1,
|
|
"SetPolyFillMode": 2,
|
|
"GetPolyFillMode": 1,
|
|
"MoveToEx": 4,
|
|
"LineTo": 3,
|
|
"Rectangle": 5,
|
|
"Ellipse": 5,
|
|
"Polygon": 3,
|
|
"Polyline": 3,
|
|
"PolyBezier": 3,
|
|
"PolyBezierTo": 3,
|
|
"Arc": 9,
|
|
"ArcTo": 9,
|
|
"Pie": 9,
|
|
"Chord": 9,
|
|
"RoundRect": 7,
|
|
"SetPixel": 4,
|
|
"GetPixel": 3,
|
|
"SetPixelV": 4,
|
|
"CreateFontA": 14,
|
|
"CreateFontW": 14,
|
|
"CreateFontIndirectA": 1,
|
|
"CreateFontIndirectW": 1,
|
|
"EnumFontFamiliesA": 4,
|
|
"EnumFontFamiliesW": 4,
|
|
"EnumFontFamiliesExA": 5,
|
|
"EnumFontFamiliesExW": 5,
|
|
"AddFontResourceA": 1,
|
|
"AddFontResourceW": 1,
|
|
"AddFontResourceExA": 3,
|
|
"AddFontResourceExW": 3,
|
|
"RemoveFontResourceA": 1,
|
|
"RemoveFontResourceW": 1,
|
|
"GetDIBits": 7,
|
|
"SetDIBits": 7,
|
|
"SetDIBitsToDevice": 12,
|
|
"StretchDIBits": 13,
|
|
"CreateRectRgn": 4,
|
|
"CreateRectRgnIndirect": 1,
|
|
"CreateEllipticRgn": 4,
|
|
"CreateRoundRectRgn": 6,
|
|
"CreatePolygonRgn": 3,
|
|
"CombineRgn": 4,
|
|
"EqualRgn": 2,
|
|
"GetRgnBox": 2,
|
|
"OffsetRgn": 3,
|
|
"PtInRegion": 3,
|
|
"RectInRegion": 2,
|
|
"SelectClipRgn": 2,
|
|
"ExtSelectClipRgn": 3,
|
|
"GetClipBox": 2,
|
|
"GetClipRgn": 2,
|
|
"IntersectClipRect": 5,
|
|
"ExcludeClipRect": 5,
|
|
"SetStretchBltMode": 2,
|
|
"GetStretchBltMode": 1,
|
|
"CreateMetaFileA": 1,
|
|
"CreateMetaFileW": 1,
|
|
"CloseMetaFile": 1,
|
|
"PlayMetaFile": 2,
|
|
"CreateEnhMetaFileA": 4,
|
|
"CreateEnhMetaFileW": 4,
|
|
"CloseEnhMetaFile": 1,
|
|
"PlayEnhMetaFile": 3,
|
|
"GetEnhMetaFileHeader": 3,
|
|
"DeleteEnhMetaFile": 1,
|
|
"GdiFlush": 0,
|
|
"SetLayout": 2,
|
|
"GetLayout": 1,
|
|
"SetGraphicsMode": 2,
|
|
"GetGraphicsMode": 1,
|
|
"SetWorldTransform": 2,
|
|
"GetWorldTransform": 2,
|
|
"ModifyWorldTransform": 3,
|
|
"BeginPath": 1,
|
|
"EndPath": 1,
|
|
"StrokePath": 1,
|
|
"FillPath": 1,
|
|
"StrokeAndFillPath": 1,
|
|
"CloseFigure": 1,
|
|
"FlattenPath": 1,
|
|
"WidenPath": 1,
|
|
"PathToRegion": 1,
|
|
"GetPath": 4,
|
|
"AbortPath": 1,
|
|
"SetMiterLimit": 3,
|
|
"GetMiterLimit": 2,
|
|
"GetNearestColor": 2,
|
|
|
|
// --- advapi32.dll ---
|
|
"RegOpenKeyExA": 5,
|
|
"RegOpenKeyExW": 5,
|
|
"RegCreateKeyExA": 9,
|
|
"RegCreateKeyExW": 9,
|
|
"RegCloseKey": 1,
|
|
"RegQueryValueExA": 6,
|
|
"RegQueryValueExW": 6,
|
|
"RegSetValueExA": 6,
|
|
"RegSetValueExW": 6,
|
|
"RegDeleteKeyA": 2,
|
|
"RegDeleteKeyW": 2,
|
|
"RegDeleteValueA": 2,
|
|
"RegDeleteValueW": 2,
|
|
"RegEnumKeyExA": 8,
|
|
"RegEnumKeyExW": 8,
|
|
"RegEnumValueA": 8,
|
|
"RegEnumValueW": 8,
|
|
"RegQueryInfoKeyA": 12,
|
|
"RegQueryInfoKeyW": 12,
|
|
"RegFlushKey": 1,
|
|
"RegNotifyChangeKeyValue": 5,
|
|
"OpenProcessToken": 3,
|
|
"OpenThreadToken": 4,
|
|
"GetTokenInformation": 5,
|
|
"SetTokenInformation": 4,
|
|
"AdjustTokenPrivileges": 6,
|
|
"LookupPrivilegeValueA": 3,
|
|
"LookupPrivilegeValueW": 3,
|
|
"LookupAccountSidA": 7,
|
|
"LookupAccountSidW": 7,
|
|
"LookupAccountNameA": 7,
|
|
"LookupAccountNameW": 7,
|
|
"ConvertSidToStringSidA": 2,
|
|
"ConvertSidToStringSidW": 2,
|
|
"ConvertStringSidToSidA": 2,
|
|
"ConvertStringSidToSidW": 2,
|
|
"IsValidSid": 1,
|
|
"GetLengthSid": 1,
|
|
"CopySid": 3,
|
|
"EqualSid": 2,
|
|
"AllocateAndInitializeSid": 9,
|
|
"FreeSid": 1,
|
|
"GetSidSubAuthority": 2,
|
|
"GetSidSubAuthorityCount": 1,
|
|
"InitializeSecurityDescriptor": 2,
|
|
"SetSecurityDescriptorDacl": 4,
|
|
"GetSecurityDescriptorDacl": 4,
|
|
"InitializeAcl": 3,
|
|
"AddAccessAllowedAce": 4,
|
|
"GetUserNameA": 2,
|
|
"GetUserNameW": 2,
|
|
"CryptAcquireContextA": 5,
|
|
"CryptAcquireContextW": 5,
|
|
"CryptReleaseContext": 2,
|
|
"CryptGenRandom": 3,
|
|
"CryptCreateHash": 5,
|
|
"CryptHashData": 4,
|
|
"CryptGetHashParam": 5,
|
|
"CryptDestroyHash": 1,
|
|
"CryptDeriveKey": 5,
|
|
"CryptDecrypt": 6,
|
|
"CryptEncrypt": 7,
|
|
"CryptDestroyKey": 1,
|
|
"CryptExportKey": 6,
|
|
"CryptImportKey": 6,
|
|
"CryptSetKeyParam": 4,
|
|
"CryptGetKeyParam": 5,
|
|
|
|
// --- shell32.dll ---
|
|
"ShellExecuteA": 6,
|
|
"ShellExecuteW": 6,
|
|
"ShellExecuteExA": 1,
|
|
"ShellExecuteExW": 1,
|
|
"ShellAboutA": 4,
|
|
"ShellAboutW": 4,
|
|
"SHGetFolderPathA": 5,
|
|
"SHGetFolderPathW": 5,
|
|
"SHGetSpecialFolderPathA": 4,
|
|
"SHGetSpecialFolderPathW": 4,
|
|
"SHGetPathFromIDListA": 2,
|
|
"SHGetPathFromIDListW": 2,
|
|
"SHBrowseForFolderA": 1,
|
|
"SHBrowseForFolderW": 1,
|
|
"SHFileOperationA": 1,
|
|
"SHFileOperationW": 1,
|
|
"SHGetDesktopFolder": 1,
|
|
"SHCreateDirectoryExA": 3,
|
|
"SHCreateDirectoryExW": 3,
|
|
"DragAcceptFiles": 2,
|
|
"DragQueryFileA": 4,
|
|
"DragQueryFileW": 4,
|
|
"DragFinish": 1,
|
|
"ExtractIconA": 3,
|
|
"ExtractIconW": 3,
|
|
"ExtractIconExA": 5,
|
|
"ExtractIconExW": 5,
|
|
"FindExecutableA": 3,
|
|
"FindExecutableW": 3,
|
|
|
|
// --- winmm.dll ---
|
|
"PlaySoundA": 3,
|
|
"PlaySoundW": 3,
|
|
"timeGetTime": 0,
|
|
"timeBeginPeriod": 1,
|
|
"timeEndPeriod": 1,
|
|
"timeSetEvent": 5,
|
|
"timeKillEvent": 1,
|
|
"waveOutOpen": 6,
|
|
"waveOutClose": 1,
|
|
"waveOutWrite": 3,
|
|
"waveOutPrepareHeader": 3,
|
|
"waveOutUnprepareHeader": 3,
|
|
"waveOutReset": 1,
|
|
"waveOutGetNumDevs": 0,
|
|
"waveOutGetDevCapsA": 3,
|
|
"waveOutGetDevCapsW": 3,
|
|
"mciSendCommandA": 4,
|
|
"mciSendCommandW": 4,
|
|
"mciSendStringA": 4,
|
|
"mciSendStringW": 4,
|
|
"mciGetErrorStringA": 3,
|
|
"mciGetErrorStringW": 3,
|
|
"midiOutOpen": 5,
|
|
"midiOutClose": 1,
|
|
"midiOutShortMsg": 2,
|
|
|
|
// --- ole32.dll ---
|
|
"CoInitialize": 1,
|
|
"CoInitializeEx": 2,
|
|
"CoUninitialize": 0,
|
|
"CoCreateInstance": 5,
|
|
"CoTaskMemAlloc": 1,
|
|
"CoTaskMemRealloc": 2,
|
|
"CoTaskMemFree": 1,
|
|
"CoRegisterClassObject": 5,
|
|
"CoRevokeClassObject": 1,
|
|
"CLSIDFromProgID": 2,
|
|
"CLSIDFromString": 2,
|
|
"StringFromCLSID": 2,
|
|
"StringFromGUID2": 3,
|
|
"ProgIDFromCLSID": 2,
|
|
|
|
// --- oleaut32.dll ---
|
|
"SysAllocString": 1,
|
|
"SysAllocStringLen": 2,
|
|
"SysReAllocString": 2,
|
|
"SysReAllocStringLen": 3,
|
|
"SysFreeString": 1,
|
|
"SysStringLen": 1,
|
|
"SysStringByteLen": 1,
|
|
"VariantInit": 1,
|
|
"VariantClear": 1,
|
|
"VariantCopy": 2,
|
|
"VariantChangeType": 4,
|
|
"VariantChangeTypeEx": 5,
|
|
"SafeArrayCreate": 3,
|
|
"SafeArrayCreateEx": 4,
|
|
"SafeArrayDestroy": 1,
|
|
"SafeArrayGetDim": 1,
|
|
"SafeArrayGetElement": 3,
|
|
"SafeArrayPutElement": 3,
|
|
"SafeArrayAccessData": 2,
|
|
"SafeArrayUnaccessData": 1,
|
|
"SafeArrayGetLBound": 3,
|
|
"SafeArrayGetUBound": 3,
|
|
|
|
// --- comctl32.dll ---
|
|
"InitCommonControls": 0,
|
|
"InitCommonControlsEx": 1,
|
|
"ImageList_Create": 5,
|
|
"ImageList_Destroy": 1,
|
|
"ImageList_Add": 3,
|
|
"ImageList_AddMasked": 3,
|
|
"ImageList_Draw": 6,
|
|
"ImageList_DrawEx": 10,
|
|
"ImageList_GetImageCount": 1,
|
|
"ImageList_GetImageInfo": 3,
|
|
"ImageList_SetBkColor": 2,
|
|
"ImageList_GetBkColor": 1,
|
|
"ImageList_ReplaceIcon": 3,
|
|
"PropertySheetA": 1,
|
|
"PropertySheetW": 1,
|
|
"CreateStatusWindowA": 4,
|
|
"CreateStatusWindowW": 4,
|
|
|
|
// --- comdlg32.dll ---
|
|
"GetOpenFileNameA": 1,
|
|
"GetOpenFileNameW": 1,
|
|
"GetSaveFileNameA": 1,
|
|
"GetSaveFileNameW": 1,
|
|
"ChooseColorA": 1,
|
|
"ChooseColorW": 1,
|
|
"ChooseFontA": 1,
|
|
"ChooseFontW": 1,
|
|
"FindTextA": 1,
|
|
"FindTextW": 1,
|
|
"ReplaceTextA": 1,
|
|
"ReplaceTextW": 1,
|
|
"PrintDlgA": 1,
|
|
"PrintDlgW": 1,
|
|
"PageSetupDlgA": 1,
|
|
"PageSetupDlgW": 1,
|
|
"CommDlgExtendedError": 0,
|
|
|
|
// --- ws2_32.dll ---
|
|
"WSAStartup": 2,
|
|
"WSACleanup": 0,
|
|
"WSAGetLastError": 0,
|
|
"WSASetLastError": 1,
|
|
"socket": 3,
|
|
"closesocket": 1,
|
|
"bind": 3,
|
|
"listen": 2,
|
|
"accept": 3,
|
|
"connect": 3,
|
|
"send": 4,
|
|
"recv": 4,
|
|
"sendto": 6,
|
|
"recvfrom": 6,
|
|
"select": 5,
|
|
"setsockopt": 5,
|
|
"getsockopt": 5,
|
|
"getaddrinfo": 4,
|
|
"freeaddrinfo": 1,
|
|
"getnameinfo": 7,
|
|
"ioctlsocket": 3,
|
|
"shutdown": 2,
|
|
"gethostname": 2,
|
|
"gethostbyname": 1,
|
|
"getpeername": 3,
|
|
"getsockname": 3,
|
|
"inet_addr": 1,
|
|
"inet_ntoa": 1,
|
|
"htons": 1,
|
|
"htonl": 1,
|
|
"ntohs": 1,
|
|
"ntohl": 1,
|
|
|
|
// --- shlwapi.dll ---
|
|
"PathFileExistsA": 1,
|
|
"PathFileExistsW": 1,
|
|
"PathFindExtensionA": 1,
|
|
"PathFindExtensionW": 1,
|
|
"PathFindFileNameA": 1,
|
|
"PathFindFileNameW": 1,
|
|
"PathRemoveFileSpecA": 1,
|
|
"PathRemoveFileSpecW": 1,
|
|
"PathAppendA": 2,
|
|
"PathAppendW": 2,
|
|
"PathCombineA": 3,
|
|
"PathCombineW": 3,
|
|
"PathIsRelativeA": 1,
|
|
"PathIsRelativeW": 1,
|
|
"PathIsDirectoryA": 1,
|
|
"PathIsDirectoryW": 1,
|
|
"PathStripPathA": 1,
|
|
"PathStripPathW": 1,
|
|
"PathRemoveExtensionA": 1,
|
|
"PathRemoveExtensionW": 1,
|
|
"PathAddExtensionA": 2,
|
|
"PathAddExtensionW": 2,
|
|
"PathRenameExtensionA": 2,
|
|
"PathRenameExtensionW": 2,
|
|
"StrStrA": 2,
|
|
"StrStrW": 2,
|
|
"StrStrIA": 2,
|
|
"StrStrIW": 2,
|
|
"StrCmpNA": 3,
|
|
"StrCmpNW": 3,
|
|
"StrCmpNIA": 3,
|
|
"StrCmpNIW": 3,
|
|
"StrChrA": 2,
|
|
"StrChrW": 2,
|
|
"StrRChrA": 3,
|
|
"StrRChrW": 3,
|
|
"StrDupA": 1,
|
|
"StrDupW": 1,
|
|
"SHDeleteKeyA": 2,
|
|
"SHDeleteKeyW": 2,
|
|
"SHDeleteValueA": 3,
|
|
"SHDeleteValueW": 3,
|
|
"SHGetValueA": 6,
|
|
"SHGetValueW": 6,
|
|
"SHSetValueA": 6,
|
|
"SHSetValueW": 6,
|
|
|
|
// --- version.dll ---
|
|
"GetFileVersionInfoA": 4,
|
|
"GetFileVersionInfoW": 4,
|
|
"GetFileVersionInfoSizeA": 2,
|
|
"GetFileVersionInfoSizeW": 2,
|
|
"VerQueryValueA": 4,
|
|
"VerQueryValueW": 4,
|
|
|
|
// --- crypt32.dll ---
|
|
"CertOpenStore": 5,
|
|
"CertCloseStore": 2,
|
|
"CertOpenSystemStoreA": 2,
|
|
"CertOpenSystemStoreW": 2,
|
|
"CertFindCertificateInStore": 6,
|
|
"CertFreeCertificateContext": 1,
|
|
"CertDuplicateCertificateContext": 1,
|
|
"CertGetCertificateChain": 8,
|
|
"CertFreeCertificateChain": 1,
|
|
"CryptDecodeObjectEx": 7,
|
|
"CryptEncodeObjectEx": 7,
|
|
"CertGetNameStringA": 5,
|
|
"CertGetNameStringW": 5,
|
|
"PFXImportCertStore": 3,
|
|
|
|
// --- winspool.drv ---
|
|
"OpenPrinterA": 3,
|
|
"OpenPrinterW": 3,
|
|
"ClosePrinter": 1,
|
|
"EnumPrintersA": 6,
|
|
"EnumPrintersW": 6,
|
|
"GetDefaultPrinterA": 2,
|
|
"GetDefaultPrinterW": 2,
|
|
"StartDocPrinterA": 3,
|
|
"StartDocPrinterW": 3,
|
|
"EndDocPrinter": 1,
|
|
"StartPagePrinter": 1,
|
|
"EndPagePrinter": 1,
|
|
"WritePrinter": 4,
|
|
"DocumentPropertiesA": 6,
|
|
"DocumentPropertiesW": 6,
|
|
"DeviceCapabilitiesA": 5,
|
|
"DeviceCapabilitiesW": 5,
|
|
|
|
// --- imm32.dll ---
|
|
"ImmGetContext": 1,
|
|
"ImmReleaseContext": 2,
|
|
"ImmGetCompositionStringA": 4,
|
|
"ImmGetCompositionStringW": 4,
|
|
"ImmSetCompositionStringA": 5,
|
|
"ImmSetCompositionStringW": 5,
|
|
"ImmGetOpenStatus": 1,
|
|
"ImmSetOpenStatus": 2,
|
|
"ImmGetConversionStatus": 3,
|
|
"ImmSetConversionStatus": 3,
|
|
"ImmIsIME": 1,
|
|
"ImmNotifyIME": 4,
|
|
"ImmGetDefaultIMEWnd": 1,
|
|
"ImmAssociateContext": 2,
|
|
"ImmAssociateContextEx": 3,
|
|
"ImmInstallIMEA": 2,
|
|
"ImmInstallIMEW": 2,
|
|
|
|
// --- msimg32.dll (same as gdi32 exports) ---
|
|
"GradientFill": 6,
|
|
|
|
// --- uxtheme.dll ---
|
|
"OpenThemeData": 2,
|
|
"CloseThemeData": 1,
|
|
"DrawThemeBackground": 6,
|
|
"DrawThemeText": 8,
|
|
"GetThemeBackgroundContentRect": 6,
|
|
"GetThemePartSize": 6,
|
|
"IsThemeActive": 0,
|
|
"IsAppThemed": 0,
|
|
"SetWindowTheme": 3,
|
|
"GetThemeColor": 5,
|
|
"GetThemeFont": 6,
|
|
"GetThemeMetric": 5,
|
|
"GetThemeSysColor": 2,
|
|
"GetThemeSysFont": 3,
|
|
"EnableThemeDialogTexture": 2,
|
|
"IsThemeDialogTextureEnabled": 1,
|
|
|
|
// --- wininet.dll ---
|
|
"InternetOpenA": 5,
|
|
"InternetOpenW": 5,
|
|
"InternetConnectA": 8,
|
|
"InternetConnectW": 8,
|
|
"InternetCloseHandle": 1,
|
|
"InternetOpenUrlA": 6,
|
|
"InternetOpenUrlW": 6,
|
|
"InternetReadFile": 4,
|
|
"InternetWriteFile": 4,
|
|
"HttpOpenRequestA": 8,
|
|
"HttpOpenRequestW": 8,
|
|
"HttpSendRequestA": 5,
|
|
"HttpSendRequestW": 5,
|
|
"HttpQueryInfoA": 5,
|
|
"HttpQueryInfoW": 5,
|
|
"InternetQueryDataAvailable": 2,
|
|
"InternetSetOptionA": 4,
|
|
"InternetSetOptionW": 4,
|
|
"InternetQueryOptionA": 4,
|
|
"InternetQueryOptionW": 4,
|
|
|
|
// --- winhttp.dll ---
|
|
"WinHttpOpen": 5,
|
|
"WinHttpConnect": 4,
|
|
"WinHttpOpenRequest": 7,
|
|
"WinHttpAddRequestHeaders": 4,
|
|
"WinHttpSendRequest": 7,
|
|
"WinHttpReceiveResponse": 2,
|
|
"WinHttpQueryHeaders": 6,
|
|
"WinHttpReadData": 4,
|
|
"WinHttpQueryDataAvailable": 2,
|
|
"WinHttpSetOption": 4,
|
|
"WinHttpQueryOption": 4,
|
|
"WinHttpCloseHandle": 1,
|
|
"WinHttpCrackUrl": 4,
|
|
"WinHttpSetCredentials": 6,
|
|
|
|
// --- psapi.dll ---
|
|
"EnumProcesses": 3,
|
|
"EnumProcessModules": 4,
|
|
"GetModuleBaseNameA": 4,
|
|
"GetModuleBaseNameW": 4,
|
|
"GetModuleFileNameExA": 4,
|
|
"GetModuleFileNameExW": 4,
|
|
"GetProcessMemoryInfo": 3,
|
|
"EnumProcessModulesEx": 5,
|
|
|
|
// --- gdi32.dll extras (needed for 32-bit installer DLLs) ---
|
|
"SelectPalette": 3,
|
|
"RealizePalette": 1,
|
|
"CreatePalette": 1,
|
|
"CreateScalableFontResourceA": 4,
|
|
"CreateScalableFontResourceW": 4,
|
|
"DeleteMetaFile": 1,
|
|
"SetMetaFileBitsEx": 2,
|
|
"GetTextExtentPointA": 4,
|
|
"GetTextExtentPointW": 4,
|
|
|
|
// --- user32.dll extras ---
|
|
"DrawFocusRect": 2,
|
|
"GetDialogBaseUnits": 0,
|
|
"InvalidateRgn": 3,
|
|
|
|
// --- user32.dll DDE/misc (needed for 32-bit installer DLLs) ---
|
|
"DdeInitializeA": 4,
|
|
"DdeInitializeW": 4,
|
|
"DdeUninitialize": 1,
|
|
"DdeCreateStringHandleA": 3,
|
|
"DdeCreateStringHandleW": 3,
|
|
"DdeFreeStringHandle": 2,
|
|
"DdeQueryStringA": 5,
|
|
"DdeQueryStringW": 5,
|
|
"DdeNameService": 4,
|
|
"DdeConnect": 4,
|
|
"DdeDisconnect": 1,
|
|
"DdeClientTransaction": 8,
|
|
"DdeGetData": 4,
|
|
"DdeCreateDataHandle": 7,
|
|
"DdeFreeDataHandle": 1,
|
|
"DdePostAdvise": 3,
|
|
"WinHelpA": 4,
|
|
"WinHelpW": 4,
|
|
"OemToCharA": 2,
|
|
"OemToCharW": 2,
|
|
"CharToOemA": 2,
|
|
"CharToOemW": 2,
|
|
"DrawIcon": 4,
|
|
|
|
// --- advapi32.dll extras ---
|
|
"RegSetValueA": 5,
|
|
"RegSetValueW": 5,
|
|
"RegQueryValueA": 4,
|
|
"RegQueryValueW": 4,
|
|
"AccessCheck": 8,
|
|
"RevertToSelf": 0,
|
|
"ImpersonateSelf": 1,
|
|
"GetFileSecurityA": 5,
|
|
"GetFileSecurityW": 5,
|
|
|
|
// --- version.dll extras ---
|
|
"VerInstallFileA": 8,
|
|
"VerInstallFileW": 8,
|
|
"VerFindFileA": 7,
|
|
"VerFindFileW": 7,
|
|
|
|
// --- mpr.dll ---
|
|
"WNetGetConnectionA": 3,
|
|
"WNetGetConnectionW": 3,
|
|
|
|
// --- winmm.dll extras ---
|
|
"sndPlaySoundA": 2,
|
|
"sndPlaySoundW": 2,
|
|
"midiOutGetNumDevs": 0,
|
|
}
|
|
|
|
// RegisterAutoStubHandler registers a handler for a specific function in a
|
|
// synthetic DLL by looking up its trap ID.
|
|
func (d *Dispatcher) RegisterAutoStubHandler(synth *SynthPE, funcName string, h TrapHandler) {
|
|
if synth == nil || h == nil {
|
|
return
|
|
}
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
moduleKey := strings.ToLower(synth.Name)
|
|
moduleHandlers := d.handlersByModule[moduleKey]
|
|
if moduleHandlers == nil {
|
|
moduleHandlers = make(map[string]TrapHandler)
|
|
d.handlersByModule[moduleKey] = moduleHandlers
|
|
}
|
|
moduleHandlers[funcName] = h
|
|
addr, ok := synth.Exports[funcName]
|
|
if !ok {
|
|
return
|
|
}
|
|
id, ok := synth.StubIDs[addr]
|
|
if !ok {
|
|
return
|
|
}
|
|
d.handlers[id] = h
|
|
}
|
|
|
|
// RegisterSemanticHandler registers a concrete handler together with the ABI
|
|
// and executable contract identity used by compatibility audits.
|
|
func (d *Dispatcher) RegisterSemanticHandler(synth *SynthPE, funcName string, semantic SemanticHandler) {
|
|
if synth == nil || semantic.Handler == nil || semantic.ImplementationID == "" || semantic.Signature == "" || semantic.ContractCaseID == "" {
|
|
return
|
|
}
|
|
addr, ok := synth.Exports[funcName]
|
|
if !ok {
|
|
return
|
|
}
|
|
id, ok := synth.StubIDs[addr]
|
|
if !ok {
|
|
return
|
|
}
|
|
d.RegisterAutoStubHandler(synth, funcName, semantic.Handler)
|
|
d.mu.Lock()
|
|
if d.semanticByModule == nil {
|
|
d.semanticByModule = make(map[string]map[string]SemanticHandler)
|
|
}
|
|
module := strings.ToLower(synth.Name)
|
|
if d.semanticByModule[module] == nil {
|
|
d.semanticByModule[module] = make(map[string]SemanticHandler)
|
|
}
|
|
if strings.HasPrefix(strings.ToLower(strings.TrimSpace(semantic.Signature)), "cdecl") {
|
|
d.cdeclIDs[id] = true
|
|
}
|
|
d.semanticByModule[module][funcName] = semantic
|
|
d.mu.Unlock()
|
|
}
|
|
|
|
// SemanticHandlers returns a copy of the concrete semantic registration map.
|
|
func (d *Dispatcher) SemanticHandlers() map[string]map[string]SemanticHandler {
|
|
d.mu.RLock()
|
|
defer d.mu.RUnlock()
|
|
result := make(map[string]map[string]SemanticHandler, len(d.semanticByModule))
|
|
for module, handlers := range d.semanticByModule {
|
|
result[module] = make(map[string]SemanticHandler, len(handlers))
|
|
for name, handler := range handlers {
|
|
result[module][name] = handler
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// WrapAutoStubHandler replaces an existing synthetic DLL handler while
|
|
// preserving access to the handler registered before it.
|
|
func (d *Dispatcher) WrapAutoStubHandler(synth *SynthPE, funcName string, wrap func(TrapHandler) TrapHandler) bool {
|
|
if d == nil || synth == nil || wrap == nil {
|
|
return false
|
|
}
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
addr, ok := synth.Exports[funcName]
|
|
if !ok {
|
|
return false
|
|
}
|
|
id, ok := synth.StubIDs[addr]
|
|
if !ok {
|
|
return false
|
|
}
|
|
previous, ok := d.handlers[id]
|
|
if !ok {
|
|
return false
|
|
}
|
|
handler := wrap(previous)
|
|
if handler == nil {
|
|
return false
|
|
}
|
|
d.handlers[id] = handler
|
|
if d.handlersByModule == nil {
|
|
d.handlersByModule = make(map[string]map[string]TrapHandler)
|
|
}
|
|
moduleKey := strings.ToLower(synth.Name)
|
|
moduleHandlers := d.handlersByModule[moduleKey]
|
|
if moduleHandlers == nil {
|
|
moduleHandlers = make(map[string]TrapHandler)
|
|
d.handlersByModule[moduleKey] = moduleHandlers
|
|
}
|
|
moduleHandlers[funcName] = handler
|
|
return true
|
|
}
|
|
|
|
// RegisterDynamicHandler adds a new export to a synthetic DLL and registers
|
|
// a handler for it. Used for functions that apps look up via GetProcAddress
|
|
// but aren't in the DLL's original import table.
|
|
func (d *Dispatcher) RegisterDynamicHandler(mem *mmu.MMU, synth *SynthPE, funcName string, id uint32, h TrapHandler) {
|
|
if synth == nil || h == nil {
|
|
return
|
|
}
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
d.registerDynamicHandlerLocked(mem, synth, funcName, id, h)
|
|
}
|
|
|
|
func (d *Dispatcher) dynamicIDInUseLocked(id uint32) bool {
|
|
if _, ok := d.handlers[id]; ok {
|
|
return true
|
|
}
|
|
return d.names[id] != ""
|
|
}
|
|
|
|
func (d *Dispatcher) registerDynamicHandlerLocked(mem *mmu.MMU, synth *SynthPE, funcName string, id uint32, h TrapHandler) {
|
|
if d.handlersByModule == nil {
|
|
d.handlersByModule = make(map[string]map[string]TrapHandler)
|
|
}
|
|
moduleKey := strings.ToLower(synth.Name)
|
|
moduleHandlers := d.handlersByModule[moduleKey]
|
|
if moduleHandlers == nil {
|
|
moduleHandlers = make(map[string]TrapHandler)
|
|
d.handlersByModule[moduleKey] = moduleHandlers
|
|
}
|
|
moduleHandlers[funcName] = h
|
|
// Check if already exists as a regular export
|
|
if addr, ok := synth.Exports[funcName]; ok {
|
|
if existingID, ok := synth.StubIDs[addr]; ok {
|
|
d.handlers[existingID] = h
|
|
return
|
|
}
|
|
}
|
|
if d.dynamicIDInUseLocked(id) {
|
|
if d.nextDynamicID > id {
|
|
id = d.nextDynamicID
|
|
}
|
|
for d.dynamicIDInUseLocked(id) {
|
|
id++
|
|
}
|
|
}
|
|
allocID := synth.AddDynamicExport(mem, funcName, id)
|
|
if allocID == 0 {
|
|
return
|
|
}
|
|
d.handlers[id] = h
|
|
d.names[id] = synth.Name + "!" + funcName
|
|
if d.cdeclModules[moduleKey] {
|
|
if d.cdeclIDs == nil {
|
|
d.cdeclIDs = make(map[uint32]bool)
|
|
}
|
|
d.cdeclIDs[id] = true
|
|
}
|
|
if id >= d.nextDynamicID {
|
|
d.nextDynamicID = id + 1
|
|
}
|
|
}
|
|
|
|
func (d *Dispatcher) EnsureDynamicExport(mem *mmu.MMU, synth *SynthPE, funcName string, idFloor uint32) (uint64, uint32, bool) {
|
|
if synth == nil {
|
|
return 0, idFloor, false
|
|
}
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
if addr := synth.Exports[funcName]; addr != 0 {
|
|
if d.nextDynamicID > idFloor {
|
|
idFloor = d.nextDynamicID
|
|
}
|
|
return addr, idFloor, false
|
|
}
|
|
id := idFloor
|
|
if d.nextDynamicID > id {
|
|
id = d.nextDynamicID
|
|
}
|
|
for d.dynamicIDInUseLocked(id) {
|
|
id++
|
|
}
|
|
if synth.AddDynamicExport(mem, funcName, id) == 0 {
|
|
return synth.Exports[funcName], idFloor, false
|
|
}
|
|
d.names[id] = synth.Name + "!" + funcName
|
|
if d.cdeclModules[strings.ToLower(synth.Name)] {
|
|
if d.cdeclIDs == nil {
|
|
d.cdeclIDs = make(map[uint32]bool)
|
|
}
|
|
d.cdeclIDs[id] = true
|
|
}
|
|
if nArgs, ok := win32ArgCounts[funcName]; ok {
|
|
d.stdcallArgs[id] = nArgs
|
|
}
|
|
d.nextDynamicID = id + 1
|
|
return synth.Exports[funcName], d.nextDynamicID, true
|
|
}
|
|
|
|
func (d *Dispatcher) SetSynthOrdinal(synth *SynthPE, ordinal uint16, addr uint64) {
|
|
if synth == nil || addr == 0 {
|
|
return
|
|
}
|
|
d.mu.Lock()
|
|
synth.ExportOrds[ordinal] = addr
|
|
d.mu.Unlock()
|
|
}
|
|
|
|
// MaterializeNamedHandler adds a synthetic export for a handler that was
|
|
// registered by name before the application requested it with GetProcAddress.
|
|
func (d *Dispatcher) MaterializeNamedHandler(mem *mmu.MMU, synth *SynthPE, funcName string, idFloor uint32) (uint64, uint32) {
|
|
if synth == nil {
|
|
return 0, idFloor
|
|
}
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
if addr, ok := synth.Exports[funcName]; ok {
|
|
if d.nextDynamicID > idFloor {
|
|
idFloor = d.nextDynamicID
|
|
}
|
|
return addr, idFloor
|
|
}
|
|
h, ok := d.handlersByModule[strings.ToLower(synth.Name)][funcName]
|
|
if !ok {
|
|
return 0, idFloor
|
|
}
|
|
id := idFloor
|
|
if d.nextDynamicID > id {
|
|
id = d.nextDynamicID
|
|
}
|
|
for d.dynamicIDInUseLocked(id) {
|
|
id++
|
|
}
|
|
d.registerDynamicHandlerLocked(mem, synth, funcName, id, h)
|
|
d.applyWin32ArgCountsLocked(synth)
|
|
return synth.Exports[funcName], d.nextDynamicID
|
|
}
|
|
|
|
func (d *Dispatcher) handlerSnapshot(id uint32) (TrapHandler, string, bool, int, bool) {
|
|
d.mu.RLock()
|
|
defer d.mu.RUnlock()
|
|
handler := d.handlers[id]
|
|
name := d.names[id]
|
|
cdecl := d.cdeclIDs[id]
|
|
argCount, hasArgCount := d.stdcallArgs[id]
|
|
return handler, name, cdecl, argCount, hasArgCount
|
|
}
|
|
|
|
// Handle is the vmcall trap entry point, called by the CPU emulator.
|
|
func (d *Dispatcher) Handle(cpu arch.CPU) {
|
|
callCtx := *d.ctx
|
|
callCtx.CPU = cpu
|
|
ctx := &callCtx
|
|
if setter, ok := any(ctx).(interface{ SetCurrentCPU(arch.CPU) }); ok {
|
|
setter.SetCurrentCPU(cpu)
|
|
}
|
|
syscallID := uint32(cpu.SyscallNum()) // EAX contains the syscall ID
|
|
is32 := ctx.State != nil && ctx.State.Is32
|
|
handler, handlerName, isCdecl, explicitArgCount, hasExplicitArgCount := d.handlerSnapshot(syscallID)
|
|
|
|
// Debug: log any stub called from within the zero VirtualAlloc region
|
|
if is32 {
|
|
sp := cpu.GetSP()
|
|
if retAddr, err := ctx.Mem.Read32(sp); err == nil {
|
|
if retAddr >= 0x10400000 && retAddr <= 0x10BFFFFF {
|
|
name := handlerName
|
|
if name == "" {
|
|
name = fmt.Sprintf("unknown_0x%04X", syscallID)
|
|
}
|
|
ravelog.Logf("[zero-region] stub called from zero-region ret=0x%x: %s\n", retAddr, name)
|
|
}
|
|
}
|
|
}
|
|
|
|
if ctx.TraceSyscall {
|
|
name := handlerName
|
|
if name == "" {
|
|
name = fmt.Sprintf("unknown_0x%04X", syscallID)
|
|
}
|
|
impl := ""
|
|
if handler == nil {
|
|
impl = " [UNIMPL]"
|
|
}
|
|
ravelog.Logf("[syscall] %s (id=0x%04X)%s\n", name, syscallID, impl)
|
|
}
|
|
|
|
if handler == nil {
|
|
name := handlerName
|
|
if name == "" {
|
|
name = fmt.Sprintf("unknown_0x%04X", syscallID)
|
|
}
|
|
// Log missing API to file for tracking
|
|
if syscallID >= AutoSynthIDBase {
|
|
// This is an auto-synth stub - log the missing API
|
|
missingFile, err := os.OpenFile("missing_api.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err == nil {
|
|
fmt.Fprintf(missingFile, "[MISSING] auto-synth!%s (id=0x%04X)\n", name, syscallID)
|
|
missingFile.Close()
|
|
}
|
|
}
|
|
ravelog.Logf("[ntapi] UNIMPLEMENTED: %s (id=0x%04X)\n", name, syscallID)
|
|
// For auto-synth user-mode DLL stubs, return 0 (NULL/FALSE).
|
|
// For NT syscalls, return STATUS_NOT_IMPLEMENTED.
|
|
if syscallID >= AutoSynthIDBase {
|
|
cpu.SetSyscallReturn(0)
|
|
} else {
|
|
cpu.SetSyscallReturn(0xC0000002)
|
|
}
|
|
// PE32 stdcall cleanup for unimplemented stubs:
|
|
// use the arg count table if available.
|
|
if is32 && !isCdecl {
|
|
if hasExplicitArgCount && explicitArgCount > 0 {
|
|
d.doStdcallCleanup(cpu, explicitArgCount)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
if ctx.Trace {
|
|
name := handlerName
|
|
sp := cpu.GetSP()
|
|
if name != "__wine_dbg_header" || sp < 0x7C000000 {
|
|
if is32 {
|
|
retAddr, _ := ctx.Mem.Read32(sp)
|
|
ravelog.Logf("[trace] -> %s (id=0x%04X) sp=0x%x ret=0x%x\n", name, syscallID, sp, retAddr)
|
|
} else {
|
|
retAddr, _ := ctx.Mem.Read64(sp)
|
|
ravelog.Logf("[trace] -> %s (id=0x%04X) sp=0x%x ret=0x%x\n", name, syscallID, sp, retAddr)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Detect the PE32 win32k path: gdi32/user32 syscall stubs dispatch via
|
|
// `call [KUSER_SHARED_DATA->SystemCall]`, landing in our vmcall trampoline.
|
|
// That `call` pushed one extra return address, so stack args sit 4 bytes
|
|
// higher, and stack cleanup is done by the stub's own `ret N` (not by us).
|
|
viaTramp := false
|
|
if is32 && ctx.State != nil && ctx.State.Win32kTrampoline != 0 {
|
|
pc := cpu.GetPC()
|
|
t := ctx.State.Win32kTrampoline
|
|
if pc >= t && pc <= t+4 {
|
|
viaTramp = true
|
|
}
|
|
}
|
|
if viaTramp {
|
|
ctx.i386ArgExtra = 4
|
|
} else {
|
|
ctx.i386ArgExtra = 0
|
|
}
|
|
|
|
ctx.ReturnOverridden = false
|
|
ctx.PCRedirected = false
|
|
ctx.maxArgIdx = -1
|
|
|
|
// Win32 API/COM stub calls (cdecl/stdcall) must preserve the caller's
|
|
// callee-saved registers (EBX, ESI, EDI, EBP). Our Go handlers only set
|
|
// the return value (EAX) and must not leak register changes back to the
|
|
// guest, otherwise games that keep a live value in EBX across an API call
|
|
// (e.g. kkrieger's message pump, which needs EBX==0) break. Snapshot them
|
|
// before the handler and restore after, unless the handler deliberately
|
|
// redirects control flow (sync WndProc dispatch, callbacks) where the
|
|
// register state must flow into the redirected target.
|
|
var savedCallee [4]uint64
|
|
rrCallee, hasRR := cpu.(RegisterReader)
|
|
if is32 && hasRR {
|
|
savedCallee = [4]uint64{rrCallee.ReadReg(3), rrCallee.ReadReg(5), rrCallee.ReadReg(6), rrCallee.ReadReg(7)} // EBX,EBP,ESI,EDI
|
|
}
|
|
|
|
if d.hprof != nil {
|
|
d.hprof.record(syscallID, cpu.GetPC())
|
|
}
|
|
status := handler(ctx)
|
|
if !ctx.ReturnOverridden {
|
|
cpu.SetSyscallReturn(uint64(status))
|
|
}
|
|
|
|
if is32 && hasRR && !ctx.PCRedirected {
|
|
if rw, ok := cpu.(RegisterWriter); ok {
|
|
regs := [4]int{3, 5, 6, 7}
|
|
for i, r := range regs {
|
|
if rrCallee.ReadReg(r) != savedCallee[i] {
|
|
rw.WriteReg(r, savedCallee[i])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// PE32 stdcall cleanup: the callee must pop arguments from the stack.
|
|
// Skip if the handler redirected PC (sync WndProc dispatch manages its own stack).
|
|
// Also skip for the SystemCall-trampoline path: the trampoline's `ret`
|
|
// returns to the real gdi32/user32 stub, whose own `ret N` pops the args.
|
|
if is32 && viaTramp {
|
|
// Emulate the trampoline's `ret` (RET 0): pop the return address back
|
|
// into the real gdi32/user32 stub and set PC, preserving EAX. The stub's
|
|
// own `ret N` then pops the service args. (Like synth stubs, the CPU
|
|
// expects the dispatcher to manage the return PC, so a plain skip would
|
|
// not execute the trampoline's `ret`.)
|
|
d.doStdcallCleanup(cpu, 0)
|
|
} else if is32 && !isCdecl && !ctx.PCRedirected {
|
|
// Prefer explicit arg count (from Win32 API table) over heuristic.
|
|
nArgs := ctx.maxArgIdx + 1
|
|
if hasExplicitArgCount {
|
|
nArgs = explicitArgCount
|
|
}
|
|
if d.traceStdcall {
|
|
sp := cpu.GetSP()
|
|
ret, _ := d.ctx.Mem.Read32(sp)
|
|
// Only the game's own code range, to find the call that misaligns
|
|
// the stack right before the message pump reads a bad EBX.
|
|
if ret >= 0x800000 && ret < 0x820000 {
|
|
ebx := uint64(0)
|
|
if rr, ok := cpu.(RegisterReader); ok {
|
|
ebx = rr.ReadReg(3)
|
|
}
|
|
ravelog.Logf("[stdcall] %s nArgs=%d sp=0x%x ret=0x%x ebx=0x%x\n",
|
|
handlerName, nArgs, sp, ret, ebx)
|
|
}
|
|
}
|
|
if nArgs > 0 {
|
|
d.doStdcallCleanup(cpu, nArgs)
|
|
}
|
|
} else if is32 {
|
|
name := handlerName
|
|
if strings.Contains(name, "com!") || strings.Contains(name, "d3d!") {
|
|
ravelog.Logf("[stdcall-SKIP] %s cdecl=%v pcRedir=%v is32=%v\n", name, isCdecl, ctx.PCRedirected, is32)
|
|
}
|
|
if d.traceStdcall {
|
|
sp := cpu.GetSP()
|
|
ret, _ := d.ctx.Mem.Read32(sp)
|
|
if ret >= 0x800000 && ret < 0x820000 {
|
|
ravelog.Logf("[stdcall-nocleanup] %s id=0x%x cdecl=%v pcRedir=%v maxArgIdx=%d sp=0x%x ret=0x%x\n",
|
|
name, syscallID, isCdecl, ctx.PCRedirected, ctx.maxArgIdx, sp, ret)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// doStdcallCleanup emulates RET n for PE32 stdcall: pop the return address,
|
|
// skip all arguments, and set RIP directly - avoiding any stack writes that
|
|
// could clobber output buffers sitting just above the argument area.
|
|
func (d *Dispatcher) doStdcallCleanup(cpu arch.CPU, nArgs int) {
|
|
sp := cpu.GetSP()
|
|
retAddr, _ := d.ctx.Mem.Read32(sp)
|
|
newSP := sp + 4 + uint64(nArgs)*4
|
|
cpu.SetSP(newSP)
|
|
cpu.SetPC(uint64(retAddr))
|
|
}
|
|
|
|
// register adds a handler for a given syscall ID.
|
|
func (d *Dispatcher) register(id uint32, name string, h TrapHandler) {
|
|
d.handlers[id] = h
|
|
d.names[id] = name
|
|
}
|
|
|
|
// RegisterHandler registers a handler for a specific syscall ID.
|
|
func (d *Dispatcher) RegisterHandler(id uint32, name string, h TrapHandler) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
d.handlers[id] = h
|
|
d.names[id] = name
|
|
}
|
|
|
|
// registerNtapiHandlers registers all NTAPI syscall handlers.
|
|
func (d *Dispatcher) registerNtapiHandlers() {
|
|
for i, name := range ntapiExports {
|
|
id := ntapiIDBase + uint32(i)
|
|
d.names[id] = name
|
|
}
|
|
|
|
// File I/O
|
|
d.register(idOf("NtCallbackReturn"), "NtCallbackReturn", d.handleNtCallbackReturn)
|
|
d.register(idOf("NtCreateFile"), "NtCreateFile", handleNtCreateFile)
|
|
d.register(idOf("NtOpenFile"), "NtOpenFile", handleNtOpenFile)
|
|
d.register(idOf("NtReadFile"), "NtReadFile", handleNtReadFile)
|
|
d.register(idOf("NtWriteFile"), "NtWriteFile", handleNtWriteFile)
|
|
d.register(idOf("NtClose"), "NtClose", handleNtClose)
|
|
d.register(idOf("NtQueryInformationFile"), "NtQueryInformationFile", handleNtQueryInformationFile)
|
|
d.register(idOf("NtSetInformationFile"), "NtSetInformationFile", handleNtSetInformationFile)
|
|
d.register(idOf("NtQueryDirectoryFile"), "NtQueryDirectoryFile", handleNtQueryDirectoryFile)
|
|
d.register(idOf("NtQueryVolumeInformationFile"), "NtQueryVolumeInformationFile", handleNtQueryVolumeInformationFile)
|
|
d.register(idOf("NtDeleteFile"), "NtDeleteFile", handleNtDeleteFile)
|
|
d.register(idOf("NtFlushBuffersFile"), "NtFlushBuffersFile", handleNtFlushBuffersFile)
|
|
d.register(idOf("NtDeviceIoControlFile"), "NtDeviceIoControlFile", handleNtDeviceIoControlFile)
|
|
d.register(idOf("NtCreateSection"), "NtCreateSection", handleNtCreateSection)
|
|
d.register(idOf("NtMapViewOfSection"), "NtMapViewOfSection", handleNtMapViewOfSection)
|
|
d.register(idOf("NtUnmapViewOfSection"), "NtUnmapViewOfSection", handleNtUnmapViewOfSection)
|
|
|
|
// Registry
|
|
d.register(idOf("NtOpenKey"), "NtOpenKey", handleNtOpenKey)
|
|
d.register(idOf("NtOpenKeyEx"), "NtOpenKeyEx", handleNtOpenKeyEx)
|
|
d.register(idOf("NtCreateKey"), "NtCreateKey", handleNtCreateKey)
|
|
d.register(idOf("NtQueryValueKey"), "NtQueryValueKey", handleNtQueryValueKey)
|
|
d.register(idOf("NtSetValueKey"), "NtSetValueKey", handleNtSetValueKey)
|
|
d.register(idOf("NtDeleteKey"), "NtDeleteKey", handleNtDeleteKey)
|
|
d.register(idOf("NtDeleteValueKey"), "NtDeleteValueKey", handleNtDeleteValueKey)
|
|
d.register(idOf("NtEnumerateKey"), "NtEnumerateKey", handleNtEnumerateKey)
|
|
d.register(idOf("NtEnumerateValueKey"), "NtEnumerateValueKey", handleNtEnumerateValueKey)
|
|
d.register(idOf("NtQueryKey"), "NtQueryKey", handleNtQueryKey)
|
|
|
|
// Process / Thread
|
|
d.register(idOf("NtQueryInformationProcess"), "NtQueryInformationProcess", handleNtQueryInformationProcess)
|
|
d.register(idOf("NtQueryInformationThread"), "NtQueryInformationThread", handleNtQueryInformationThread)
|
|
d.register(idOf("NtQuerySystemInformation"), "NtQuerySystemInformation", handleNtQuerySystemInformation)
|
|
d.register(idOf("NtTerminateProcess"), "NtTerminateProcess", handleNtTerminateProcess)
|
|
|
|
// Virtual Memory
|
|
d.register(idOf("NtAllocateVirtualMemory"), "NtAllocateVirtualMemory", handleNtAllocateVirtualMemory)
|
|
d.register(idOf("NtFreeVirtualMemory"), "NtFreeVirtualMemory", handleNtFreeVirtualMemory)
|
|
d.register(idOf("NtProtectVirtualMemory"), "NtProtectVirtualMemory", handleNtProtectVirtualMemory)
|
|
d.register(idOf("NtQueryVirtualMemory"), "NtQueryVirtualMemory", handleNtQueryVirtualMemory)
|
|
|
|
// Synchronization
|
|
d.register(idOf("NtCreateEvent"), "NtCreateEvent", handleNtCreateEvent)
|
|
d.register(idOf("NtSetEvent"), "NtSetEvent", handleNtSetEvent)
|
|
d.register(idOf("NtResetEvent"), "NtResetEvent", handleNtResetEvent)
|
|
d.register(idOf("NtClearEvent"), "NtClearEvent", handleNtClearEvent)
|
|
d.register(idOf("NtPulseEvent"), "NtPulseEvent", handleNtPulseEvent)
|
|
d.register(idOf("NtQueryEvent"), "NtQueryEvent", handleNtQueryEvent)
|
|
d.register(idOf("NtQueryMutant"), "NtQueryMutant", handleNtQueryMutant)
|
|
d.register(idOf("NtQuerySemaphore"), "NtQuerySemaphore", handleNtQuerySemaphore)
|
|
d.register(idOf("NtQueryTimerResolution"), "NtQueryTimerResolution", handleNtQueryTimerResolution)
|
|
d.register(idOf("NtWaitForSingleObject"), "NtWaitForSingleObject", handleNtWaitForSingleObject)
|
|
d.register(idOf("NtWaitForMultipleObjects"), "NtWaitForMultipleObjects", handleNtWaitForMultipleObjects)
|
|
d.register(idOf("NtCreateMutant"), "NtCreateMutant", handleNtCreateMutant)
|
|
d.register(idOf("NtReleaseMutant"), "NtReleaseMutant", handleNtReleaseMutant)
|
|
d.register(idOf("NtDelayExecution"), "NtDelayExecution", handleNtDelayExecution)
|
|
d.register(idOf("NtYieldExecution"), "NtYieldExecution", handleNtYieldExecution)
|
|
d.register(idOf("NtQueryPerformanceCounter"), "NtQueryPerformanceCounter", handleNtQueryPerformanceCounter)
|
|
d.register(idOf("NtQuerySystemTime"), "NtQuerySystemTime", handleNtQuerySystemTime)
|
|
// Keyed Events (used by SRW locks, condition variables, critical section fallback)
|
|
d.register(idOf("NtCreateKeyedEvent"), "NtCreateKeyedEvent", handleNtCreateKeyedEvent)
|
|
d.register(idOf("NtOpenKeyedEvent"), "NtOpenKeyedEvent", handleNtOpenKeyedEvent)
|
|
d.register(idOf("NtWaitForKeyedEvent"), "NtWaitForKeyedEvent", handleNtWaitForKeyedEvent)
|
|
d.register(idOf("NtReleaseKeyedEvent"), "NtReleaseKeyedEvent", handleNtReleaseKeyedEvent)
|
|
d.register(idOf("ZwCreateKeyedEvent"), "ZwCreateKeyedEvent", handleNtCreateKeyedEvent)
|
|
d.register(idOf("ZwWaitForKeyedEvent"), "ZwWaitForKeyedEvent", handleNtWaitForKeyedEvent)
|
|
d.register(idOf("ZwReleaseKeyedEvent"), "ZwReleaseKeyedEvent", handleNtReleaseKeyedEvent)
|
|
// UUID allocation
|
|
d.register(idOf("NtAllocateUuids"), "NtAllocateUuids", handleNtAllocateUuids)
|
|
d.register(idOf("ZwAllocateUuids"), "ZwAllocateUuids", handleNtAllocateUuids)
|
|
|
|
// Critical Sections (implemented in handler, not real kernel calls)
|
|
d.register(idOf("RtlInitializeCriticalSection"), "RtlInitializeCriticalSection", handleRtlInitCritSec)
|
|
d.register(idOf("RtlInitializeCriticalSectionAndSpinCount"), "RtlInitializeCriticalSectionAndSpinCount", handleRtlInitCritSec)
|
|
d.register(idOf("RtlInitializeCriticalSectionEx"), "RtlInitializeCriticalSectionEx", handleRtlInitCritSec)
|
|
d.register(idOf("RtlEnterCriticalSection"), "RtlEnterCriticalSection", handleRtlEnterCritSec)
|
|
d.register(idOf("RtlLeaveCriticalSection"), "RtlLeaveCriticalSection", handleRtlLeaveCritSec)
|
|
d.register(idOf("RtlDeleteCriticalSection"), "RtlDeleteCriticalSection", handleRtlDeleteCritSec)
|
|
d.register(idOf("RtlTryEnterCriticalSection"), "RtlTryEnterCriticalSection", handleRtlTryEnterCritSec)
|
|
|
|
// SRW Locks
|
|
d.register(idOf("RtlInitializeSRWLock"), "RtlInitializeSRWLock", handleRtlInitSRWLock)
|
|
d.register(idOf("RtlAcquireSRWLockExclusive"), "RtlAcquireSRWLockExclusive", handleRtlAcquireSRWExcl)
|
|
d.register(idOf("RtlReleaseSRWLockExclusive"), "RtlReleaseSRWLockExclusive", handleRtlReleaseSRWExcl)
|
|
d.register(idOf("RtlAcquireSRWLockShared"), "RtlAcquireSRWLockShared", handleRtlAcquireSRWShared)
|
|
d.register(idOf("RtlReleaseSRWLockShared"), "RtlReleaseSRWLockShared", handleRtlReleaseSRWShared)
|
|
d.register(idOf("RtlTryAcquireSRWLockExclusive"), "RtlTryAcquireSRWLockExclusive", handleRtlTryAcquireSRWExcl)
|
|
d.register(idOf("RtlTryAcquireSRWLockShared"), "RtlTryAcquireSRWLockShared", handleRtlTryAcquireSRWShared)
|
|
|
|
// Condition Variables
|
|
d.register(idOf("RtlInitializeConditionVariable"), "RtlInitializeConditionVariable", handleRtlInitCondVar)
|
|
d.register(idOf("RtlWakeConditionVariable"), "RtlWakeConditionVariable", handleRtlWakeCondVar)
|
|
d.register(idOf("RtlWakeAllConditionVariable"), "RtlWakeAllConditionVariable", handleRtlWakeAllCondVar)
|
|
|
|
// Heap
|
|
d.register(idOf("RtlAllocateHeap"), "RtlAllocateHeap", handleRtlAllocateHeap)
|
|
d.register(idOf("RtlFreeHeap"), "RtlFreeHeap", handleRtlFreeHeap)
|
|
d.register(idOf("RtlReAllocateHeap"), "RtlReAllocateHeap", handleRtlReAllocateHeap)
|
|
d.register(idOf("RtlSizeHeap"), "RtlSizeHeap", handleRtlSizeHeap)
|
|
d.register(idOf("RtlCreateHeap"), "RtlCreateHeap", handleRtlCreateHeap)
|
|
d.register(idOf("RtlDestroyHeap"), "RtlDestroyHeap", handleRtlDestroyHeap)
|
|
|
|
// String utilities
|
|
d.register(idOf("RtlInitUnicodeString"), "RtlInitUnicodeString", handleRtlInitUnicodeString)
|
|
d.register(idOf("RtlFreeUnicodeString"), "RtlFreeUnicodeString", handleNoop)
|
|
|
|
// Misc
|
|
d.register(idOf("RtlGetVersion"), "RtlGetVersion", handleRtlGetVersion)
|
|
d.register(idOf("RtlNtStatusToDosError"), "RtlNtStatusToDosError", handleRtlNtStatusToDosError)
|
|
d.register(idOf("RtlSetLastWin32Error"), "RtlSetLastWin32Error", handleRtlSetLastWin32Error)
|
|
d.register(idOf("RtlGetLastWin32Error"), "RtlGetLastWin32Error", handleRtlGetLastWin32Error)
|
|
d.register(idOf("NtDuplicateObject"), "NtDuplicateObject", handleNtDuplicateObject)
|
|
d.register(idOf("NtQueryObject"), "NtQueryObject", handleNtQueryObject)
|
|
|
|
// DLL loading
|
|
d.register(idOf("LdrGetDllHandle"), "LdrGetDllHandle", handleLdrGetDllHandle)
|
|
d.register(idOf("LdrGetProcedureAddress"), "LdrGetProcedureAddress", handleLdrGetProcedureAddress)
|
|
d.register(idOf("LdrLoadDll"), "LdrLoadDll", handleLdrLoadDll)
|
|
d.register(idOf("LdrGetDllHandleEx"), "LdrGetDllHandleEx", handleLdrGetDllHandleEx)
|
|
d.register(idOf("LdrAddRefDll"), "LdrAddRefDll", handleLdrAddRefDll)
|
|
d.register(idOf("LdrGetDllPath"), "LdrGetDllPath", handleLdrGetDllPath)
|
|
d.register(idOf("LdrGetDllFullName"), "LdrGetDllFullName", handleLdrGetDllFullName)
|
|
|
|
// PEB/TEB
|
|
d.register(idOf("RtlGetCurrentPeb"), "RtlGetCurrentPeb", handleRtlGetCurrentPeb)
|
|
d.register(idOf("RtlAcquirePebLock"), "RtlAcquirePebLock", handleRtlAcquirePebLock)
|
|
d.register(idOf("RtlReleasePebLock"), "RtlReleasePebLock", handleRtlReleasePebLock)
|
|
|
|
// String conversions
|
|
d.register(idOf("RtlInitAnsiString"), "RtlInitAnsiString", handleRtlInitAnsiString)
|
|
d.register(idOf("RtlInitUnicodeStringEx"), "RtlInitUnicodeStringEx", handleRtlInitUnicodeStringEx)
|
|
d.register(idOf("RtlMultiByteToUnicodeN"), "RtlMultiByteToUnicodeN", handleRtlMultiByteToUnicodeN)
|
|
d.register(idOf("RtlMultiByteToUnicodeSize"), "RtlMultiByteToUnicodeSize", handleRtlMultiByteToUnicodeSize)
|
|
d.register(idOf("RtlUnicodeToMultiByteN"), "RtlUnicodeToMultiByteN", handleRtlUnicodeToMultiByteN)
|
|
d.register(idOf("RtlUnicodeToMultiByteSize"), "RtlUnicodeToMultiByteSize", handleRtlUnicodeToMultiByteSize)
|
|
d.register(idOf("RtlAnsiStringToUnicodeString"), "RtlAnsiStringToUnicodeString", handleRtlAnsiStringToUnicodeString)
|
|
d.register(idOf("RtlUnicodeStringToAnsiString"), "RtlUnicodeStringToAnsiString", handleRtlUnicodeStringToAnsiString)
|
|
d.register(idOf("RtlUnicodeStringToAnsiSize"), "RtlUnicodeStringToAnsiSize", handleNoop)
|
|
d.register(idOf("RtlFreeAnsiString"), "RtlFreeAnsiString", handleRtlFreeAnsiString)
|
|
d.register(idOf("RtlCreateUnicodeString"), "RtlCreateUnicodeString", handleRtlCreateUnicodeString)
|
|
d.register(idOf("RtlCompareUnicodeStrings"), "RtlCompareUnicodeStrings", handleRtlCompareUnicodeStrings)
|
|
d.register(idOf("RtlUTF8ToUnicodeN"), "RtlUTF8ToUnicodeN", handleRtlUTF8ToUnicodeN)
|
|
d.register(idOf("RtlUnicodeToUTF8N"), "RtlUnicodeToUTF8N", handleRtlUnicodeToUTF8N)
|
|
d.register(idOf("RtlIsNormalizedString"), "RtlIsNormalizedString", handleRtlIsNormalizedString)
|
|
d.register(idOf("RtlNormalizeString"), "RtlNormalizeString", handleRtlNormalizeString)
|
|
d.register(idOf("RtlDuplicateUnicodeString"), "RtlDuplicateUnicodeString", handleNoop)
|
|
|
|
// PE image helpers
|
|
d.register(idOf("RtlImageNtHeader"), "RtlImageNtHeader", handleRtlImageNtHeader)
|
|
d.register(idOf("RtlImageDirectoryEntryToData"), "RtlImageDirectoryEntryToData", handleRtlImageDirectoryEntryToData)
|
|
|
|
// System info
|
|
d.register(idOf("RtlGetNativeSystemInformation"), "RtlGetNativeSystemInformation", handleRtlGetNativeSystemInformation)
|
|
d.register(idOf("NtGetTickCount"), "NtGetTickCount", handleNtGetTickCount)
|
|
d.register(idOf("NtFlushInstructionCache"), "NtFlushInstructionCache", handleNtFlushInstructionCache)
|
|
d.register(idOf("NtQueryDefaultLocale"), "NtQueryDefaultLocale", handleNtQueryDefaultLocale)
|
|
d.register(idOf("NtQueryDefaultUILanguage"), "NtQueryDefaultUILanguage", handleNtQueryDefaultUILanguage)
|
|
d.register(idOf("NtQueryInstallUILanguage"), "NtQueryInstallUILanguage", handleNtQueryInstallUILanguage)
|
|
|
|
// Thread context
|
|
d.register(idOf("NtGetContextThread"), "NtGetContextThread", handleNtGetContextThread)
|
|
d.register(idOf("NtSetContextThread"), "NtSetContextThread", handleNtSetContextThread)
|
|
d.register(idOf("NtResumeThread"), "NtResumeThread", handleNtResumeThread)
|
|
d.register(idOf("NtSuspendThread"), "NtSuspendThread", handleNtSuspendThread)
|
|
|
|
// Token / Security
|
|
d.register(idOf("NtOpenProcessToken"), "NtOpenProcessToken", handleNtOpenProcessToken)
|
|
d.register(idOf("NtOpenThreadToken"), "NtOpenThreadToken", handleNtOpenThreadToken)
|
|
d.register(idOf("NtQueryInformationToken"), "NtQueryInformationToken", handleNtQueryInformationToken)
|
|
d.register(idOf("NtSetInformationToken"), "NtSetInformationToken", handleNtSetInformationToken)
|
|
d.register(idOf("NtAdjustPrivilegesToken"), "NtAdjustPrivilegesToken", handleNtAdjustPrivilegesToken)
|
|
d.register(idOf("NtPrivilegeCheck"), "NtPrivilegeCheck", handleNtPrivilegeCheck)
|
|
d.register(idOf("NtAllocateLocallyUniqueId"), "NtAllocateLocallyUniqueId", handleNtAllocateLocallyUniqueId)
|
|
d.register(idOf("NtSetSecurityObject"), "NtSetSecurityObject", handleNtSetSecurityObject)
|
|
d.register(idOf("NtQuerySecurityObject"), "NtQuerySecurityObject", handleNtQuerySecurityObject)
|
|
|
|
// Heap extended
|
|
d.register(idOf("RtlGetProcessHeaps"), "RtlGetProcessHeaps", handleRtlGetProcessHeaps)
|
|
d.register(idOf("RtlLockHeap"), "RtlLockHeap", handleRtlLockHeap)
|
|
d.register(idOf("RtlUnlockHeap"), "RtlUnlockHeap", handleRtlUnlockHeap)
|
|
d.register(idOf("RtlValidateHeap"), "RtlValidateHeap", handleRtlValidateHeap)
|
|
d.register(idOf("RtlSetHeapInformation"), "RtlSetHeapInformation", handleRtlSetHeapInformation)
|
|
d.register(idOf("RtlQueryHeapInformation"), "RtlQueryHeapInformation", handleRtlQueryHeapInformation)
|
|
d.register(idOf("RtlGetUserInfoHeap"), "RtlGetUserInfoHeap", handleRtlGetUserInfoHeap)
|
|
d.register(idOf("RtlSetUserValueHeap"), "RtlSetUserValueHeap", handleRtlSetUserValueHeap)
|
|
d.register(idOf("RtlCompactHeap"), "RtlCompactHeap", handleRtlCompactHeap)
|
|
d.register(idOf("RtlWalkHeap"), "RtlWalkHeap", handleRtlWalkHeap)
|
|
|
|
// Code page / locale
|
|
d.register(idOf("RtlInitCodePageTable"), "RtlInitCodePageTable", handleRtlInitCodePageTable)
|
|
d.register(idOf("RtlInitNlsTables"), "RtlInitNlsTables", handleRtlInitNlsTables)
|
|
d.register(idOf("RtlResetRtlTranslations"), "RtlResetRtlTranslations", handleRtlResetRtlTranslations)
|
|
|
|
// FLS
|
|
d.register(idOf("RtlFlsAlloc"), "RtlFlsAlloc", handleRtlFlsAlloc)
|
|
d.register(idOf("RtlFlsFree"), "RtlFlsFree", handleRtlFlsFree)
|
|
d.register(idOf("RtlFlsGetValue"), "RtlFlsGetValue", handleRtlFlsGetValue)
|
|
d.register(idOf("RtlFlsSetValue"), "RtlFlsSetValue", handleRtlFlsSetValue)
|
|
d.register(idOf("RtlProcessFlsData"), "RtlProcessFlsData", handleRtlProcessFlsData)
|
|
|
|
// Process/Thread lifecycle
|
|
d.register(idOf("RtlExitUserProcess"), "RtlExitUserProcess", handleRtlExitUserProcess)
|
|
d.register(idOf("RtlExitUserThread"), "RtlExitUserThread", handleRtlExitUserThread)
|
|
d.register(idOf("RtlNormalizeProcessParams"), "RtlNormalizeProcessParams", handleRtlNormalizeProcessParams)
|
|
d.register(idOf("RtlIsProcessorFeaturePresent"), "RtlIsProcessorFeaturePresent", handleRtlIsProcessorFeaturePresent)
|
|
d.register(idOf("NtOpenProcess"), "NtOpenProcess", handleNtOpenProcess)
|
|
d.register(idOf("NtSetInformationProcess"), "NtSetInformationProcess", handleNtSetInformationProcess)
|
|
d.register(idOf("NtSetInformationThread"), "NtSetInformationThread", handleNtSetInformationThread)
|
|
d.register(idOf("NtOpenThread"), "NtOpenThread", handleNtOpenThread)
|
|
d.register(idOf("NtAlertThread"), "NtAlertThread", handleNtAlertThread)
|
|
d.register(idOf("NtAlertResumeThread"), "NtAlertResumeThread", handleNtAlertResumeThread)
|
|
d.register(idOf("NtTestAlert"), "NtTestAlert", handleNtTestAlert)
|
|
|
|
// Exception handling
|
|
d.register(idOf("RtlCaptureContext"), "RtlCaptureContext", handleRtlCaptureContext)
|
|
d.register(idOf("RtlUnwind"), "RtlUnwind", handleRtlUnwind)
|
|
d.register(idOf("RtlUnwindEx"), "RtlUnwindEx", handleRtlUnwindEx)
|
|
d.register(idOf("RtlLookupFunctionEntry"), "RtlLookupFunctionEntry", handleRtlLookupFunctionEntry)
|
|
d.register(idOf("RtlRestoreContext"), "RtlRestoreContext", handleRtlRestoreContext)
|
|
d.register(idOf("RtlRaiseException"), "RtlRaiseException", handleRtlRaiseException)
|
|
d.register(idOf("RtlRaiseStatus"), "RtlRaiseStatus", handleRtlRaiseStatus)
|
|
d.register(idOf("RtlAddVectoredExceptionHandler"), "RtlAddVectoredExceptionHandler", handleRtlAddVectoredExceptionHandler)
|
|
d.register(idOf("RtlRemoveVectoredExceptionHandler"), "RtlRemoveVectoredExceptionHandler", handleRtlRemoveVectoredExceptionHandler)
|
|
d.register(idOf("RtlPcToFileHeader"), "RtlPcToFileHeader", handleRtlPcToFileHeader)
|
|
d.register(idOf("RtlGetEnabledExtendedFeatures"), "RtlGetEnabledExtendedFeatures", handleRtlGetEnabledExtendedFeatures)
|
|
d.register(idOf("RtlSetUnhandledExceptionFilter"), "RtlSetUnhandledExceptionFilter", handleRtlSetUnhandledExceptionFilter)
|
|
|
|
// Synchronization extended
|
|
d.register(idOf("NtCreateSemaphore"), "NtCreateSemaphore", handleNtCreateSemaphore)
|
|
d.register(idOf("NtReleaseSemaphore"), "NtReleaseSemaphore", handleNtReleaseSemaphore)
|
|
d.register(idOf("NtOpenEvent"), "NtOpenEvent", handleNtOpenEvent)
|
|
d.register(idOf("NtOpenMutant"), "NtOpenMutant", handleNtOpenMutant)
|
|
d.register(idOf("NtOpenSemaphore"), "NtOpenSemaphore", handleNtOpenSemaphore)
|
|
d.register(idOf("NtOpenSection"), "NtOpenSection", handleNtOpenSection)
|
|
d.register(idOf("NtCreateTimer"), "NtCreateTimer", handleNtCreateTimer)
|
|
d.register(idOf("NtSetTimer"), "NtSetTimer", handleNtSetTimer)
|
|
d.register(idOf("NtCancelTimer"), "NtCancelTimer", handleNtCancelTimer)
|
|
d.register(idOf("NtQueryTimer"), "NtQueryTimer", handleNtQueryTimer)
|
|
d.register(idOf("RtlSleepConditionVariableCS"), "RtlSleepConditionVariableCS", handleRtlSleepConditionVariableCS)
|
|
d.register(idOf("RtlSleepConditionVariableSRW"), "RtlSleepConditionVariableSRW", handleRtlSleepConditionVariableSRW)
|
|
d.register(idOf("RtlWaitOnAddress"), "RtlWaitOnAddress", handleRtlWaitOnAddress)
|
|
|
|
// I/O Completion
|
|
d.register(idOf("NtCreateIoCompletion"), "NtCreateIoCompletion", handleNtCreateIoCompletion)
|
|
d.register(idOf("NtSetIoCompletion"), "NtSetIoCompletion", handleNtSetIoCompletion)
|
|
d.register(idOf("NtRemoveIoCompletion"), "NtRemoveIoCompletion", handleNtRemoveIoCompletion)
|
|
d.register(idOf("NtRemoveIoCompletionEx"), "NtRemoveIoCompletionEx", handleNtRemoveIoCompletionEx)
|
|
d.register(idOf("NtCancelIoFile"), "NtCancelIoFile", handleNtCancelIoFile)
|
|
d.register(idOf("NtCancelIoFileEx"), "NtCancelIoFileEx", handleNtCancelIoFileEx)
|
|
|
|
// Object manager
|
|
d.register(idOf("NtCreateDirectoryObject"), "NtCreateDirectoryObject", handleNtCreateDirectoryObject)
|
|
d.register(idOf("NtOpenDirectoryObject"), "NtOpenDirectoryObject", handleNtOpenDirectoryObject)
|
|
d.register(idOf("NtCreateSymbolicLinkObject"), "NtCreateSymbolicLinkObject", handleNtCreateSymbolicLinkObject)
|
|
d.register(idOf("NtOpenSymbolicLinkObject"), "NtOpenSymbolicLinkObject", handleNtOpenSymbolicLinkObject)
|
|
d.register(idOf("NtQuerySymbolicLinkObject"), "NtQuerySymbolicLinkObject", handleNtQuerySymbolicLinkObject)
|
|
d.register(idOf("NtSetInformationObject"), "NtSetInformationObject", handleNtSetInformationObject)
|
|
d.register(idOf("NtCompareObjects"), "NtCompareObjects", handleNtCompareObjects)
|
|
|
|
// File I/O extended
|
|
d.register(idOf("NtQueryAttributesFile"), "NtQueryAttributesFile", handleNtQueryAttributesFile)
|
|
d.register(idOf("NtQueryFullAttributesFile"), "NtQueryFullAttributesFile", handleNtQueryFullAttributesFile)
|
|
d.register(idOf("NtLockFile"), "NtLockFile", handleNtLockFile)
|
|
d.register(idOf("NtUnlockFile"), "NtUnlockFile", handleNtUnlockFile)
|
|
d.register(idOf("NtCreateMailslotFile"), "NtCreateMailslotFile", handleNtCreateMailslotFile)
|
|
d.register(idOf("NtCreateNamedPipeFile"), "NtCreateNamedPipeFile", handleNtCreateNamedPipeFile)
|
|
d.register(idOf("NtFsControlFile"), "NtFsControlFile", handleNtFsControlFile)
|
|
d.register(idOf("NtNotifyChangeKey"), "NtNotifyChangeKey", handleNtNotifyChangeKey)
|
|
d.register(idOf("NtNotifyChangeDirectoryFile"), "NtNotifyChangeDirectoryFile", handleNtNotifyChangeDirectoryFile)
|
|
|
|
// Path functions
|
|
d.register(idOf("RtlDosPathNameToNtPathName_U"), "RtlDosPathNameToNtPathName_U", handleRtlDosPathNameToNtPathName_U)
|
|
d.register(idOf("RtlDosPathNameToNtPathName_U_WithStatus"), "RtlDosPathNameToNtPathName_U_WithStatus", handleRtlDosPathNameToNtPathName_U_WithStatus)
|
|
d.register(idOf("RtlGetCurrentDirectory_U"), "RtlGetCurrentDirectory_U", handleRtlGetCurrentDirectory_U)
|
|
d.register(idOf("RtlSetCurrentDirectory_U"), "RtlSetCurrentDirectory_U", handleRtlSetCurrentDirectory_U)
|
|
d.register(idOf("RtlGetFullPathName_U"), "RtlGetFullPathName_U", handleRtlGetFullPathName_U)
|
|
d.register(idOf("RtlGetNtGlobalFlags"), "RtlGetNtGlobalFlags", handleRtlGetNtGlobalFlags)
|
|
d.register(idOf("RtlGetNtProductType"), "RtlGetNtProductType", handleRtlGetNtProductType)
|
|
d.register(idOf("RtlDetermineDosPathNameType_U"), "RtlDetermineDosPathNameType_U", handleRtlDetermineDosPathNameType_U)
|
|
|
|
// Bitmap
|
|
d.register(idOf("RtlInitializeBitMap"), "RtlInitializeBitMap", handleRtlInitializeBitMap)
|
|
d.register(idOf("RtlSetBits"), "RtlSetBits", handleRtlSetBits)
|
|
d.register(idOf("RtlClearBits"), "RtlClearBits", handleRtlClearBits)
|
|
d.register(idOf("RtlAreBitsSet"), "RtlAreBitsSet", handleRtlAreBitsSet)
|
|
d.register(idOf("RtlAreBitsClear"), "RtlAreBitsClear", handleRtlAreBitsClear)
|
|
|
|
// Error mode
|
|
d.register(idOf("RtlGetThreadErrorMode"), "RtlGetThreadErrorMode", handleRtlGetThreadErrorMode)
|
|
d.register(idOf("RtlSetThreadErrorMode"), "RtlSetThreadErrorMode", handleRtlSetThreadErrorMode)
|
|
|
|
// Environment
|
|
d.register(idOf("RtlCreateEnvironment"), "RtlCreateEnvironment", handleRtlCreateEnvironment)
|
|
d.register(idOf("RtlDestroyEnvironment"), "RtlDestroyEnvironment", handleRtlDestroyEnvironment)
|
|
d.register(idOf("RtlSetEnvironmentVariable"), "RtlSetEnvironmentVariable", handleRtlSetEnvironmentVariable)
|
|
d.register(idOf("RtlQueryEnvironmentVariable_U"), "RtlQueryEnvironmentVariable_U", handleRtlQueryEnvironmentVariable_U)
|
|
d.register(idOf("RtlExpandEnvironmentStrings_U"), "RtlExpandEnvironmentStrings_U", handleRtlExpandEnvironmentStrings_U)
|
|
d.register(idOf("RtlCreateProcessParametersEx"), "RtlCreateProcessParametersEx", handleRtlCreateProcessParametersEx)
|
|
d.register(idOf("RtlDestroyProcessParameters"), "RtlDestroyProcessParameters", handleRtlDestroyProcessParameters)
|
|
|
|
// RunOnce
|
|
d.register(idOf("RtlRunOnceBeginInitialize"), "RtlRunOnceBeginInitialize", handleRtlRunOnceBeginInitialize)
|
|
d.register(idOf("RtlRunOnceComplete"), "RtlRunOnceComplete", handleRtlRunOnceComplete)
|
|
d.register(idOf("RtlRunOnceExecuteOnce"), "RtlRunOnceExecuteOnce", handleRtlRunOnceExecuteOnce)
|
|
|
|
// Misc system
|
|
d.register(idOf("NtPowerInformation"), "NtPowerInformation", handleNtPowerInformation)
|
|
d.register(idOf("NtQueueApcThread"), "NtQueueApcThread", handleNtQueueApcThread)
|
|
d.register(idOf("NtGetNlsSectionPtr"), "NtGetNlsSectionPtr", handleNtGetNlsSectionPtr)
|
|
d.register(idOf("NtSetSystemInformation"), "NtSetSystemInformation", handleNtSetSystemInformation)
|
|
d.register(idOf("NtSetSystemTime"), "NtSetSystemTime", handleNtSetSystemTime)
|
|
|
|
// Security descriptors / SIDs
|
|
d.register(idOf("RtlCreateSecurityDescriptor"), "RtlCreateSecurityDescriptor", handleRtlCreateSecurityDescriptor)
|
|
d.register(idOf("RtlSetDaclSecurityDescriptor"), "RtlSetDaclSecurityDescriptor", handleRtlSetDaclSecurityDescriptor)
|
|
d.register(idOf("RtlGetDaclSecurityDescriptor"), "RtlGetDaclSecurityDescriptor", handleRtlGetDaclSecurityDescriptor)
|
|
d.register(idOf("RtlCreateAcl"), "RtlCreateAcl", handleRtlCreateAcl)
|
|
d.register(idOf("RtlAddAccessAllowedAce"), "RtlAddAccessAllowedAce", handleRtlAddAccessAllowedAce)
|
|
d.register(idOf("RtlAddAccessAllowedAceEx"), "RtlAddAccessAllowedAceEx", handleRtlAddAccessAllowedAceEx)
|
|
d.register(idOf("RtlAllocateAndInitializeSid"), "RtlAllocateAndInitializeSid", handleRtlAllocateAndInitializeSid)
|
|
d.register(idOf("RtlFreeSid"), "RtlFreeSid", handleRtlFreeSid)
|
|
d.register(idOf("RtlCopySid"), "RtlCopySid", handleRtlCopySid)
|
|
d.register(idOf("RtlEqualSid"), "RtlEqualSid", handleRtlEqualSid)
|
|
d.register(idOf("RtlLengthSid"), "RtlLengthSid", handleRtlLengthSid)
|
|
d.register(idOf("RtlInitializeSid"), "RtlInitializeSid", handleRtlInitializeSid)
|
|
d.register(idOf("RtlValidSid"), "RtlValidSid", handleRtlValidSid)
|
|
d.register(idOf("RtlSubAuthorityCountSid"), "RtlSubAuthorityCountSid", handleRtlSubAuthorityCountSid)
|
|
d.register(idOf("RtlSubAuthoritySid"), "RtlSubAuthoritySid", handleRtlSubAuthoritySid)
|
|
d.register(idOf("RtlIdentifierAuthoritySid"), "RtlIdentifierAuthoritySid", handleRtlIdentifierAuthoritySid)
|
|
|
|
// Activation context
|
|
d.register(idOf("RtlActivateActivationContext"), "RtlActivateActivationContext", handleRtlActivateActivationContext)
|
|
d.register(idOf("RtlDeactivateActivationContext"), "RtlDeactivateActivationContext", handleRtlDeactivateActivationContext)
|
|
d.register(idOf("RtlGetActiveActivationContext"), "RtlGetActiveActivationContext", handleRtlGetActiveActivationContext)
|
|
d.register(idOf("RtlAddRefActivationContext"), "RtlAddRefActivationContext", handleRtlAddRefActivationContext)
|
|
d.register(idOf("RtlReleaseActivationContext"), "RtlReleaseActivationContext", handleRtlReleaseActivationContext)
|
|
d.register(idOf("RtlCreateActivationContext"), "RtlCreateActivationContext", handleRtlCreateActivationContext)
|
|
d.register(idOf("RtlQueryActivationContextApplicationSettings"), "RtlQueryActivationContextApplicationSettings", handleRtlQueryActivationContextApplicationSettings)
|
|
d.register(idOf("RtlFindActivationContextSectionString"), "RtlFindActivationContextSectionString", handleRtlFindActivationContextSectionString)
|
|
d.register(idOf("RtlFindActivationContextSectionGuid"), "RtlFindActivationContextSectionGuid", handleRtlFindActivationContextSectionGuid)
|
|
d.register(idOf("RtlZombifyActivationContext"), "RtlZombifyActivationContext", handleRtlZombifyActivationContext)
|
|
d.register(idOf("RtlFreeActivationContextStack"), "RtlFreeActivationContextStack", handleRtlFreeActivationContextStack)
|
|
d.register(idOf("RtlQueryInformationActivationContext"), "RtlQueryInformationActivationContext", handleRtlQueryInformationActivationContext)
|
|
|
|
// Thread pool
|
|
d.register(idOf("RtlQueueWorkItem"), "RtlQueueWorkItem", handleRtlQueueWorkItem)
|
|
d.register(idOf("RtlCreateTimer"), "RtlCreateTimer", handleRtlCreateTimer)
|
|
d.register(idOf("RtlDeleteTimer"), "RtlDeleteTimer", handleRtlDeleteTimer)
|
|
d.register(idOf("RtlUpdateTimer"), "RtlUpdateTimer", handleRtlUpdateTimer)
|
|
d.register(idOf("RtlCreateTimerQueue"), "RtlCreateTimerQueue", handleRtlCreateTimerQueue)
|
|
d.register(idOf("RtlDeleteTimerQueueEx"), "RtlDeleteTimerQueueEx", handleRtlDeleteTimerQueueEx)
|
|
d.register(idOf("RtlRegisterWait"), "RtlRegisterWait", handleRtlRegisterWait)
|
|
d.register(idOf("RtlDeregisterWait"), "RtlDeregisterWait", handleRtlDeregisterWait)
|
|
d.register(idOf("RtlDeregisterWaitEx"), "RtlDeregisterWaitEx", handleRtlDeregisterWaitEx)
|
|
d.register(idOf("RtlSetIoCompletionCallback"), "RtlSetIoCompletionCallback", handleRtlSetIoCompletionCallback)
|
|
|
|
// GUID / message
|
|
d.register(idOf("RtlGUIDFromString"), "RtlGUIDFromString", handleRtlGUIDFromString)
|
|
d.register(idOf("RtlFindMessage"), "RtlFindMessage", handleRtlFindMessage)
|
|
d.register(idOf("RtlFormatMessage"), "RtlFormatMessage", handleRtlFormatMessage)
|
|
|
|
// Locale / language preferences
|
|
d.register(idOf("RtlGetLocaleFileMappingAddress"), "RtlGetLocaleFileMappingAddress", handleRtlGetLocaleFileMappingAddress)
|
|
d.register(idOf("RtlGetProductInfo"), "RtlGetProductInfo", handleRtlGetProductInfo)
|
|
d.register(idOf("RtlGetSystemPreferredUILanguages"), "RtlGetSystemPreferredUILanguages", handleRtlGetSystemPreferredUILanguages)
|
|
d.register(idOf("RtlGetUserPreferredUILanguages"), "RtlGetUserPreferredUILanguages", handleRtlGetUserPreferredUILanguages)
|
|
d.register(idOf("RtlGetProcessPreferredUILanguages"), "RtlGetProcessPreferredUILanguages", handleRtlGetProcessPreferredUILanguages)
|
|
d.register(idOf("RtlGetThreadPreferredUILanguages"), "RtlGetThreadPreferredUILanguages", handleRtlGetThreadPreferredUILanguages)
|
|
d.register(idOf("RtlGetSystemTimePrecise"), "RtlGetSystemTimePrecise", handleRtlGetSystemTimePrecise)
|
|
d.register(idOf("RtlTimeFieldsToTime"), "RtlTimeFieldsToTime", handleRtlTimeFieldsToTime)
|
|
d.register(idOf("RtlTimeToTimeFields"), "RtlTimeToTimeFields", handleRtlTimeToTimeFields)
|
|
d.register(idOf("RtlQueryUnbiasedInterruptTime"), "RtlQueryUnbiasedInterruptTime", handleRtlQueryUnbiasedInterruptTime)
|
|
|
|
// WoW64
|
|
d.register(idOf("RtlWow64GetProcessMachines"), "RtlWow64GetProcessMachines", handleRtlWow64GetProcessMachines)
|
|
d.register(idOf("RtlWow64EnableFsRedirection"), "RtlWow64EnableFsRedirection", handleRtlWow64EnableFsRedirection)
|
|
d.register(idOf("RtlWow64EnableFsRedirectionEx"), "RtlWow64EnableFsRedirectionEx", handleRtlWow64EnableFsRedirectionEx)
|
|
|
|
// Wine-specific stubs
|
|
d.register(idOf("wine_get_version"), "wine_get_version", handleWineGetVersion)
|
|
d.register(idOf("wine_server_call"), "wine_server_call", handleWineServerCall)
|
|
d.register(idOf("__wine_dbg_get_channel_flags"), "__wine_dbg_get_channel_flags", handleWineDbgGetChannelFlags)
|
|
d.register(idOf("__wine_dbg_header"), "__wine_dbg_header", handleWineDbgHeader)
|
|
d.register(idOf("__wine_dbg_output"), "__wine_dbg_output", handleWineDbgOutput)
|
|
d.register(idOf("__wine_dbg_strdup"), "__wine_dbg_strdup", handleWineDbgStrdup)
|
|
d.register(idOf("wine_nt_to_unix_file_name"), "wine_nt_to_unix_file_name", handleWineNtToUnixFileName)
|
|
d.register(idOf("wine_unix_to_nt_file_name"), "wine_unix_to_nt_file_name", handleWineUnixToNtFileName)
|
|
|
|
// ETW stubs
|
|
d.register(idOf("EtwEventRegister"), "EtwEventRegister", handleEtwEventRegister)
|
|
d.register(idOf("EtwEventUnregister"), "EtwEventUnregister", handleEtwEventUnregister)
|
|
d.register(idOf("EtwEventWrite"), "EtwEventWrite", handleEtwEventWrite)
|
|
d.register(idOf("EtwEventEnabled"), "EtwEventEnabled", handleEtwEventEnabled)
|
|
|
|
// Debug
|
|
d.register(idOf("DbgBreakPoint"), "DbgBreakPoint", handleDbgBreakPoint)
|
|
|
|
// C-runtime stubs in ntdll
|
|
d.register(idOf("_vsnprintf"), "_vsnprintf", handleVsnprintf)
|
|
d.register(idOf("_vsnwprintf"), "_vsnwprintf", handleVsnwprintf)
|
|
|
|
// CRT handlers for functions too complex for x64 inline patches
|
|
d.register(idOf("strtol"), "strtol", handleStrtol)
|
|
d.register(idOf("wcstol"), "wcstol", handleWcstol)
|
|
d.register(idOf("wcstoul"), "wcstoul", handleWcstoul)
|
|
d.register(idOf("_strnicmp"), "_strnicmp", handleStrnicmp)
|
|
d.register(idOf("_wcsicmp"), "_wcsicmp", handleWcsicmp)
|
|
d.register(idOf("_wcsnicmp"), "_wcsnicmp", handleWcsnicmp)
|
|
d.register(idOf("isalpha"), "isalpha", handleIsalpha)
|
|
d.register(idOf("islower"), "islower", handleIslower)
|
|
d.register(idOf("isxdigit"), "isxdigit", handleIsxdigit)
|
|
d.register(idOf("strpbrk"), "strpbrk", handleStrpbrk)
|
|
d.register(idOf("wcspbrk"), "wcspbrk", handleWcspbrk)
|
|
d.register(idOf("wcscspn"), "wcscspn", handleWcscspn)
|
|
d.register(idOf("wcsspn"), "wcsspn", handleWcsspn)
|
|
d.register(idOf("wcsstr"), "wcsstr", handleWcsstr)
|
|
d.register(idOf("LdrDisableThreadCalloutsForDll"), "LdrDisableThreadCalloutsForDll", handleLdrDisableThreadCalloutsForDll)
|
|
d.register(idOf("LdrFindResource_U"), "LdrFindResource_U", handleLdrFindResource_U)
|
|
d.register(idOf("LdrFindResourceDirectory_U"), "LdrFindResourceDirectory_U", handleLdrFindResource_U) // same logic
|
|
d.register(idOf("LdrAccessResource"), "LdrAccessResource", handleLdrAccessResource)
|
|
d.register(idOf("RtlFindClearBitsAndSet"), "RtlFindClearBitsAndSet", handleRtlFindClearBitsAndSet)
|
|
d.register(idOf("LdrQueryImageFileExecutionOptions"), "LdrQueryImageFileExecutionOptions", handleLdrQueryImageFileExecutionOptions)
|
|
d.register(idOf("RtlReleasePath"), "RtlReleasePath", handleRtlReleasePath)
|
|
|
|
// SList operations
|
|
d.register(idOf("RtlInitializeSListHead"), "RtlInitializeSListHead", handleRtlInitializeSListHead)
|
|
d.register(idOf("RtlInterlockedFlushSList"), "RtlInterlockedFlushSList", handleRtlInterlockedFlushSList)
|
|
d.register(idOf("RtlInterlockedPopEntrySList"), "RtlInterlockedPopEntrySList", handleRtlInterlockedPopEntrySList)
|
|
d.register(idOf("RtlInterlockedPushEntrySList"), "RtlInterlockedPushEntrySList", handleRtlInterlockedPushEntrySList)
|
|
d.register(idOf("RtlQueryDepthSList"), "RtlQueryDepthSList", handleRtlQueryDepthSList)
|
|
|
|
// Performance counter
|
|
d.register(idOf("RtlQueryPerformanceCounter"), "RtlQueryPerformanceCounter", handleRtlQueryPerformanceCounter)
|
|
d.register(idOf("RtlQueryPerformanceFrequency"), "RtlQueryPerformanceFrequency", handleRtlQueryPerformanceFrequency)
|
|
|
|
// Misc
|
|
d.register(idOf("RtlRandom"), "RtlRandom", handleRtlRandom)
|
|
d.register(idOf("RtlOpenCurrentUser"), "RtlOpenCurrentUser", handleRtlOpenCurrentUser)
|
|
d.register(idOf("RtlQueryDynamicTimeZoneInformation"), "RtlQueryDynamicTimeZoneInformation", handleRtlQueryDynamicTimeZoneInformation)
|
|
d.register(idOf("wine_get_host_version"), "wine_get_host_version", handleWineGetHostVersion)
|
|
|
|
d.register(idOf("NtUserInitializeClientPfnArrays"), "NtUserInitializeClientPfnArrays", handleNtUserInitializeClientPfnArrays)
|
|
d.register(idOf("NtUserGetSystemDpiForProcess"), "NtUserGetSystemDpiForProcess", handleNtUserGetSystemDpiForProcess)
|
|
|
|
// Atom table
|
|
d.register(idOf("NtAddAtom"), "NtAddAtom", handleNtAddAtom)
|
|
d.register(idOf("NtDeleteAtom"), "NtDeleteAtom", handleNtDeleteAtom)
|
|
d.register(idOf("NtFindAtom"), "NtFindAtom", handleNtFindAtom)
|
|
d.register(idOf("NtQueryInformationAtom"), "NtQueryInformationAtom", handleNtQueryInformationAtom)
|
|
|
|
// NtUserCallOneParam / NtUserCallTwoParam
|
|
d.register(idOf("NtUserCallOneParam"), "NtUserCallOneParam", handleNtUserCallOneParam)
|
|
d.register(idOf("NtUserCallTwoParam"), "NtUserCallTwoParam", handleNtUserCallTwoParam)
|
|
|
|
// NtGdi* - GDI object stubs
|
|
d.register(idOf("NtGdiCreateBitmap"), "NtGdiCreateBitmap", handleNtGdiCreateBitmap)
|
|
d.register(idOf("NtGdiCreatePatternBrushInternal"), "NtGdiCreatePatternBrushInternal", handleNtGdiCreatePatternBrushInternal)
|
|
d.register(idOf("NtGdiDeleteObjectApp"), "NtGdiDeleteObjectApp", handleNtGdiDeleteObjectApp)
|
|
d.register(idOf("NtGdiSelectBitmap"), "NtGdiSelectBitmap", handleNtGdiSelectBitmap)
|
|
d.register(idOf("NtGdiSelectBrush"), "NtGdiSelectBrush", handleNtGdiSelectBrush)
|
|
d.register(idOf("NtGdiSelectPen"), "NtGdiSelectPen", handleNtGdiSelectPen)
|
|
d.register(idOf("NtGdiSelectFont"), "NtGdiSelectFont", handleNtGdiSelectFont)
|
|
d.register(idOf("NtGdiCreateSolidBrush"), "NtGdiCreateSolidBrush", handleNtGdiCreateSolidBrush)
|
|
d.register(idOf("NtGdiCreatePen"), "NtGdiCreatePen", handleNtGdiCreatePen)
|
|
d.register(idOf("NtGdiCreateRectRgn"), "NtGdiCreateRectRgn", handleNtGdiCreateRectRgn)
|
|
d.register(idOf("NtGdiCreateCompatibleDC"), "NtGdiCreateCompatibleDC", handleNtGdiCreateCompatibleDC)
|
|
d.register(idOf("NtGdiGetStockObject"), "NtGdiGetStockObject", handleNtGdiGetStockObject)
|
|
d.register(idOf("NtGdiCreateCompatibleBitmap"), "NtGdiCreateCompatibleBitmap", handleNtGdiCreateCompatibleBitmap)
|
|
d.register(idOf("NtGdiHfontCreate"), "NtGdiHfontCreate", handleNtGdiHfontCreate)
|
|
d.register(idOf("NtGdiExtGetObjectW"), "NtGdiExtGetObjectW", handleNtGdiExtGetObjectW)
|
|
d.register(idOf("NtGdiGetDeviceCaps"), "NtGdiGetDeviceCaps", handleNtGdiGetDeviceCaps)
|
|
d.register(idOf("NtGdiGetAndSetDCDword"), "NtGdiGetAndSetDCDword", handleNtGdiGetAndSetDCDword)
|
|
d.register(idOf("NtGdiSaveDC"), "NtGdiSaveDC", handleNtGdiSaveDC)
|
|
d.register(idOf("NtGdiRestoreDC"), "NtGdiRestoreDC", handleNtGdiRestoreDC)
|
|
d.register(idOf("NtGdiCombineRgn"), "NtGdiCombineRgn", handleNtGdiCombineRgn)
|
|
d.register(idOf("NtGdiGetRgnBox"), "NtGdiGetRgnBox", handleNtGdiGetRgnBox)
|
|
d.register(idOf("NtGdiSetRectRgn"), "NtGdiSetRectRgn", handleNtGdiSetRectRgn)
|
|
d.register(idOf("NtGdiOffsetRgn"), "NtGdiOffsetRgn", handleNtGdiOffsetRgn)
|
|
d.register(idOf("NtGdiPatBlt"), "NtGdiPatBlt", handleNtGdiPatBlt)
|
|
d.register(idOf("NtGdiBitBlt"), "NtGdiBitBlt", handleNtGdiBitBlt)
|
|
d.register(idOf("NtGdiOpenDCW"), "NtGdiOpenDCW", handleNtGdiOpenDCW)
|
|
d.register(idOf("NtGdiGetTextMetricsW"), "NtGdiGetTextMetricsW", handleNtGdiGetTextMetricsW)
|
|
d.register(idOf("NtGdiFlush"), "NtGdiFlush", handleNtGdiFlush)
|
|
|
|
// ── Wave 10: additional NT handlers ──────────────────────────
|
|
// RtlEncode/DecodePointer (used by CRT on Vista+)
|
|
d.register(idOf("RtlEncodePointer"), "RtlEncodePointer", handleRtlEncodePointer)
|
|
d.register(idOf("RtlDecodePointer"), "RtlDecodePointer", handleRtlDecodePointer)
|
|
d.register(idOf("RtlEncodeSystemPointer"), "RtlEncodeSystemPointer", handleRtlEncodeSystemPointer)
|
|
d.register(idOf("RtlDecodeSystemPointer"), "RtlDecodeSystemPointer", handleRtlDecodeSystemPointer)
|
|
d.register(idOf("RtlCmDecodeMemIoResource"), "RtlCmDecodeMemIoResource", handleRtlCmDecodeMemIoResource)
|
|
d.register(idOf("RtlIoDecodeMemIoResource"), "RtlIoDecodeMemIoResource", handleRtlIoDecodeMemIoResource)
|
|
// Thread management
|
|
d.register(idOf("NtTerminateThread"), "NtTerminateThread", handleNtTerminateThread)
|
|
d.register(idOf("ZwTerminateThread"), "ZwTerminateThread", handleNtTerminateThread)
|
|
d.register(idOf("NtCreateThread"), "NtCreateThread", handleNtCreateThread)
|
|
d.register(idOf("NtCreateThreadEx"), "NtCreateThreadEx", handleNtCreateThreadEx)
|
|
// Job objects
|
|
d.register(idOf("NtCreateJobObject"), "NtCreateJobObject", handleNtCreateJobObject)
|
|
d.register(idOf("NtOpenJobObject"), "NtOpenJobObject", handleNtOpenJobObject)
|
|
d.register(idOf("NtAssignProcessToJobObject"), "NtAssignProcessToJobObject", handleNtAssignProcessToJobObject)
|
|
d.register(idOf("NtQueryInformationJobObject"), "NtQueryInformationJobObject", handleNtQueryInformationJobObject)
|
|
// SEH / exception unwind (x64)
|
|
d.register(idOf("RtlAddFunctionTable"), "RtlAddFunctionTable", handleRtlAddFunctionTable)
|
|
d.register(idOf("RtlInstallFunctionTableCallback"), "RtlInstallFunctionTableCallback", handleRtlInstallFunctionTableCallback)
|
|
d.register(idOf("RtlDeleteFunctionTable"), "RtlDeleteFunctionTable", handleRtlDeleteFunctionTable)
|
|
d.register(idOf("RtlAddGrowableFunctionTable"), "RtlAddGrowableFunctionTable", handleRtlAddGrowableFunctionTable)
|
|
d.register(idOf("RtlGrowFunctionTable"), "RtlGrowFunctionTable", handleRtlGrowFunctionTable)
|
|
d.register(idOf("RtlDeleteGrowableFunctionTable"), "RtlDeleteGrowableFunctionTable", handleRtlDeleteGrowableFunctionTable)
|
|
d.register(idOf("RtlLookupFunctionEntry"), "RtlLookupFunctionEntry", handleRtlLookupFunctionEntry)
|
|
d.register(idOf("RtlCaptureContext"), "RtlCaptureContext", handleRtlCaptureContext)
|
|
d.register(idOf("RtlVirtualUnwind"), "RtlVirtualUnwind", handleRtlVirtualUnwind)
|
|
// Misc NT
|
|
d.register(idOf("NtAreMappedFilesTheSame"), "NtAreMappedFilesTheSame", handleNtAreMappedFilesTheSame)
|
|
d.register(idOf("NtSetTimerEx"), "NtSetTimerEx", handleNtSetTimerEx)
|
|
}
|
|
|
|
// registerWin32kHandlers registers placeholder Win32k handlers.
|
|
func (d *Dispatcher) registerWin32kHandlers() {
|
|
for i, name := range win32uExports {
|
|
id := win32uIDBase + uint32(i)
|
|
d.names[id] = name
|
|
}
|
|
// Win32k handlers are registered by the win32k package when available.
|
|
}
|
|
|
|
// RegisterWin32kHandler allows external packages to register Win32k handlers.
|
|
func (d *Dispatcher) RegisterWin32kHandler(name string, h TrapHandler) {
|
|
d.mu.Lock()
|
|
defer d.mu.Unlock()
|
|
for i, n := range win32uExports {
|
|
if n == name {
|
|
id := win32uIDBase + uint32(i)
|
|
d.handlers[id] = h
|
|
d.names[id] = name
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// idOf returns the syscall ID for a given NTAPI function name.
|
|
func idOf(name string) uint32 {
|
|
for i, n := range ntapiExports {
|
|
if n == name {
|
|
return ntapiIDBase + uint32(i)
|
|
}
|
|
}
|
|
// Check win32u exports
|
|
for i, n := range win32uExports {
|
|
if n == name {
|
|
return win32uIDBase + uint32(i)
|
|
}
|
|
}
|
|
panic(fmt.Sprintf("unknown ntapi export: %s", name))
|
|
}
|
|
|
|
// handleNoop is a no-op handler returning STATUS_SUCCESS.
|
|
func handleNoop(ctx *TrapContext) uint32 {
|
|
return StatusSuccess
|
|
}
|