I added saving and loading of FSM rules in file - so now you can edit them (or perhaps even write new manually) and then apply with new tool afsm. So lets see how it works
- We must make functions distinguishable. Functions must be either exported or contain loading of some constant - from constant pool or from .rdata section
- Then this functions disassembling and FSM rules applied to code-flow graph. There may be several results, so I added global storage - it can be accessed by index from any rules (but sure this storage belongs to each processed file). Storage logic cannot be auto-derived so you should write such rules manually - storing states must have "stg" prefix with index
- load - loading from "section". Can have prefix stg N to remember this address
- store - storing to "section". Can have prefix stg N to remember this address
- ldrb - like "load" but for 1 byte
- ldrh - like "load" but for 2 bytes
- strb - like "store" but for 1 byte
- strh - like "store" but for 2 byte
- gload index - load address from storage with index
- gstore index - store to address from storage with index
- const - load some constant from constant pool
- rdata - load some 8 byte constant from .rdata section
- guid - load 16 byte guid from .rdata section. Actually rdata and guid could be one state with variable size but I am too lazy
- call_imp - call some imported function from IAT
- call_dimp - call some function from delayed IAT
- call_exp - call exported function
- call - just some call, perhaps located in specific section. Can have prefix stg N to remember this address
- gcall index - call function with address in storage
- FsRtlpHeatRegisterVolume
- IoInitSystemPreDrivers
- PnpDiagInitialize