вторник, 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?

Sure you can try to disasm whole .text section and hope that sooner or later the right piece of code will be found
Or perhaps add some optimization. First thing to notice is that you always know address of instruction in arm64. So next thing is to check if some instruction is ADRP or ADD - you can use some bitmasks magic for this (see file aarch64-tbl.h from GNU binutils). And only when you have the right instructions you can use disassembler to extract immediate values. So algo looks like
  • make array of addresses for each RXX register with NULL as initial value
  • check with bitmask for adrp or add current opcode
  • disasm instruction
  • store for ADRP address using register as index
  • for ADD check if previous ADRP was not too far - bcs it can be in some previous function, so I add check for 40 bytes
  • if address from ADRP + current imm value from ADD == your reference - stop
I commited today this logic in my armpatched GitHub - see class xref_finder in file hack.h

Some results. Reference to string was found at offset 1AE704 from start of .text section - this is 0x6B9C1 opcodes. Disasm was called only 0xB3C1 times - 0x273C for ADRP and 0x7C3B for ADD

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

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