How can I set a breakpoint in windbg before loader fixes all addresses of the DLLs and imported functions?
Related
I try to build and load a basic kernel extension on macOS 13.2 Ventura on M1 (Apple Silicon).
There is a lot of literature online on macOS kext. However, many things have changed in recent versions of macOS regarding kext and most of this literature is obsolete.
Disclaimer: I know that "system extensions" should now be used instead of kext in most cases. In my specific case, this is a test kext to learn more on the Arm64 architexture and my purpose is only to read a few CPU system registers. These registers can be read at EL1 (kernel) only. This is why a system extension is not suitable and a kext is required. BTW, I already did the same thing on Linux with a dedicated loadable kernel module. I now try to transpose this to macOS.
As a prerequisite, I disabled SIP and allowed custom kexts.
I started with the kext template in Xcode and added a few traces, either using printf() (several articles on kexts mention a printf function in the kernel) or os_log(). The build is successful. I copied the kext bundle in another directory and make it owned by root.
When loading the module with sudo kmutil load -p test-kext.kext, I get the following errors when using os_log(). When using printf(), I have the same messages with _printf instead of __os_log_internal.
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 'test-kext' because: Failed to bind '__os_log_internal' in 'test-kext' (at offset 0x0 in __DATA_CONST, __auth_got) as could not find a kext which exports this symbolFailed to bind '__os_log_default' in 'test-kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
test-kext specific:
1: Failed to bind '__os_log_internal' in 'test-kext' (at offset 0x0 in __DATA_CONST, __auth_got) as could not find a kext which exports this symbolFailed to bind '__os_log_default' in 'test-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 'test-kext' because: Failed to bind '__os_log_internal' in 'test-kext' (at offset 0x0 in __DATA_CONST, __auth_got) as could not find a kext which exports this symbolFailed to bind '__os_log_default' in 'test-kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
test-kext specific:
1: Failed to bind '__os_log_internal' in 'test-kext' (at offset 0x0 in __DATA_CONST, __auth_got) as could not find a kext which exports this symbolFailed to bind '__os_log_default' in 'test-kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
The Xcode build is successful. In the build log, I see that the link command for the kext uses the options -no_adhoc_codesign -kext -nostdlib -lkmodc++ -lkmod -lcc_kext. It seems that some kernel libraries are referenced and I would expect to find the log functions.
In /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform, I have found libkmod.a and libkmodc++.a but I could not find any *cc_kext*. There is no symbol *printf* or *os_log* in libkmod.a and libkmodc++.a.
How would you log kernel messages from a kext on macOS 13 and how would you build the result?
libkmod and libkmodc++ don't provide access to general kernel APIs; they implement some small stubs of functionality related to kext startup and shutdown code which interact with the boilerplate kext code auto-generated by Xcode, as well as a handful of OSKext*() functions.
Kernel APIs are exported to kexts from the core kernel via "KPIs" which have bundle identifiers in the same way that kexts do. So the mechanism for linking against core kernel APIs is the same as declaring a dependency on another kext: the OSBundleLibraries Info.plist property.
Because identifying which KPI a particular symbol is defined in, there's a tool that scans your kext and spits out a list of bundle identifiers: kextlibs. There is a man page for kextlibs which goes into detail on more advanced uses of the tool.
As established in the comments, missing the requisite libkern KPI from OSBundleLibraries is what's causing the link errors in this case.
Thanks to the various help here, I managed to complete my kext, without Xcode, using only makefiles.
If anyone is interested by a complete kext example for macOS Ventura using makefiles only, you may have a look here:
https://github.com/lelegard/arm-cpusysregs
I'm debugging the linux kernel using kgdb module and gdb.
when trying to set a breakpoint at some address, gdb sets it at another, wrong address.
(gdb) b *0xffffffff81528690
Breakpoint 1 at 0x81528690
Anyone knows why?
I found what is the issue.
By default running gdb without specifying an executable will force 32-bit mode, that why address were truncated.
After running it on the kernel image, which was built for x86_64 architecture i could break on 64bit long addresses.
I have aslr enabled and when I play some game called assault cube the base address of this program is always the same (00400000) I get it by doing GetModuleHandle(NULL) also tried to get it with windbg and it also says 00400000 and I was wondering how come it never changes since for the other programs it always changes?
Even if you have ASLR enabled globally, Windows only applies it to applications that specifically indicate that they support it. Doing otherwise could easily make legacy applications crash unexpectedly, leading to compatibility problems. All executables and supporting DLLs must explicitly indicate that they support ASLR.
Indicating that you support ASLR is something you do when linking the object file by specifying the /DYNAMICBASE option (at least if you're using Microsoft's linker). Modern versions of the linker have it turned on by default, but if your game was compiled with an older version of the toolset before dynamic address relocation support was the default (e.g., VS 2008 and earlier) or with a linker from a different vendor, it is likely that it was not linked with ASLR support.
This is called out in the relevant MSDN article (emphasis added):
ASLR moves executable images into random locations when a system boots, making it harder for exploit code to operate predictably. For a component to support ASLR, all components that it loads must also support ASLR. For example, if A.exe consumes B.dll and C.dll, all three must support ASLR. By default, Windows Vista and later will randomize system DLLs and EXEs, but DLLs and EXEs created by ISVs must opt in to support ASLR using the /DYNAMICBASE linker option.
See also: Vista ASLR is not on by default for image base addresses
Note that you can modify the PE header of an existing binary, forcing it to support ASLR, by running the editbin utility available with the SDK. As with the linker, the /dynamicbase switch will turn it on.
Or, you can force ASLR globally by editing the following registry entry:
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\MoveImages
Of course, neither of these actually change the code, so if there are compatibility problems, the application will break.
I am trying to debug the kernel using windbg.My host is windows 7 x64.My target is windows 7 x86 which is installed in vmware.I have successfully connected to target machine.But often I am getting an error symbols could not be loaded.I have already set the path for symbols using the url of msdn.But I unable to connect net during debugging.SO I have planned to download symbols and specify the path .If I want to download means whether I have to download the x86 symbols or x64 symbols?
You need the symbols for the OS that's being debugged, 32-bit Windows 7 in your case.
Since your target PC is 32-bit, its drivers will be 32-bit as well and will require the 32-bit symbols for debugging.
Debugging session should not matter for connectivity to internet. If that is the issue, you may want to look into that.
You may also want to check:
Have you saved your workspace settings, so that symbol path is always set appropriately?
Try !sym noisy on debugger prompt and check for which symbols its giving the problems.
I want to know if an executable supports the common security protections such as NX flag, stack cookies or ASLR. It seems ASLR is set at the OS level but how do you know it is enabled? On Windows some executable do not support ASLR so I was wondering how you can determine this on Mac OS X.
First of all ALSR used in OSX 10.6 and below did not randomize all regions of memory. As far as I know ASLR is enabled for all running executables. This is very easy to test for, just fire up a debugger set a break point and record any memory address on the stack. Restart the application and see if that same variable has the same memory address.
I think in OSX 10.7 they started randomizing the dynamic linker. Which linux, bsd, and even windows systems have been doing for a number of years.
For OSX, linked libraries ASLR can be tested for using executing export DYLD_PRINT_SEGMENTS=1 and then running a command. The TEXT memory region is the base address for the library. Run this command twice against any binary. If the base address is different between the two execution then ASLR's dirty work is to blame.
Stack cookies are an entirely different ballgame. This is a compiler level protection and will vary based on the application. Modern versions of GCC should default to stack carnies enabled. Again you should consult your debugger to see if a specific application is using canaries. Just examine the stack frame of any function to see if there is a random value inserted between the locally declared variables and the return address.
As far as the NX flag goes, you should assume any system made after 1999 uses this trivial form of protection. But, this is by far the most simple protection for you to bypass, just ret-to-libc or employ an ROP chain (because of aslr).