Several days ago I made PoC to extract addresses of WSK data from windows 10 arm64 afd.sys - specifically AfdWskClientListHead and lock AfdWskClientSpinLock. Nothing special except fact that afd.sys has no exported functions. So you must find some rare constant, then find functions which use it and only then do some disasm applying state machine to each code block (see lambda passed to traverse_simple_state_graph)
While I was writing this code, I was not left with a question whether it is possible to employ computer to build such state machines. And now I know that this is possible (at least for code on plain C for RISC-like asm with predictable addresses of instructions etc etc)
Lets see how such algo can be arranged:
1) you must find all cross-refs to desired variable and collect list of functions which use it (exactly what deriv_hack::find_xrefs method does)
2) then you must disasm each such function and try to get some primitives - like loading of constants, calling imported/exported functions etc - see deriv_hack::make_path method. Sure set of this primitives will be different for each processor and perhaps will depends from your tasks
Results for afd.sys!AfdWskClientListHead:
found at 00002698
load
call_imp KeAcquireInStackQueuedSpinLock
load
found at 00004B30
const 43444661 count 1
call_imp ExAllocatePoolWithTag
call_imp KeInitializeSpinLock
load
call_imp KeAcquireInStackQueuedSpinLock
load
found at 000078C4
load
call_imp KeAcquireInStackQueuedSpinLock
load
found at 0000D8B0
load
call_imp ExEnterCriticalRegionAndAcquireResourceExclusive
load
call_imp KeAcquireInStackQueuedSpinLock
load
found at 0000D9F0
load
call_imp KeAcquireInStackQueuedSpinLock
load
found at 00015BD8
load
load
call_imp KeAcquireInStackQueuedSpinLock
load
found at 000988D0
load
- wait for loading of constant 0x43444661
- then wait for ExAllocatePoolWithTag call
- then wait for KeAcquireInStackQueuedSpinLock
- and first loading in this state is AfdWskClientListHead