Skip to content

Commit

Permalink
Retrieving ASLR offset using mach_vm_region
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Dec 30, 2020
1 parent 5c938b9 commit 50f9f9e
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 10 deletions.
2 changes: 1 addition & 1 deletion cmd/dlv/cmds/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func New(docCall bool) *cobra.Command {
rootCommand.PersistentFlags().StringVar(&backend, "backend", "default", `Backend selection (see 'dlv help backend').`)
rootCommand.PersistentFlags().StringArrayVarP(&redirects, "redirect", "r", []string{}, "Specifies redirect rules for target process (see 'dlv help redirect')")
rootCommand.PersistentFlags().BoolVar(&allowNonTerminalInteractive, "allow-non-terminal-interactive", false, "Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr")
rootCommand.PersistentFlags().BoolVar(&disableASLR, "disable-aslr", false, "Disables address space randomization. This option is forced to true on darwin/arm64")
rootCommand.PersistentFlags().BoolVar(&disableASLR, "disable-aslr", false, "Disables address space randomization")

// 'attach' subcommand.
attachCommand := &cobra.Command{
Expand Down
9 changes: 9 additions & 0 deletions pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,15 @@ func loadBinaryInfoMacho(bi *BinaryInfo, image *Image, path string, entryPoint u
if err != nil {
return err
}

if entryPoint != 0 {
// This is a little bit hacky. We use the entryPoint variable, but it
// actually holds the address of the mach-o header. We can use this
// to calculate the offset to the non-aslr location of the mach-o header
// (which is 0x100000000)
image.StaticBase = entryPoint - 0x100000000
}

image.closer = exe
if !supportedDarwinArch[exe.Cpu] {
return &ErrUnsupportedArch{os: "darwin", cpuArch: exe.Cpu}
Expand Down
22 changes: 22 additions & 0 deletions pkg/proc/native/proc_darwin.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,28 @@ reset_exception_ports(task_t task, mach_port_t *exception_port, mach_port_t *not
return KERN_SUCCESS;
}

mach_vm_address_t
get_macho_header_offset(task_t task) {
kern_return_t kret;
mach_vm_address_t address;
mach_vm_size_t size;
vm_region_basic_info_data_64_t info;
mach_msg_type_number_t infoCnt = VM_REGION_BASIC_INFO_COUNT_64;
mach_port_t object_name;

// start at 0x0
address = 0x0;

kret = mach_vm_region(task, &address, &size, VM_REGION_BASIC_INFO_64,
(vm_region_info_64_t)&info, &infoCnt, &object_name);
// Return 0 if we cannot find the address, since we implicitly use this to denote
// that we do not have the entrypoint in bininfo
if (kret != KERN_SUCCESS) return 0;

// address will then contain the start address of the section after __PAGEZERO, i.e. the mach-o header
return address;
}

char *
find_executable(int pid) {
static char pathbuf[PATH_MAX];
Expand Down
23 changes: 14 additions & 9 deletions pkg/proc/native/proc_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"unsafe"

sys "golang.org/x/sys/unix"
Expand Down Expand Up @@ -64,7 +63,7 @@ func Launch(cmd []string, wd string, flags proc.LaunchFlags, _ []string, _ strin
argvSlice = append(argvSlice, nil)

disableASLR := 0
if flags&proc.LaunchDisableASLR != 0 || (runtime.GOOS == "darwin" && runtime.GOARCH == "arm64") {
if flags&proc.LaunchDisableASLR != 0 {
disableASLR = 1
}

Expand Down Expand Up @@ -119,12 +118,10 @@ func Launch(cmd []string, wd string, flags proc.LaunchFlags, _ []string, _ strin

dbp.os.initialized = true

regs, err := dbp.memthread.Registers()
if err != nil {
return nil, err
}

dbp.os.entryPoint = regs.PC()
// This is a bit hacky. This is technically not the entrypoint,
// but rather we use the variable to points at the mach-o header,
// so we can get the offset in bininfo
dbp.os.entryPoint = uint64(C.get_macho_header_offset(dbp.os.task))

tgt, err := dbp.initialize(argv0Go, []string{})
if err != nil {
Expand Down Expand Up @@ -161,6 +158,12 @@ func Attach(pid int, _ []string) (*proc.Target, error) {
return nil, err
}

// TODO: Find out, if the target is actually using ASLR or not
// This is a bit hacky. This is technically not the entrypoint,
// but rather we use the variable to points at the mach-o header,
// so we can get the offset in bininfo
dbp.os.entryPoint = uint64(C.get_macho_header_offset(dbp.os.task))

tgt, err := dbp.initialize(findExecutable("", dbp.pid), []string{})
if err != nil {
dbp.Detach(false)
Expand Down Expand Up @@ -478,4 +481,6 @@ func (dbp *nativeProcess) EntryPoint() (uint64, error) {
return dbp.os.entryPoint, nil
}

func initialize(dbp *nativeProcess) error { return nil }
func initialize(dbp *nativeProcess) error {
return nil
}
3 changes: 3 additions & 0 deletions pkg/proc/native/proc_darwin.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,6 @@ get_task_for_pid(int pid);

int
task_is_valid(task_t task);

mach_vm_address_t
get_macho_header_offset(task_t task);

0 comments on commit 50f9f9e

Please sign in to comment.