Vault7: CIA Hacking Tools Revealed
Navigation: » Latest version
Owner: User #15728648
Ghidra
Manual Analysis of a 64-bit kernelcache in Ghidra
Getting Trustcache-related offsets
Hint: When using the Calculator app to get these values, open the large negative integer in scientific mode, then open in programmer mode to view the correct hex conversion.
- Install Ghidra 5.6.3 with AARCH64 processor support
- Run analysis
- find "last entry has non-NULL string in kernelcache by doing a memory search for the string
- this is in a kext, so find mach_header_64 by search backwards in memory, search for 'feedfacf', in hex
- mark as as mach_header_64 (press t)
- next available memory, mark as segment_command_64
- Expand segment to see number of sections
- next avail, mark as an array of section_64
- expand first section, should be __text, __TEXT
- copy size into clipboard, jump to address
- select the size of the section by doing Select -> bytes as shown below
- enter 'd' to disassemble
- jump back to string ref, jump to first xref
- open decompiler
- get unslid function address by:
- Run mop/kernel_cache.py with -s on the kernelcache, and subtract it from the function address
- OR manually looking at the start address of the __text, and find slide by subtracting __text segment start address minus the kernel load address - 0x1000, then subtract it from function address:
- Example:
kernel load address(predetermined): 0xffffff8000202000
__text section start address:0xffffff8014e03000
slide == 0xffffff8014e03000 - 0xffffff8000202000 - 0x1000 = 0x14c00000
- Example:
- edit the plist in entry EL_CONFIG_AMFI_ADD_JIT_HASH(4) -> unslid address function addres
- Example: ffffff800f93d420 - 0xEE00000 = 0xffffff8000B3D420
- Now we need the address of EL_CONFIG_AMFI_DYNAMIC_TRUSTCACHE struct. You can find it within the ADD_JIT_HASH function you found above.
Looking at disassembly, you can see a call to a a mutex_lock. The trustcache struct contains the lock being passed as x0, so subtract the DAT_reference by the offset in the disassembly
You can see above that DAT_ffffff800f959278 is the address of the lock being passed to FUN_ffffff800f93ed20, so we subtract 0x48 from ffffff800f959278 to get the address of the EL_CONFIG_AMFI_DYNAMIC_TRUSTCACHE struct. - Once you have the address, get its unslid address like you did above
- edit the plist in entry EL_CONFIG_AMFI_DYNAMIC_TRUSTCACHE(5) -> unslide address
- Example: 00f959230 -0xEE00000 = 0xffffff8000B59230
- Save the plist, build elutil and confirm el_trustcache works.
Generating Sandbox Profiles
- Checkout the apple_sandbox project.
- Edit the pull_profiles.rb file. You will be changing the NAMES_OFFSET and PROFILES_OFFSET global variables.
- Open /usr/libexec/sandboxd into Ghidra/IDA
- In the __const segment, find a string pointer to "AdSheet". Get the address of this pointer, subtract the base address value from it(usually 0x1000). Set the NAMES_OFFSET to this address.
- Move 0x100 ahead - this should be a pointer to the start of the profiles. Set the PROFILES_OFFSET to this address, with the base address subtracted as before.
- run pull_profiles.rb on the sandboxd binary you just disassembled. This should generate *sb.bin files in your output directory of all the profiles.
- Within the apple_sandbox project, cd into sb_decompiler directory.
- run ./sb_decompiler.rb ios_<your version here> <path to binary sandbox profile> <output name>
find ~/Desktop/Research/sandbox_profiles/7.0.3/binary_profiles/ -name "*.sb.bin" -exec ./sb_decompiler.rb ios_703 {} {}.sb \;
- Note: You may need to edit sb_decompiler.rb, and created a new iOS<version>.yaml file in sb_decompiler/src/version_info if the Apple's TinyScheme implementation changes/adds new rules etc.