понедельник, 8 февраля 2021 г.

fsm rules syntax

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

  1. We must make functions distinguishable. Functions must be either exported or contain loading of some constant - from constant pool or from .rdata section
  2. 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

вторник, 26 января 2021 г.

auto-derived FSM for usermode dlls

As expected results of auto-derived FSM for usermode dlls are much worse - for example on rpcrt4.dll can be found only 76 symbols from 228. It's because code in usermode contains much fewer unique constants (like NTSTATUS or allocation tags in kernel). So we need to use some additional data to make edges more distinguishable. Lets consider several candidates

load_config

Contains addresses of SecurityCookie and ptrs to GuardCFCheckFunctionPointer & GuardCFDispatchFunctionPointer. At least knowing SecurityCookie we can distinguish loading of some address in .data section from loading of cookies in prolog/epilogue of functions. But results are almost the same - 78 from 228

delayed import

New source of data missing in kernel mode. So I added new state to FSM - call_dimp, almost the same as call_imp but for delayed IAT. As expected results have grown - 109 from 228

constants in .rdata section

arm64 code can use not only ldr from constant pool but regular const data in .rdata section - for example strings for GetProcAddress etc. Lets see how looks such code:

понедельник, 25 января 2021 г.

W32pServiceTable from windows 10 build 20292 64bit

 It seems that MS cut off whole apfnSimpleCall dispatching - no more functions

  • NtUserCallHwndParamLock
  • NtUserCallHwndParam
  • NtUserCallHwndLockSafe
  • NtUserCallHwndParamLockSafe
  • NtUserCallHwndLock
  • NtUserCallHwnd
  • NtUserCallNoParam
  • NtUserCallTwoParam
  • NtUserCallOneParam
  • NtUserCallHwndSafe
  • NtUserCallHwndOpt
Instead all functions from apfnSimpleCall now exported and contained in W32pServiceTable. Like (just to name few):
  • CreateMenu -> NtUserCreateMenu
  • CreatePopupMenu -> NtUserCreatePopupMenu
  • AllowForegroundActivation -> NtUserAllowForegroundActivation
etc etc
content of W32pServiceTable (W32pServiceLimit .eq. 0x5AA):

четверг, 14 января 2021 г.

using of auto-derived state machines

Let`s see what we can do with our auto-derived state-machines. All source code in my github repo

Simple case: KdLocalDebugEnabled

Assume that we want to find address of KdLocalDebugEnabled. On kernel 18345 RVA is 37CC18 and it located in section .data. Run
ldr.exe -se -t 8 -der D:\work\kernel\w10\18346\arm\ntoskrnl.exe 37CC18
to build rules. Option -t sets number of threads. Results:

found at 0076D850 - KdSystemDebugControl
 ldrb exorted KdDebuggerEnabled
 ldrb
apply return 37CC18, must_be 37CC18

This rule say that we must find exported function KdSystemDebugControl, wait for loading of exported symbol KdDebuggerEnabled and next loading operation will give us address of KdLocalDebugEnabled
Now apply this rule for kernel RTM 2004 (with option -T you can specify files on which to test rules):
ldr.exe -se -t 8 -der D:\work\kernel\w10\18346\arm\ntoskrnl.exe 37CC18 -T d:\work\kernel\w10\rtm\2004\arm\ntoskrnl.exe
 ldrb exorted KdDebuggerEnabled
 ldrb
Test[0]: C3F639

Lets check this address
// pubsym <rva 0xc3f639> KdLocalDebugEnabled

Second case: CmpTraceRoutine

IDA Pro shows 106 xrefs on kernel 18345, RVA is 8A8008. Lets see if rule for finding this address can be derived automatically:

воскресенье, 10 января 2021 г.

efficiency of auto-derived state machines

It`s time to measure how effective this state-machines. I made today simple perl script to measure how much symbols (located in sections .data, ALMOSTRO and PAGEDATA) can be found for arm64 windows kernel. The conditions for success are

  • found function is exported
  • or found function use some unique constant which is used no more than 3 times
Result on kernel build 18346:
total: 3493 symbols, found 1466

Simple state machine with states containing only loading/storing, call import/export and loading of some constant is able to retrieve almost 42% of symbols

PS: for adf.sys (which has no exported functions at all) results even better:
total: 164 symbols, found 73
44.5%

пятница, 8 января 2021 г.

(semi)auto building of state machine

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:

вторник, 29 декабря 2020 г.

IDCFuncs in ida pro 7.x

Let's assume what we want to have some normal programming language inside ida pro (not strange looking pile of spaces). Or just to made RPC interface so you can use several instances of ida from external processeses. In previous versions (since 4.x - I can be wrong) we had IDCFuncs which I used for example to embed perl. But since 7.x this symbol is no longer exported (obviously to make users' lives even more unbearable). Sure this small problem can`t stop me. So there are at least two ways to find IDCFuncs in any ida pro 7.x

signature search

strictly speaking this method allows you to find IDCFuncs->funcs. Name of first function in this array of ext_idcfunc_t always is "____" (yes, some undocumented function with name of four underscores). So you first must search for it in .text section (in ida.dll/ida64.dll) and then find address in .data - this will be first ext_idcfunc_t:

struct ext_idcfunc_t
{  const char *name;             ///< Name of function  
   idc_func_t *fptr;             ///< Pointer to the Function
   const char *args;             ///< Type of arguments. Terminated with 0.        
   const idc_value_t *defvals;   ///< Default argument values.
   int ndefvals;                 ///< Number of default values.     
   int flags;                    ///< \ref EXTFUN_
};

some disasm magic

It`s very ironic that in the disassembler you have to use another disassembler to find what you want. Lets see which exported functions use IDCFuncs