Address Space Layout Randomisation and PIE can change where an application is loaded into memory each time it is run. If you do not have symbols, this makes it harder to set breakpoints as you will not know the addresses (such as for a crash in a particular function) ahead of time because they will have changed since the last run.
On macOS, disable SIP before proceeding, otherwise debugging will not work.
As an example, a user in a Linux guest may perform a hypothetical action that results in the following hypothetical vulnerability in the VMware vmware-vmx
process that is running on the host operating system:
Process 642 stopped
* thread #8, stop reason = EXC_BAD_ACCESS (code=1, address=0xfffffffffffffffd)
frame #0: 0x00000001068b269d vmware-vmx`___lldb_unnamed_symbol5753$$vmware-vmx + 1037
vmware-vmx`___lldb_unnamed_symbol5753$$vmware-vmx:
-> 0x1068b269d <+1037>: mov eax, dword ptr [rdx]
0x1068b269f <+1039>: add ecx, -0x4
0x1068b26a2 <+1042>: mov dword ptr [rbp - 0x58], ecx
0x1068b26a5 <+1045>: cmp eax, 0x50c
Target 0: (vmware-vmx) stopped.
From the above, we know the hypothetical issue is in the vmware-vmx
process (refer to the frame #0
line).
Using LLDB's disass
command to disassemble the function that we have crashed in reveals the following:
(lldb) disass
vmware-vmx`___lldb_unnamed_symbol5753$$vmware-vmx:
0x1068b2290 <+0>: push rbp
0x1068b2291 <+1>: mov rbp, rsp
0x1068b2294 <+4>: push r15
0x1068b2296 <+6>: push r14
0x1068b2298 <+8>: push r13
0x1068b229a <+10>: push r12
0x1068b229c <+12>: push rbx
We cannot set a breakpoint on the name vmware-vmx`___lldb_unnamed_symbol5753$$vmware-vmx
, and the function's start address, 0x1068b2290
, may be different for each run because of ASLR and PIE. Using LLDB's image list
command, you can discover where the vmware-vmx
process has been loaded into memory:
(lldb) image list vmware-vmx
[ 0] D02523F0-41B5-3ED5-87A8-CF8EB4066916 0x00000001066fc000 /Applications/VMware Fusion.app/Contents/Library/vmware-vmx
By printing, as hex, the start of the function we are interested in (0x1068b2290
) minus the base address of the vmware-vmx
process (0x00000001066fc000
), we can find the offset of the function we are interested in:
(lldb) p/x 0x1068b2290 - 0x00000001066fc000
(long) $0 = 0x00000000001b6290
Now we know that the base address of vmware-vmx
+ 0x00000000001b6290
will always be the function we are interested in (until a software update is applied, which may change the offset).
The following shows a new debugging session, where LLDB's process interrupt
command is used to interrupt the vmware-vmx
process; find the current base address of vmware-vmx
; find the start address of the function we are interested in by adding our offset; and then setting a breakpoint on this function:
(lldb) process interrupt
Process 957 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x00007fff204f0c62 libsystem_kernel.dylib`kevent + 10
libsystem_kernel.dylib`kevent:
-> 0x7fff204f0c62 <+10>: jae 0x7fff204f0c6c ; <+20>
0x7fff204f0c64 <+12>: mov rdi, rax
0x7fff204f0c67 <+15>: jmp 0x7fff204ecb49 ; cerror_nocancel
0x7fff204f0c6c <+20>: ret
Target 0: (vmware-vmx) stopped.
(lldb) image list vmware-vmx
[ 0] D02523F0-41B5-3ED5-87A8-CF8EB4066916 0x000000010f6a2000 /Applications/VMware Fusion.app/Contents/Library/vmware-vmx
(lldb) p/x 0x000000010f6a2000 + 0x00000000001b6290
(long) $0 = 0x000000010f858290
(lldb) disass --start-address 0x000000010f858290
vmware-vmx`___lldb_unnamed_symbol5753$$vmware-vmx:
0x10f858290 <+0>: push rbp
0x10f858291 <+1>: mov rbp, rsp
0x10f858294 <+4>: push r15
0x10f858296 <+6>: push r14
0x10f858298 <+8>: push r13
0x10f85829a <+10>: push r12
0x10f85829c <+12>: push rbx
(lldb) br s -a 0x000000010f858290
Breakpoint 1: where = vmware-vmx`___lldb_unnamed_symbol5753$$vmware-vmx, address = 0x000000010f858290
You can learn more GDB and LLDB debugging commands in the GDB to LLDB command map document.