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
Each rule starts with "section" keyword - it is section where located address which you want to find (you can use comments starting with '#'). Then you must pick function. If functions is exported it`s easy - "func" export_name, if not - just pick section where this function located with "fsection" section_name
Then follow one or more states of FSM:
- 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
Lets see example - say we want to find MCGEN_TRACE_CONTEXTs in kernel - registered with non-exported function McGenEventRegister_EtwRegister, There are 3 functions where this call occurs:
- FsRtlpHeatRegisterVolume
- IoInitSystemPreDrivers
- PnpDiagInitialize
none of them are exported. Try write rules for them
# FsRtlpHeatRegisterVolume - located in PAGE section
section .data
fsection PAGE
call_exp ExAcquireResourceExclusiveLite
# MS_StorageTiering_Provider_Context - store in index 2
stg2 load
# MS_StorageTiering_Provider
guid FC 55 0C 99 62 26 F6 47 B7 D7 EB 3C 02 7C B1 3F
stg1 call
# IoInitSystemPreDrivers - located in INIT section
section .data
fsection INIT
call_imp ExpInitializeStateSeparationPhase0
# IoTraceHandle - store in index 3
stg3 load
# IoTraceProvider
guid BD CA 03 A1 42 82 93 4A 8D F5 1C DF 3B 3F 26 A6
call_exp EtwRegister
# IoMgrProvider_Context - store in index 4
stg4 load
# IoMgrProvider
guid 86 F5 F1 AB 50 2E A8 4B 92 8D 49 04 4E 6F 0D B7
# call to MS_StorageTiering_Provider - stored in first rule with index 1
gcall 1
# PnpDiagInitialize - located in INIT section
section .data
fsection INIT
# MS_KernelPnP_Provider_Context - store in index 5
stg5 load
# MS_KernelPnP_Provider
guid 39 5A 20 9C 50 12 7D 48 AB D7 E8 31 C6 29 05 39
# call to MS_StorageTiering_Provider - stored in first rule with index 1
gcall 1
As you can see I just store address of McGenEventRegister_EtwRegister in first rule with index 1 and then use gcall 1 as last state - just to be sure if this function really was called. Remaining indexes described in comments. Apply this rules to kernel 20251:
afsm.exe -a D:\src\armpatched\Release\mc.fsm D:\work\kernel\w10\20251\arm\ntoskrnl.exe
[0] D:\work\kernel\w10\20251\arm\ntoskrnl.exe: found at 0 1 - 399238 2 - C0DBE0[0] D:\work\kernel\w10\20251\arm\ntoskrnl.exe: found at 0 1 - 399238 2 - C0DBE0 3 - C4A5D8 4 - C0A280[0] D:\work\kernel\w10\20251\arm\ntoskrnl.exe: found at 0 1 - 399238 2 - C0DBE0 3 - C4A5D8 4 - C0A280 5 - C04780
Now run this rules on kernel 18362:
afsm.exe -a D:\src\armpatched\Release\mc.fsm D:\work\kernel\w10\18362\arm\ntoskrnl.exe
Second rules has no match - it`s bcs IoMgrTraceHandle registered with EtwRegister on old versions of kernel, so lets add new rule:
You can ask me - wait, function IoInitSystemPreDrivers is so long, why first state which you want is call imported ExpInitializeStateSeparationPhase0? Bcs I don`t care about other used variables - I want only build FSM to extract addresses of IoTraceHandle & IoMgrProvider_Context
afsm.exe -a D:\src\armpatched\Release\mc.fsm D:\work\kernel\w10\18362\arm\ntoskrnl.exe
[0] D:\work\kernel\w10\18362\arm\ntoskrnl.exe: found at 0
1 - 1942A8
2 - 3561A0
[0] D:\work\kernel\w10\18362\arm\ntoskrnl.exe: found at 0
1 - 1942A8
2 - 3561A0
5 - 352E20
# IoInitSystemPreDrivers on old kernel
section .data
fsection INIT
call_imp ExpInitializeStateSeparationPhase0
stg3 load
guid BD CA 03 A1 42 82 93 4A 8D F5 1C DF 3B 3F 26 A6
call_exp EtwRegister
# IoMgrTraceHandle - store in index 6
stg6 load
guid 86 F5 F1 AB 50 2E A8 4B 92 8D 49 04 4E 6F 0D B7
call_exp EtwRegister
Комментариев нет:
Отправить комментарий