вторник, 30 июня 2020 г.

search references in arm64 code

Let's assume that you want to find address of non-exported CrashdmpCallTable in kernel. Usual old school way is to find unicode string "\SystemRoot\System32\Drivers\crashdmp.sys" and then to find reference to in .text section - if you are lucky enough this will be somewhere in middle of function IopLoadCrashdumpDriver. But on arm64 loading of address splitted in pair of instructions and even worse - values depends from address of instruction. Let`s see how it looks:

.text:00000001401AF700 6A 01 00 90     ADRP  X10, #aSystemrootSy_0@PAGE ; "\\SystemRoot\\System32\\Drivers\\crashd"...
.text:00000001401AF704 48 C1 09 91     ADD   X8, X10, #aSystemrootSy_0@PAGEOFF ; "\\SystemRoot\\System32\\Drivers\\crashd"...


Output from cmdline disasm for each of opcodes:
armpatched.exe 6A010090
Disassembled: adrp x10, 2c000

        This instruction is AD_INSTR_ADRP and is part of group AD_G_DataProcessingImmediate
        This instruction has 4 decode fields (from left to right):
                0x1, 0, 0xb, 0xa
        This instruction has 2 operands (from left to right):
                This operand is of type AD_OP_REG
                        Register: x10 size 40
                This operand is of type AD_OP_IMM
                        Immediate type: AD_IMM_ULONG
                        Value: 0x2c000

and
armpatched.exe 48C10991
Disassembled: add x8, x10, #0x270

        This instruction is AD_INSTR_ADD and is part of group AD_G_DataProcessingImmediate
        This instruction has 7 decode fields (from left to right):
                0x1, 0, 0, 0, 0x270, 0xa, 0x8
        This instruction has 3 operands (from left to right):
                This operand is of type AD_OP_REG
                        Register: x8 size 40
                This operand is of type AD_OP_REG
                        Register: x10 size 40
                This operand is of type AD_OP_IMM
                        Immediate type: AD_IMM_ULONG
                        Value: 0x270


What are the options?

пятница, 19 июня 2020 г.

sve/sve2 instructions for arm64

Today I finished adding of sve/sve2 instructions to my pet-project armpatched
I used as reference ISA_A64_xml_futureA-2019-09_OPT.pdf
Sure code is full of bugs, incomplete and has terrible style - all what you can expect from 7KLOC on plain C
Known problems:
  • since my main goal was code analysis disasm strings looks not very good - for example I totally emit register size suffixes (although size storing in op_reg.sz)
  • I don`t know for what used "fields" so they filled in voluntary random order
Zx registers marked as floating point with op_reg.fp == 2 and Px registers with op_reg.fp == 3
Code was tested on all possible instructions and looks like it does not crash. Bcs it seems that some instructions use floating point you must use KeSaveFloatingPointState/KeRestoreFloatingPointState in case of kernel mode

пятница, 12 июня 2020 г.

arm64 pc-relative literals

Lets see for example non-exported function function SepInitializeCodeIntegrity from arm64 kernel:
  STP             X19, X20, [SP,#-0x20+var_10]!
  STP             X21, X22, [SP,#0x10+var_s0]
  STR             X23, [SP,#0x10+var_s10]
  STP             X29, X30, [SP,#0x10+var_20]!
  MOV             X29, SP
  ADRP            X8, #SeCiCallbacks@PAGE
  ADD             X20, X8, #SeCiCallbacks@PAGEOFF
  ADD             X8, X20, #4
  MOV             W21, #6
  ADD             X9, X8, #0xC0

loc_1406A9C90                           ; CODE XREF: SepInitializeCodeIntegrity+30 j
  STP             XZR, XZR, [X8],#0x10
  CMP             X8, X9
  B.NE            loc_1406A9C90
  STR             WZR, [X8]
  MOV             W9, #0xD0
  LDR             X8, =0xA000007

qword_1406A9D30 DCQ 0xA000007


As you can see all DWORD constants under arm64 stored in some place after function, so you sure can find address 1406A9D30 but how to find function which using this constant? Instruction ldr can be located in range of 1Mb from this address

вторник, 9 июня 2020 г.

undocumented env vars in mscorwks.dll

There are lots of env vars with prefix COMPlus_
So lets see only not presented in this document

Main function constructing name of env var is ?EnvGetString@REGUTIL@@SAPEAGPEBGH@Z called from:
  • ?UnsafeGetConfigDWORD@@YAKPEBGK@Z
  • ?GetConfigDWORD@EEConfig@@SAKPEBGKKHW4ConfigSearch@1@@Z
  • ?GetConfigString@EEConfig@@SAJPEBGPEAPEAGHW4ConfigSearch@1@@Z
  • ?init@ConfigDWORD@@AEAAXPEAGK@Z
  • ?GetConfigString@REGUTIL@@SAPEAGPEBGHW4CORConfigLevel@1@@Z
  • ?GetConfigDWORD@REGUTIL@@SAKPEBGKW4CORConfigLevel@1@H@Z

and perhaps from several thousand more places so I wrote some script to collect names and filter out known. Final list is:
  • AllowStrongNameBypass - DWORD
  • AssemblyUsageLogImpersonateUser - DWORD
  • BBSweep - DWORD
  • BreakOnAV - DWORD
  • bypassTrustedAppStrongNames - DWORD
  • Cor_Enable_Profiling - DWORD
  • DbgJITDebugLaunchSetting - DWORD
  • DbgManagedDebugger - string
  • DbgThreadCreateOption - DWORD
  • DisableDoubleMapping - DWORD
  • DisableSecurityTransparency - DWORD
  • EagerWatsonBuckets - DWORD
  • EHGolden - DWORD
  • JumpStubReserve - DWORD
  • legacyAssemblyProvidedEvidence - DWORD
  • legacyHMACWarning - DWORD
  • legacyMyComputerZone - DWORD
  • legacyV1CASPolicy - DWORD
  • LOPFriendlyFrames - DWORD
  • MD_TrackColDesMisses - DWORD
  • MemoryReport - DWORD
  • MemoryReportBreakOnContext - string
  • MemoryReportOutput - string
  • MemoryReportStackFrames - DWORD
  • MemoryReportSweepInterval - DWORD
  • MultiDomainHostGAC - DWORD
  • NGenAllowMsiInstall - DWORD
  • PrecodeInCodeHeap - DWORD
  • ReaderWriterLock_UseFixedIdGeneration - DWORD
  • ShowMetaDataAccess - DWORD
  • StressLoadThreadCount - DWORD
  • useEnUSLcidWithComInvoke - DWORD
  • UseFileMappingForByteArrays - DWORD
  • UseMethodDataCacheInFindDispatchImpl - DWORD
  • UsePcRel32Calls - DWORD

понедельник, 8 июня 2020 г.

COMPlus_ETWEnabled

There is nice trick to hide that your .NET assemblies does not have ETW logging
Lets see if we can detect this not from environment vars
ETW logging inited in mscorwks.dll!CEtwTracer::Register: