Finding the memory address of fs:28h

224 views Asked by At

I debug a program with gdb for fun, with stack guard so it writes the canary to the stack from fs:28h. Out of curiosity, I trying to find the memory address that fs:28h points to. I encounter two problems. first, gdb cannot show me the value in gdtr/ldtr because it doesn't run in ring zero. second, When reading fs with gdb it contains 0, how does it make sense? I know that gdt/ldt contain 0 in the first index to return invalid address and the RPL is off so what am I missing here? If anyone knows how to find the address that segment register fs points to I would like to know.

file: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked
1

There are 1 answers

3
zwol On

You appear to be using x86_64-linux-gnu, i.e. all three of x86-64 CPU, Linux kernel, and the GNU C Library. With this combination of hardware and system software, the FS segment is set such that the memory operand %fs:0 refers to the beginning of the thread control block for the currently executing thread. (A thread control block is an internal C library data structure that describes a running thread. You can think of it as the object referred to by a pthread_t thread handle.)

Precisely because x86 has historically not made it easy for unprivileged code to look up the "actual" address (more precisely "linear virtual address") referred to by a %fs:xxx or %gs:xxx memory operand, the first field of the thread control block on x86_64-linux-gnu is a pointer to the thread control block itself. Thus,

void *read_fs(void) {
    void *rv;
    asm("movq %%fs:0, %0" : "=r" (rv));
    return rv;
}

will return the address you want. Keep in mind that this is only guaranteed to be true on x86_64-linux-gnu. If you switch to a different Unix kernel (e.g. FreeBSD) or a different C library (e.g. musl libc), there's a good chance that the FS segment will still point to the thread control block, but the data in that space is likely to be rather different.