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

fsm rules for rpcrt4!GlobalRpcServer

I already described how you can extract address of GlobalRpcServer and offset to some RPC_SERVER_T fields. Lets do it for arm64 in declarative manner using FSM

Start again with I_RpcServerRegisterForwardFunction function - we can get address of RpcHasBeenInitialized (will be stored with index 1), GlobalRpcServer (with index 2) and RPC_SERVER_T.pRpcForwardFunction offset (with index 3):

section .data
func I_RpcServerRegisterForwardFunction
# 1 - RpcHasBeenInitialized
stg1 load
# 2 - GlobalRpcServer
stg2 load
# 3 - ForwardFunction offset
stg3 strx

Next we can get size of RPC_SERVER_T - from function InitializeRpcServer as argument to AllocWrapper. But InitializeRpcServer is surprisingly hard to find - it is not exported and called one time from InitializeServerDLL (which also non-exported). It using lots of unicode strings but unfortunately they all have common prefix "NT AUTHORITY" what makes them indistinguishable for signature 16 bytes. But you can notice that inside this function registering some RPC_SERVER_INTERFACE - so we can use its content as GUID: 

section .data
fsection .text
# size of RPC_SERVER_T - 1st arg to AllocWrapper, stored with index 4
stg4 movx0
# AllocWrapper
call
# store to GlobalRpcServer
gstore 2

Next in function you can see call to RtlInitializeCriticalSectionAndSpinCount expecting pointer to CRITICAL_SECTION as first argument (passed in register x0) - store this offset under index 5:

# x0 - offset to critical section, stored with index 5
stg5 addx0
call_imp RtlInitializeCriticalSectionAndSpinCount

And now we must insert loading of our pseudo-GUID to be able to find function InitializeRpcServer:

guid 60 00 00 00 80 BD A8 AF  8A 7D C9 11 BE F4 08 00
call .text

Also we can find offset to stop event - from exported function RpcMgmtStopServerListening, where this offset passed as first argument to SetEvent:

# stop event offset - from RpcMgmtStopServerListening
section .data
func RpcMgmtStopServerListening
gload 1
gload 2
# 7 - offset to stop event, 1st arg to SetEvent
stg7 ldrx0
call_imp SetEvent

Run our rules on couple of files:

afsm.exe -a D:\src\armpatched\fsm\tmp.fsm d:\work\kernel\w10\18363\arm\rpcrt4.dll D:\work\kernel\w10\rtm\2004\arm\rpcrt4.dll
[0] d:\work\kernel\w10\18363\arm\rpcrt4.dll: found at 0
 1 - 114D3C
 2 - 114D28
 3 - 178
 4 - 1F0
 5 - 60
 7 - 108
[1] D:\work\kernel\w10\rtm\2004\arm\rpcrt4.dll: found at 0
 1 - 10ED44
 2 - 10ED30
 3 - 178
 4 - 1F0
 5 - 60
 7 - 108

With only 3 simple rules we can extract:
  • address of RpcHasBeenInitialized - at index 1
  • address of GlobalRpcServer - at index 2
  • offset of RPC_SERVER_T.pRpcForwardFunction - at index 3
  • size of RPC_SERVER - at index 4
  • offset to some CRITICAL_SECTION in RPC_SERVER - at index 5
  • offset to stop event in RPC_SERVER - at index 7
This data is enough to select right version of RPC_SERVER struct (or at least say that this is some new and unknown version)

Комментариев нет:

Отправить комментарий