Platform differences (not synonymous substitutions)
| Platform | Unit form | Loading and signing model | Type information source | Main observation surface |
|---|---|---|---|---|
| Windows | First distinguish the driver model: WDM / KMDF / UMDF / minifilter / NDIS·miniport; then discuss .sys(PE) |
SCM registration + driver signing (WHCP / test signing;as of 2026-04 legacy cross-sign is untrusted by default) | PDB(public≠private)、WDK / ntddk.h types |
WinDbg kernel debugging,!drvobj/!process/!wdfkd.*、Volatility |
| Linux | .ko(ET_REL relocatable object) |
insmod/modprobe + vermagic / symbol CRC / signature trailer |
BTF (including split BTF and .BTF.base), vmlinux, source code |
/proc/kallsyms、/sys/module/*/sections/, kprobe/ftrace, memory cross-view |
| macOS | Three models: KEXT (kernel mode) / DEXT·DriverKit (user mode) / System Extension (framework) | AuxKC (loaded at boot) + UAKL + Reduced Security / System Extension activation approval | Symbols, Mach-O,Info.plist(IOKitPersonalities) |
IORegistry、kmutil, dSYM+KDK; dext goes through user-mode analysis and debugging |
| Android | GKI module / vendor module | GKI signing + KMI symbol whitelist | BTF、KMI symbol list、Module.symvers |
Partition where the module resides,modules.load plan |
| seL4 (microkernel) | capability system: objects (TCB/Endpoint/CNode/Frame/Untyped/SC) + cap distribution | No capability means no access right; objects are created at construction time by spec/loader | capDL spec(.cdl)、CAmkES ADL、ELF |
capDL snapshot(seL4_DebugSnapshot)、seL4_DebugCapIdentify, QEMU emulation |
| Fuchsia/Zircon | handle references a kernel object(numericprocess-local)+ user-mode driver component(DFv2) | driver manager maintains node topology, driver index matches by bind rules , driver host hosts instances | FIDL, component manifest, bind rules | driver manager/driver index matching and topology, driver host process partitioning, handle+rights relationship graph |
| FreeBSD | .ko(KLD, ELF relocatable) |
linker sets + SYSINIT(SI_SUB_* + SI_ORDER_* ordering) + runtime kernel linker |
Symbols,set_* set, source code |
__start_set_*/__stop_set_* boundary, load path (built-in/preloaded/kldload) |
| illumos/Solaris | .so kernel modules (DDI/DKI drivers) |
_init → mod_install(&modlinkage);_fini → mod_remove |
modlinkage→modldrv→dev_ops→cb_ops static linking |
Read field by field dev_ops/cb_ops(including nulldev/nodev placeholder semantics) |
| OpenBSD | Same form as general Unix, but the kernelis relinked randomly on every boot(KARL) + autoconf runtime matching | link kit + rc background relinking; detach can wait for users to exit | Symbols (after KARL must compare by symbol rather than by bytes) | link kit/rc relinking traces, autoconf table, pledge/unveil state |
| NetBSD | .kmod(ELF, resolved by the kernel linker) |
automatically loaded on demand(including dependency recursion) + automatic unload; strict constraints between module and kernel versions | Module version reporting and kernel version | Actual module path (layout varies with KERNEL_DIR ),.plist attributes |
| Genode | Component tree:session + capability + quota | Routing mediated by parent, namesremapped layer by layer | Component XML configuration and routing table | capability's PD local naming, quota donation chain, ROM updates |
| MINIX 3 | User-space services + RS self-healing restart | RS monitoring/restart; label stable,endpoint changes | Fixed-length message (56 bytes) definition and grants | Service label↔endpoint, grant verification, live update phases |
| Plan 9 / 9front | Per-process namespace + user-space file server | bind/mount/union; services published via /srv then mounted |
9P's fid/qid/walk and message types | Namespace binding history, 9P session alignment |
| HelenOS | User-space server + fibril(kernel does not know) | User-space DDF; devman scores and starts drivers by match id | DDF structure (driver_ops_t) |
Distinction between kernel thread and user fibril |
| Redox | scheme + user-space daemon | Kernel converts file operations into SQE/CQE messages | SQE/CQE fields, handle mapping | scheme name → provider; mapping between client fd and provider descriptor |
| Haiku | kernel module, but split into driver module / device module two layers | Device Manager's device_node tree + on-demand discovery | Node attributes and bus type rules | /dev path ↔ node ↔ driver |
| IBM z/OS | TCB and SRB two types of schedulable units | cross-memory / PC / AR modes | Address space triple (home/primary/secondary) | Current primary/secondary/home and work unit type |
| IBM i | Object-based (library as container object) | Single storage layer: memory and disk in the same 64-bit address space | Object qualified names and global pointers | Object reference vs main memory address |
| OpenVMS | Process/thread + AST asynchronous control flow | $QIO + event flags + AST |
IOSB, AST parameters | Completion flow (IOSB → flag → AST) |
| Unikraft / MirageOS | Library operating system / unikernel: application and OS library as a whole chain | Build target determines everything (native vs binary; unix/hvt/xen…) | Build configuration and shim | How calls enter the "kernel", source of device wiring |
| HIC | Same privilege level processes + MMU isolation(Privileged-1 and Core-0 at the same physical privilege level); drivers only map authorized MMIO/shared memory | Self-describing modules (UUID/version/endpoint/resources/dependencies/signature) + capability accounting; dynamic loading and rolling updates | Module metadata, capability table | domain / capability / mapping / device ownership / version / lifecycle topology |
Failure Mode Decision Table (the main entry point of this skill)
When decompilation results or runtime observations conflict with expectations, use this table to suspect first, then rule out:
| Symptom | Suspect first (in order) | Direction to handle |
|---|---|---|
| struct offsets all wrong | ① Whether BTF matches the target ② Whether kernel build matches ③ RANDSTRUCT(CONFIG_GCC_PLUGIN_RANDSTRUCT; such kernels carry taint T) |
Priority: target BTF > exact build debug info > exact seed+config > dynamic verification > guessing offsets (worst) |
| symbol resolution is weird | ① MODVERSIONS(CRC)② Android KMI ③ livepatch(.klp.rela/.klp.sym)④ split BTF |
Check each according to the corresponding branch, don't treat it as "file corruption" |
| File and runtime behavior are inconsistent | ① Linux runtime relocation / init-only sections have disappeared ② macOS AuxKC is still running the old version ③ Android is actually loading a module with the same name from another partition | Record "disk version / running version / boot time", don't just look at the disk |
| Disk code and in-memory instructions are inconsistent | First rule out legitimate dynamic patching:alternatives、static keys/jump labels、ftrace、livepatch、paravirt、kprobe(Linux) | Only "unexplainable modifications" raise rootkit suspicion—many things that "look tampered with" are actually kernel mechanisms |
| A certain function cannot be found in memory | ① __init section has been freed ② built-in (there was never a separate .ko) ③ stripped ④ split BTF |
Trace "what state changes init left behind" (callback/hook/modified pointers), rather than looking for init itself |
kallsyms all 0 / addresses don't match vmlinux |
① kernel.kptr_restrict ② KASLR(both kernel text and module base are randomized) |
First look at the policy and recovery slide, don't judge "hooked" or "not the same kernel" |
| Symbolized offsets keep drifting / resolve to strings | ① Missed __TEXT_EXEC.vmaddr(arm64e's KEXT panic base address needs it added) ② The symbol file and panic image's UUID/build are inconsistent |
First adjust the base address by segment, then verify UUID+arch+exact build (KDK), don't doubt the disassembly |
| kext signature is valid but it just won't load | Not just the signature:UAKL / user approval / Reduced Security / AuxKC rebuild + reboot; x86_64 kext also hits KMErrorDomain 71(Rosetta does not translate kexts) |
Judge architecture / signature / approval / UAKL / boot policy / AuxKC inclusion separately |
UserClient can't connect / kIOReturnBadArgument |
① activated/entitlement/Team ID/sandbox ② dispatch's count/size/completion rejects before the handler | Troubleshoot in the order "authorization chain first, then ABI, finally handler", don't guess selector logic first |
| Module "disappears" | ① built-in (there was never a module file) ② rootkit unlinks it(module list unlink) ③ macOS Kernel Collection ④ Android another partition or another boot stage | Cross-view comparison, don't draw conclusions from a single view |
| driver IPC can't get through | ① selector/ABI ② entitlement ③ sandbox ④ Team ID (macOS) ⑤ service was never activated ⑥ dispatch's count/size/completion rejects before the handler(Windows' kIOReturnBadArgument for the isomorphic case see the macOS branch) |
Order it from "can it connect" to "how to tune after it connects", instead of guessing selectors directly |
Cannot find IRP handler / MajorFunction is empty |
Determine the driver model first:KMDF(!drvobj pointing to Wdf01000.sys is normal), NDIS/miniport, minifilter, UMDF |
Go find the corresponding callback registration graph(Evt* / Ndis* / FLT_* / WDF config dataflow), not "no I/O" |
IoCallDriver has returned but the behavior did not complete |
completion edge:STATUS_PENDING is not a failure, the terminal state is in IRP->IoStatus.Status and completion path (STATUS_MORE_PROCESSING_REQUIRED will take over) |
CFG needs completion edges added, otherwise cleanup/copy-back/retry looks like "nobody called it" |
Old .sys suddenly cannot load (the signature looks fine) |
① Since 2026-04, legacy cross-sign is untrusted by default(only WHCP recognizes it; pilot evaluation mode) ② Under HVCI, Test Mode still requires signing ③ Secure Boot blocks testsigning | Don't judge it as "signature corrupted" or "API changed"; check the policy layer first (see [[windows-kernel]] §26–28) |
| Seeing an abnormal ELF section | ① signature trailer (appended at the end of the ELF) ② livepatch .klp.rela ③ BTF/.BTF.base ④ ORC unwind ⑤ architecture/toolchain metadata |
Classify first, then handle;do not truncate/strip in order to "fix" it |
| The same CPtr numeric value is treated as the same object | CPtr is a local address in each CSpace, not a global ID (seL4) | Restore each CSpace mapping first, align by kernel object align |
| Thread/service "stuck" or looks like "configuration corrupted" | ① MCS: SC not bound / budget exhausted / passive server has no SC at all ② fault handler did not fix the fault | Troubleshoot according to MCS semantics (SC / budget / donation chain),don't apply POSIX deadlock assumptions |
| IRQ only comes once | No Ack (seL4: without ack the kernel will not send subsequent interrupts) | Check the IRQ handling loop for seL4_IRQHandler_Ack |
| The same handle numeric value is treated as the same object | A handle numeric value is only meaningful within the current process, and after closing it may still be reused (Fuchsia/Zircon) | Restore according to each process's handle table to align with kernel object ; in the relationship graph record object + handle + rights these three items |
A handle once held now reports BAD_HANDLE |
was sent away by channel_write sent away(in-transit / transfer), or the write failed and it was dropped |
Check the transfer semantics first (including whether ZX_RIGHT_TRANSFER was removed),don't judge it as UAF |
| There is clearly inter-driver IPC but there are no channel calls in the syscall trace | Two drivers co-reside in the same driver host → in-process channel of the driver runtime | Verify by driver host partitioning (only when co-residing do node symbols go in-process); don't judge it as "calls are hidden" ([[zircon-kernel]]) |
According to bus probe() , cannot find the driver binding |
DFv2 uses node properties + bind rules matched via the driver index | restore the node → bind rules → driver component → driver host chain, rather than looking for a probe callback ([[zircon-kernel]]) |
| some init / registration functionhas no callers at all | linker set registration(FreeBSD SYSINIT; for Zephyr see [[re-rtos/zephyr]]) |
trace back from the function address to the registration struct and the owning set_* set,don't mark it as dead code([[freebsd-kernel]]) |
a large contiguous run of pointers/objects, section name set_* |
the kernel's ownlinker set set | interpret it as a registration set, not a jump table / obfuscation table |
| inconsistent judgment of what the driver "supports" | nulldev(a legitimate no-op) and nodev(unsupported, returns ENXIO) are conflated |
read field by field dev_ops/cb_ops 's placeholder semantics ([[illumos-kernel]]) |
| same-version kernelthe layout differs on every boot / the two binaries are not byte-for-byte identical | KARL relinking(OpenBSD) — not patched, and not a different version | compare by symbol/semantics, don't do byte comparison ([[openbsd-kernel]]) |
| moduleappears on its own / disappears on its own, and no loader can be found | kernelon-demand automatic loadingand automatic unloading (NetBSD) | align it to the event that triggered it and the .plist settings, look at the timeline rather than the process ([[netbsd-kernel]]) |
| module loading fails but the file looks fine | module and kernelversion compatibility(NetBSD) | first verify the exact kernel version/build, don't just force-load it ([[netbsd-kernel]]) |
| the service name is the same but it seems connected to a different object / a capability value is treated as a global ID | the name only holds ina local hierarchy, and a capability is PD-local naming(Genode) | align by routing table + label chain / align by session ([[genode]]) |
| driver processdisappears and reappears | RS self-healing restart(MINIX 3) — not persistence | align the label (stable) with the endpoint (which changes) ([[minix3]]) |
| an integer in IPC is treated as a buffer pointer | it may be grant ID(MINIX 3, messages are fixed-length at 56 bytes) | restore by (endpoint, grant ID, offset, rights) ;EPERM is an invalid grant rather than insufficient permission |
| the path is the same but a different object is accessed | per-process namespace(Plan 9) | restore the bind/mount history and the 9P session, don't assert that it's the same resource based on the path ([[plan9]]) |
| a large number of "thread switches" appear within a single OS thread | fibril: user-space cooperative scheduling,the kernel doesn't know about it(HelenOS) | don't look for evidence in kernel scheduling ([[helenos]]) |
read/write what it lands on is not a filesystem |
the scheme determines the meaning(Redox) | Find provider by scheme name; client fd and provider descriptor are not equal ([[redox]]) |
| Driver absent at boot, appears only later | On-demand discovery(Haiku) | Check bus type rules and on-demand flags; do not judge as load failure ([[haiku]]) |
| Execution address belongs to another address space | cross-memory / PC instruction(z/OS) | Distinguish home/primary/secondary and TCB/SRB; do not judge as hijacking ([[zos]]) |
| Routine has behavior but no caller | AST asynchronous control flow(OpenVMS) | Add AST edges; waiting for "wait again after return" is normal ([[openvms]]) |
| Object address does not look like a DRAM pointer | Single storage layer(IBM i) | Memory and disk share the same 64-bit address space; do not apply the POSIX file model ([[ibmi]]) |
| Cannot find user → syscall → kernel boundary | Library OS / unikernel | First determine the build target; "system call" may just be a function call ([[unikraft-mirageos]]) |
| Module's self-describing metadata with its own UUID/version/endpoint/resource/dependency/signature | Do metadata triage first, then disassemble | Metadata is the first layer of evidence ([[hic]]) |
| Fast-path IPC appears as "entry page → bitmap test → failure branch → jump to business page", and the jump can trigger a fault | Normal IPC boundary(paging/verification path in isolated mode) | Do not judge as obfuscation / CFI stub / bad CFG ([[hic]]) |
| The same capability structure has different layouts across versions or documentation | First do generational fingerprinting(per-core without global lock ↔ protected global table) | Do not directly apply the structure according to the latest documentation ([[hic]]) |
| A large amount of "seemingly redundant" reset / state probing in initialization | sandbox restart / recovery path(driver rebuild ≠ hardware returning to clean boot) | Do not delete it as boilerplate ([[hic]]) |
Operational steps (cross-platform common mainline)
- Confirm identity: which one is this (version in disk / running / loaded set), what build (vermagic / CRC / KMI / signature), what form (PE / ET_REL / Mach-O / user-mode dext)
- Types and symbols: prefer official type sources (PDB / BTF / symbol table / KMI list), then precise build information, and only last inference
- Functional skeleton: partition functionality from imports/exports and kernel API call relationships—especially effective when closed-source or stripped
- Hooks and hiding: enumerate hook locations (table entries / inline text / callback arrays / operation structures) + cross-view crossover(user-mode view vs kernel real objects and memory)
- Verification and wrap-up: runtime verification (debugger / kprobe / IORegistry / memory side); conclusions and evidence archived per [[re-analyze/analysis-contract]]
Platform branches (references)
- [[windows-kernel]] —— First distinguish driver models(WDM/KMDF/UMDF/minifilter/NDIS·miniport);
GsDriverEntryis not a business entry; WDM'sDRIVER_OBJECTassignment graph; KMDF's Evt* callback andWDF_*_CONFIGdataflow(!drvobjrefers to Wdf01000.sys being normal); miniport/NDIS registration callbacks;device stack and INF stack location; minifilter altitude and pre/post pipeline;CTL_CODEandMETHOD_*buffer semantics (NEITHER user pointer);completion edge andSTATUS_PENDING;PAGEsection IRQL semantics; Driver Verifier fault injection and 0xC9; PE relocation; PDB public/private and signature+age;!analyze -vis only the entry point;UMDF/Wudfhost and!wdfkd.wdfumdevstacks;2026 driver signing policy and HVCI compatibility requirements;callback-registration graph - [[linux-kernel]] —— three don'ts(.ko is not an ordinary ELF / on-disk code is not the runtime truth / after suspecting a rootkit, do not trust a single enumeration); artifact identification (bzImage is a compressed boot image); relocation priority and
.modinfo;.kofull set of legitimate forms (signature trailer / compression / BTF and split BTF+.BTF.base/ RANDSTRUCT / livepatch.klp.*/ ORC unwind);list of legitimate dynamic patching(alternatives/static keys/ftrace/livepatch/paravirt/kprobe);__ex_tableexception edge; ENDBR; callback-registration graph;__initrelease and load-stage diagnostics (CONFIG_MODULE_STATS); MODVERSIONS two-generation format; KASLR and kptr_restrict; rootkit cross-view - [[macos-kernel]] —— mixing three models(KEXT kernel mode / DEXT user mode / System Extension framework);
Info.plistfirst and the IOKit class graph (OSMetaClass/vtable); codeless kext;disk vs AuxKC versionsand unload illusions; arm64e PAC pointers;newUserClient→externalMethodand dispatch'scheck*fields (kIOReturnBadArgumentmay be rejected by the framework); authorization chain troubleshooting order; dext analyzed and debugged as user mode; Kernel Collection;panic symbolication's__TEXT_EXECoffset and UUID/KDK matching; UAKL/Reduced Security/AuxKC and KIP; era differences of rootkits; KEXT two-machine debugging vs DEXT local debugging - [[android-kernel]] —— GKI vs vendor module, protected symbol and KMI allowlist, KMI branches not interchangeable, module location and load plan
- [[sel4-kernel]] —— capability system: CPtr is a local address, not a global ID, capDL/CAmkES semantics, badge and rights, CSpace guard/depth, error codes as diagnostics, Untyped and device untyped, user-mode driver IRQ and DMA bypass, fault IPC, MCS (SC/budget/passive server/reply object), capDL snapshot cross-view
- [[zircon-kernel]] —— handle locality(a value is valid only within a process, can be reused after closing, cross-process comparison is meaningless),in-transit and transfer(writing removes it from the sender, failure also consumes it,
ZX_RIGHT_TRANSFER, rights can only be narrowed; the relationship graph records object + handle + rights),DFv2(driver manager / driver host / driver index / driver runtime; bind rules match rather thanbus probe())、local channels of co-resident drivers(there is IPC but no syscall),/dev/foois a FIDL channel, not a Unix device file - [[freebsd-kernel]] —— linker sets and
SYSINIT: registration entries are placed into startup/shutdown sets, sorted bySI_SUB_*+SI_ORDER_*(the order of same sub and same order is undefined),modern ELF uses__start_set_*/__stop_set_*delimiters and is no longer NULL-terminated(scanning with the old structure will go out of bounds),set_*general criteria for sets, KLD'sSI_SUB_KLDmerge timing and reverse teardown - [[illumos-kernel]] —— DDI/DKI driver skeleton:
_init/_fini/_info→modlinkage→modldrv→dev_ops→cb_ops;nulldev(legal no-op) vsnodev(unsupported, returnsENXIO);attachofDDI_ATTACH/DDI_RESUME(DDI_PM_RESUMEhas been deprecated); per-instance initialization belongs toattach();_finiinmod_removemust not release resources when it fails - [[openbsd-kernel]] —— KARL relinking(randomly relinked on every boot
.o,what changes is the internal layout, not the load base address, different from KASLR; byte-by-byte differences cannot be used to determine a patch);autoconf runtime match/attach (foo_attachno caller is normal, detach can wait for users);pledge/unveil 's one-way ratchet and uncatchable SIGABRT ("accessible at startup, suddenly inaccessible afterward" is a design pattern, don't attribute it to external interception) - [[netbsd-kernel]] —— on-demand automatic module loading(appears even without modload, including dependency recursion) andautomatic unloading;strong compatibility constraints between modules and kernel versions(mismatch fails, forced loading carries an official warning); module paths change with
KERNEL_DIR's new layout (hardcoding/stand/...will miss samples) - [[genode]] —— component tree + session + capability + quota: service names hold only at the local parent level (each level can be remapped, labels can be rewritten); capability is a PD-local naming;quota donations are deducted level by level along the path("the system still has memory" and "that child is OOM" are not contradictory); ROM session supports updates
- [[minix3]] —— RS self-healing restarts(a driver disappearing and reappearing is normal);labels are stable, endpoints change; messages are fixed-length 56 bytes, large data goes through grants(
EPERM= grant invalid,EFAULT= unmapped);old/new instances coexist during live update(not injection) - [[plan9]] —— per-process namespace(paths with the same name may be different objects);union only stacks a single layer;
/srvis a service registry rather than a socket;9P's fid is a handle within a session;open/read/writeis often userspace RPC - [[helenos]] —— fibril(a userspace cooperatively scheduled entity,the kernel doesn't know it exists);userspace DDF driver framework(
driver_ops_tcallbacks, devman scores matches by match id and starts them); business logic is not in the kernel dispatch table - [[redox]] —— scheme model(
read()is not necessarily a filesystem; the client fd and the provider descriptor are not equal; the provider often enters the null namespace) + boot chain(bootloader → tiny ELF loader bootstrap → initfs two-stage boot) + relibc/auxiliary vector(stable ABI is in userspace,the syscall ABI is deliberately unstable) + drivers as userspace daemons (initfs and main systemtwo-pass build) - [[haiku]] —— driver side: device_node tree + on-demand discovery + driver module/device module two layers;system side: team/thread/area/port/semaphore kernel object model,KDL(stack trace/thread/memory/switch CPU) and debugging API (incompatible with BeOS incompatible), BeOS R5 one-way compatibility boundary, userspace service boundary
- [[zos]] —— TCB and SRB、home/primary/secondary, AR mode ALET; plus load module / program object(PDS vs PDSE)、AMODE/RMODE、XPLINK and non-XPLINK stack behavior are opposite(direction, 0x800 bias, unwind mechanism), SVC/PC tables, dump types and IPCS (fewer control blocks under XPLINK, see LEDATA), EBCDIC and record model
- [[ibmi]] —— layers(the boundary between MI / TIMI / SLIC / PASE),program model(OPM/EPM/ILE;
*MOD/*PGM/*SRVPGM;bind-by-copy vs by-reference)、activation group(PSSA/PASA/heap and overlay scope),two sets of pointers(system pointer/space pointer) andtwo storage models(single-level vs teraspace, including job boundaries and tagged pointer restrictions),executable material identification(DMPOBJ/compile listing/compressed state/timestamps are necessarily different) - [[openvms]] —— two control flows: AST (completion order write IOSB → set event flag → trigger AST; does not abort an in-progress system call; after the wait is interrupted, re-execute) andcondition handling(handler chain continuation/redelivery/unwind, second exception skips already-searched frames, the default three-piece set at image startup, differences between languages); also includesimage activation and shared images(logical name redirection, restrictions on privileged/execute-only images) and calling standards
- [[unikraft-mirageos]] —— library operating system/unikernel: single address space, single protection domain; native (syscall becomes a function call) vs binary-compatible (capturing Linux ELF syscalls);device wiring comes from build-time configuration, the same source code behaves completely differently on different targets
- [[hic]] —— capability + physical sandbox + multi-version driver system:processes at the same physical privilege level are isolated by the MMU(
Ring 0 → 全内核可寻址is an invalid assumption here);module metadata precedes disassembly;entry page IPC formis not obfuscation; shared memory pointers carry domain semantics{domain, cap, mapping, offset, length, rights};driver lifecycle and hardware lifecycle are modeled separately(instance/domain/device ownership/DMA/IRQ routing/binding/version/migration state). Includes cross-system comparison (Fuchsia / seL4-CAmkES / Xen / Genode / QNX / multikernel / MINIX) andhit-miss checklist(avoid false triggers on other capability systems)
when to use / when not to use
- Prerequisites:when unsure which system the target belongs to(non-PE/ELF, OSABI pointing to a non-mainstream system, no standard container) → first go through [[re-analyze/system-fingerprints]]
- Use: static reverse engineering and runtime verification of kernel-mode payloads and drivers on various platforms (malicious drivers / rootkits / anti-cheat / EDR evasion / closed-source drivers)
- Use:capability systems(microkernels such as seL4) object graph / capability distribution / IPC topology recovery, and determining "why the behavior differs from an ordinary OS"
- Use:Fuchsia/Zircon — handle and rights relationship recovery, DFv2 driver bind rules matching and driver host partitioning, determination of co-resident driver communication ([[zircon-kernel]])
- Use:FreeBSD / illumos·Solaris — initialization registered via linker set (no caller can be found) and KLD lifecycle ([[freebsd-kernel]]); DDI/DKI driver skeleton and
dev_ops/cb_opsCapability assessment ([[illumos-kernel]]) - Use: when you need to determine "what this code in memory/in the kernel is, where it came from, and whether it has been modified"
- Do not use: UEFI / boot stages (bootkit) → [[re-uefi]]; RTOS kernel objects → [[re-rtos]]; eBPF programs (BPF-64 instruction set, progs/maps) → [[re-ebpf]]; TEE / TrustZone → [[re-tee]]; kernel debugging and crash localization only → [[re-windbg]] / [[re-lldb]]
- Do not use: when you only need to acquire the payload in memory (without analyzing kernel structures) → [[re-sample-acquire]]
Tool preparation (by platform; see each branch for details)
- Windows: [[re-ghidra]] / [[re-ida]] (import WDK kernel types), [[re-windbg]] (two-machine / KDNET kernel debugging), Microsoft public symbols; test signing is enabled only inside the debugging VM (
bcdedit /set testsigning on, Secure Boot must be disabled) - Linux:
readelf/objdump -r(ET_REL and relocation),modinfo(vermagic/dependencies/signature/livepatch),pahole/bpftool(BTF)、bpftrace/perf probe(kprobe)、ftrace - macOS:
otool/vmmap/ioreg/kmutil/codesign -d --entitlements/lldb([[re-lldb]]、[[re-format-macho]]) - Android:
modinfo/readelf+ KMI symbol list of the target branch andModule.symverscomparison
Cross-domain combination
- [[re-windbg]] / [[re-lldb]] / [[re-gdb]]: kernel debugging and runtime verification on each platform
- [[re-binary-core]]: static preliminary survey foundation (PE/ELF/Mach-O parsing, imports and exports)
- [[re-malware]]: the in-depth analysis stage for rootkit / driver-based malicious samples references this skill
- [[re-anti-analysis]]: driver packing and obfuscation countermeasures
- [[re-sandbox]]: driver loading and debugging environment isolation (VM + snapshot, the highest principle of [[re-analyze/platform-tips]])
- [[re-emulation]]: extracted key functions can be emulated and verified
- [[re-mem-forensics]]: rootkit forensic cross-check (the offline side of cross-view)
- [[re-sample-acquire]]: on-site acquisition of kernel-mode payloads (attribution of anomalous execution regions and execution context)
- [[re-ebpf]]: eBPF programs (kernel code not in the
.koform) go there - [[re-rtos]] / [[re-uefi]] / [[re-tee]]: the division of labor for embedded kernels, boot stages, and trusted execution
- Decompiler tool selection: choose one of [[re-ghidra]] / [[re-ida]] / [[re-binaryninja]]
Common pitfalls and traps (cross-platform commonalities)
- Concluding based only on the on-disk version: Linux's init-only sections have already disappeared at runtime, macOS's AuxKC may still be running an old version, and Android may load a module with the same name from another partition——first align the three identities of "disk / runtime / loaded set"
- Treating a legitimate form that "looks broken" as corruption: Linux's signature trailer, livepatch section, and split BTF are not corruption (see the four forms in [[linux-kernel]])
- Using same-version assumptions to explain offset or symbol errors: RANDSTRUCT, MODVERSIONS, and KMI branches can all make the "same version" actually different
- Determining from a single view that "there is no hook / no hidden module":
lsmod、syscall table、/sys/moduleIf any one is clean, that does not constitute a conclusion—cross-view is required, andwhen views conflict, prefer offline memory forensics - Focusing only on the same old few hook techniques: modern landing points include operation structures, ftrace, kprobes, and inline text—"the syscall table is not hooked" does not mean the kernel is clean
- Kernel-mode operations are not isolated: loading/triggering kernel code may crash directly (Windows blue screen); do everything inside a debugging VM + snapshot (the highest principle of [[re-sandbox]])
- For platform-specific pitfalls, see the corresponding branch ([[windows-kernel]] / [[linux-kernel]] / [[macos-kernel]] / [[android-kernel]])