C/C++ ASLR, PLT, esoteric stuff

AlexanderProphet

Member

Thanks: 6
Messages: 26

#1
Hullo there,
I’m writing a simple debugger and have found myself way out of my depth. A Google search on my questions only turns up dodgy black hat websites and obsolete tutorials.
I’d like to know:
1) With Address Space Layout Randomisation, obviously the traced executable and any libraries it uses could be loaded anywhere in memory. So how do I interpret DWARF info that says, for example, that “main” lives at 0x4F0? Do I add a constant to it? What library call will get me the true offset of the target program at runtime?
2) I have successfully managed to patch jmp instructions in the tracee to call libc functions indirectly via my own diagnostic functions. However I’ve hit a big problem. Because I’m patching the Procedure Linkage Table via an injected .so, the functions are only patched locally in the shared object. Calling from the tracee results in the real functions being called. I’d like to access the main program’s PLT. How can I calculate its location programmatically? I’d rather the debugee doesn’t have to be recompiled or cooperate with this in any way, i.e. it shouldn’t need to know it’s being debugged.
And yes, I’m using Linux. I have FreeBSD installed in a virtual machine and intend to switch to that once the project has matured a bit. So Linuxy answers or better still a cross platform solution would be great.
Thanks in advance.
 

_martin

Aspiring Daemon

Thanks: 135
Messages: 719

#5
Well, FreeBSD doesn't have ASLR. But your 1) is more for PIE than ASLR. When program is executed kernel chooses the address for given section (no random offset in FreeBSD), does the required parsing of binary and then handovers it to ELF interpreter (INTERP), most likely ld-elf.so (linux: ld.so). I suggest you take look in ld sources to see how parsing is done. This all is related to FreeBSD though process is the same in general.
 
OP
OP
AlexanderProphet

AlexanderProphet

Member

Thanks: 6
Messages: 26

#6
Hi _martin,
(admin: I hope I'm okay accepting help, even though the rules say I shouldn't have received it?!)
Thanks for correcting my assumption that FreeBSD has ASLR. I guess I just assumed it did because of its general reputation for robustness. Thanks for the link. I prefer documentation to source generally though because it’s less prone to sudden unexpected changes. I even wrote my own DWARF parser because I found the DWARF standard documents much more readable than any source code I could find! I looked at the GDB sources in an attempt to shed light on my questions but they are labyrinthine - I had to give up.
Anyway, regarding question 1) above, I have found something like what I was looking for on Linux: the function dladdr1 has an argument called extra_info that you can use to obtain the difference between an address in the ELF file and a memory address. FreeBSD has dladdr which is similar - you can get a shared object’s base address at least. I think tinkering with the output of these functions could obtain me what I’m looking for on both platforms.
So I have a new question. This is a FreeBSD question I promise:
3) What is the FreeBSD equivalent of /proc/pid/maps? I need addresses to feed into the above-mentioned functions.
 

_martin

Aspiring Daemon

Thanks: 135
Messages: 719

#8
Rigoletto is right, you'll get better answers about this topic on the official mailing lists.

Nevertheless to the question you asked: FreeBSD doesn't use proc by default, though you can mount it - see procfs(5). /proc/$$/map is what you're after.

I'm guessing you are doing sort of emulation of the execution because you stated in 2) that you don't want process to know it's being debugged. It would make your task easier if you can trace the process ( use ptrace(2) syscall ). You'd have control over process and get around the addresses faster.

I'm not too happy with my answer I gave you above ; I wanted to make it short. The idea was though that when processes is being executed it all starts in kernel - kernel sets all structures, allocates the memory addresses (mappings), does a very little (required) parsing and handovers the execution to loader (userspace). Loader allocates other mappings as needed.
 
OP
OP
AlexanderProphet

AlexanderProphet

Member

Thanks: 6
Messages: 26

#9
Hi _martin, Rigoletto,
Thanks for being so welcoming and taking time to answer.
I’ve fixed both issues mostly to my satisfaction now so don’t need to resort to the mailing list.
_martin I’m already throwing ptrace at the problem. I’m not actually emulating anything (I’d have be mad to try to emulate an x86-64 CPU!) I’m writing a malloc debugger so am trying to intercept various memory-related calls. Actually I think valgrind emulates an entire CPU but that’s crazy territory. Intercepting calls will not allow to catch all bugs (invalid reads and writes for example) but it can catch leaks and invalid frees. And I’m hoping the tracee will be able run at near-normal speed. I should have something interesting to share quite soon.
 
Top