3

I tried to load kext module on M1 machine running 11.4 Beta (20F5046g) Big Sur and encounter some error messages on binding at kext module loading.

Accessing kernel symbol exported from Apple kext modules

First, to access the kernel functions exported from apple's kext module, com.apple.kpi.unsupported, I used the below extern declaration.

extern int  cpu_number(void);

Also, I added the com.apple.kpi.unsupported on the info.plist

    <key>OSBundleLibraries</key>
    <dict>
            <key>com.apple.kpi.libkern</key>
            <string>20.5</string>
            <key>com.apple.kpi.unsupported</key>
            <string>20.5.0</string>
    </dict>

The compilation doesn't raise any errors, but when I try to load the module, it prints below message.

Error Domain=KMErrorDomain Code=31 "Error occurred while building a collection: 
    1: One or more binaries has an error which prevented linking.  See other errors.
    2: Could not use 'kext' because: Failed to bind '_cpu_number' in 'kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
kext specific: 
    1: Failed to bind '_cpu_number' in 'kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
" UserInfo={NSLocalizedDescription=Error occurred while building a collection: 
    1: One or more binaries has an error which prevented linking.  See other errors.
    2: Could not use 'kext' because: Failed to bind '_cpu_number' in 'kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
kext specific: 
    1: Failed to bind '_cpu_number' in 'kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol

Can I access the kernel symbol specified in the kernel symbol list but not exported from apple's kext module?

I also would like to access kernel function called SecureDTInitEntryIterator. I found that this symbol is listed on the kernel symbol located in the /System/Library/Kernels/kernel. However, $kextfind -defines-symbol _SecureDTIterateEntries doesn't return any corresponding kext module names.

As an IOS newbie, I guess that this symbol is not exported from any apple's kexy module. Is there any way to access this function from my kext module? I think I can just type cast the address where the symbol is located within the kernel space with the function prototype, but I am looking for a systematic approach if there exists.

Frant
  • 5,382
  • 1
  • 16
  • 22
ruach
  • 1,369
  • 11
  • 21
  • Note that iOS does not support kexts at all, but as you mention "Big Sur" I assume you mean macOS. – pmdj Apr 26 '21 at 12:13

1 Answers1

1

I have just checked, and the crucial detail appears to be that you are trying to access this function on arm64/aarch64. As it turns out, it's exported in the "unsupported" KPI for x86_64, but not on arm64:

There's no straightforward way of accessing unexported symbols. If you know the offset of a symbol in the exact version of the running kernel, you should be able to compute the address by offsetting from a known function address; at least, this worked on x86-64. arm64 may require extra effort due to PAC (pointer authentication).

As this circumvents Apple's policies, I don't recommend using this type of technique in a shipping product.

pmdj
  • 22,018
  • 3
  • 52
  • 103
  • I think I need to type cast the kernel memory to the symbol that I want to access. For this I've tried to use the symbols in $nm /System/Library/Kernels/kernel to get the virtual address of _SecureDTIterateEntries and cast that address with a function pointer with proper return type and arguments. However, it seems that kernel crash and system reboots. Does it because I used the wrong address in the symbol file? – ruach Apr 26 '21 at 14:06
  • Also, when I take a look at the symbols with nm, it seems that all those symbols' addresses are not changed at every boot. I assume that the kernel address space is randomized because of the KASLR but why the variables are located at the same virtaul address? – ruach Apr 26 '21 at 14:07
  • @ruach the base address of the kernel is randomised for security purposes (KASLR) and further modified for pointer authentication (PAC) so what you need to do is take the address (function pointer) of some public exported symbol and add or subtract the distance between it and the symbol you are looking for in the kernel. – pmdj Apr 26 '21 at 14:08
  • @ruach Basically, your function pointer value is: `fnptr = kaslr_base + fn_offset_in_kernel_image + pac_value`, and `nm` only tells you `fn_offset_in_kernel_image`. – pmdj Apr 26 '21 at 14:10
  • I thought that nm command returns all the kernel symbol addresses dynamically, nope? Then how can I retrieve the base address of the current kernel on kext? are there any exported symbol containing the pointer of the base address of the kernel? – ruach Apr 26 '21 at 14:12
  • `nm` is entirely static, it just looks in the file. The addresses of public KPIs should already be correctly adjusted, so you can use e.g. `memcpy` or any other function as a base. Something like: `int (*cpu_number_fn)(void) = (int(*)(void))((uintptr_t)&memcpy - memcpy_offset + cpu_number_offset);`. (Last time I did this was on x86 though, so you may need to experiment some more on M1. Be aware that the offsets change with each kernel version and variant.) – pmdj Apr 26 '21 at 14:16
  • I thought that it is kind of a kallsyms in linux. Sorry to bother you but what is the meaning of the arithmetic operations? What are the memcpy_offset and cpu_number_offset? I really appreciate your help. Or Is it possible to just modify the xnu source code to expose some symbols? I haven't tried to compile the xnu kernel and install it from the source code. If that is possible... maybe I don't need to do this circumvetion :) – ruach Apr 26 '21 at 14:20
  • Those are the offsets you can get from `nm`. (Make sure you also pass the correct `-arch=` argument to the command as the offsets will of course be different for arm64 and x86_64.) – pmdj Apr 26 '21 at 14:22
  • 1
    You may also want to look at https://www.zdziarski.com/blog/?p=6901 and the code that blog post links to, and also the older post by another author here: http://ho.ax/posts/2012/02/resolving-kernel-symbols/ – pmdj Apr 26 '21 at 14:25
  • I could successfully find the base address and SEG_LINKEDIT section command, but couldn't locate the LC_SYMTAB in the loaded kernel binary. I think the current version of macOS intentionally remove the symbol command, but not sure it is true or whether my code was wrong. I would like to check Xnu source code to confirm it is intentionally deleted on the memory or not. Which code should I take a look at in the xnu? Thanks again – ruach Apr 30 '21 at 11:21