Reading a process' memory using ptrace but with restrictions

104 Views Asked by At

I have a simple program with an initialized global variable, and I'm trying to use ptrace to read its data section.

Restrictions: I have no r permission to the elf. I don't have root privilege, so I don't have r permission to the target program's /proc/PID/maps.

My attempts: I know the size of the text section. Running LD_SHOW_AUXV=1 ./target tells me that the program has aslr. I wrote another snippet to see if $rip at the beginning of the program is the same as its base address

//from target program
    printf("base: %lx\n", getauxval(AT_BASE));

and

//from tracer program
        ptrace( PTRACE_GETREGS, my_pid, NULL, &regs );
        printf("rip: %lx\n", regs.rip);

I got

rip: 7fa86c82b140
base: 7fa86c811000

Both /proc/PID/maps and auxv can only be accessed by the target program, and $rip isn't directly usable. What to do now? I thought about injecting instructions to access auxv, but the target program doesn't have the <sys/auxv.h> library.

Update:

Since memory mapping for different files may not be continuous, I experimented again, but this time with root privilege to read /proc/PID/maps.

rip: 7f55e1354140
header: 56214add2040
entry: 56214add3080

and from /proc/PID/maps

56214add2000-56214add3000 r--p 00000000 08:01 3145841                    /home/kali/Desktop/target
56214add3000-56214add4000 r-xp 00001000 08:01 3145841                    /home/kali/Desktop/target
...
7f55e133b000-7f55e1360000 r-xp 00001000 08:01 4202628                    /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

So $rip was actually at the linker before going for .text?

Since $rip is so close to the upper end of the process' memory, can I search forward to read auxv, as it should be right after environment variables, at the top? Or can I simply pipe the return value of LD_SHOW_AUXV=1 ./target to my tracer?

1

There are 1 best solutions below

0
Nate Eldredge On

Normally the ELF header is mapped into the process's memory as the very first page, below .text and other sections of code and data. Since RIP is most likely pointing somewhere within .text, you could start from that address and do a binary search backward, looking for the first page which is mapped. You can identify whether a page is mapped by seeing whether PTRACE_PEEKTEXT (or PEEKDATA, they are actually the same) succeeds. (Note that you can't determine success or failure from the return value; you have to set errno = 0 before the call and see if it remains zero afterward.) As a check, that page should have \x7f E L F as its first four bytes (i.e. the first dword would be 0x464c457f).

Once you have found that header, you could parse it to locate the offset of the .data section.