Reading Memory Pointed by Register with Gdb

Reading memory pointed by register with GDB

I would try something like the following commands (under gdb)

 p (int*)$esp
x /20x $esp
p ((int*)$esp)[3]

How to print value pointed by register

Rax 0x7fffffdd90
Now inwant to know where rax. Is pointîg to

You already know that: it points to (stack) memory location at address 0x7fffffdd90.

i want to print [rax]

 x/gx $rax

or

 print *(int**)$rax

I want to do somthing like set $eax = [$rax]

set $rax = *(int**)$rax

Using gdb to check register's values

To see the values of the registers just use

print $rax
info register $rax
info register

In your case it seems rax contains the number 0x17 and the debugger cannot access this location. Please make sure that rax contains a valid address pointing to an integer.

You should use print instead of display if you want to take a quick view. Dont abuse the display command. You can use it if you need a kind of watchdog for an expression.

Here you find a quick reference

http://www.yolinux.com/TUTORIALS/GDB-Commands.html

hope it helps.

dereferencing a register gdb

The x command will be the easiest way to display values in memory. Try, for instance:

(gdb) x/32b $ebp

If this doesn't work (especially if you get an error that "value can't be converted to integer"), you're probably debugging a 64-bit executable. x86-64 registers have different names; use $rbp instead.

The characters after the slash in the x command control how many values are displayed, and what format is used. x/s will attempt to read a string from that address, for instance. If you don't use anything, gdb will use whatever you last used.

While it isn't strictly necessary to answer your question, I've fixed up some of the other commands you were trying to run:

p *((char *) $ebp)       <- treat $ebp as a character pointer and display what it points to
p *((char *) $ebp + 4) <- with an offset
p ((char *) $ebp)[4] <- same thing as above, except using array syntax

The $ character is only needed when referring to registers, or to gdb variables. You don't need it for anything else.

How do I read the value of all registers with gdb?

info registers prints out registers values for me which is what you are asking I think:

(gdb) info registers
rax 0x7ffff7731ec8 140737344904904
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffd618 140737488344600
rsi 0x7fffffffd608 140737488344584
rdi 0x1 1
rbp 0x0 0x0
rsp 0x7fffffffd528 0x7fffffffd528
r8 0x7ffff7730300 140737344897792
r9 0x7ffff7dec250 140737351959120
r10 0x7fffffffd390 140737488343952
r11 0x7ffff73d0b50 140737341360976
r12 0x400be0 4197344
r13 0x7fffffffd600 140737488344576
r14 0x0 0
r15 0x0 0
rip 0x402330 0x402330 <main>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb)

How can one see content of stack with GDB?

info frame to show the stack frame info

To read the memory at given addresses you should take a look at x

x/x $esp for hex x/d $esp for signed x/u $esp for unsigned etc. x uses the format syntax, you could also take a look at the current instruction via x/i $eip etc.

How to set a gdb watchpoint to a value stored in register?

GDB doesn't let you explicitly dereference void * pointers such as $rsp. It doesn't know the size or the format of the pointed-to value.

Do watch *(char *)$rsp or watch *(int *)$rsp, etc., instead to watch for a change in what the register points to. (Either by memory writes, or by the register changing to point somewhere else.)

Using watch -l *(int*)$rsp will watch for changes to that 4-byte memory location, even if $rsp later changes. (Snapshotting the address).

On x86 CPUs, watch -l can use a hardware watchpoint, unlike without -l where it's monitoring for a change in evaluating the whole expression.

How do I get gdb to tell me memory characteristics a given address

gdb has no concept of dynamic allocation and no idea about freed memory. It can tell whether an address is mapped into the process address space or not:

gdb> info files
gdb> maintenance info sections

but since your program has crashed with a SIGSEGV, you already know it has tried to access an unmapped address.

Other tools can detect access to freed memory. valgrind is normally your friend, but not for post-mortem debugging. You need to run the program under valgrind to gain insight to its behaviour.

A segfault while dereferencing a pointer seldom means that the pointer is pointing to a freed memory. More often than not, it is the pointer itself that resides in freed memory that got reused and overwritten. So

int** ptrarr = new int*[5];
ptrarr[3] = new int(5);
// later
delete [] ptrarr;
// later still after many memory allocations
int* ptr = ptrarr[3]; // ptrarr points to freed memory; UB but no segfault
// ptr contains a seemingly random value
int num = *ptr; // possible segfault

It is very hard to extract this kind of information from a post-mortem dump of a non-instrumented executable. You need to be familiar with the internal working of malloc and new, be able to chase their internal data structures, and map out their arena by hand. This is not a trivial task. Using a version of the standard library with preserved debugging symbols will help.

Failing that, you may try and map out your program's memory, including static/global variables, stack variables, all allocated data structures pointed to by the above, and all allocated data structures pointed to by pointers in other allocated data structures. I know about no tools that are able to do this automatically from a post-mortem dump, though in theory such tools are possible.

Having mapped the program memory, or perhaps some part of it, you can try and find out if an unrelated object of a different type sits at the address where your invalid pointer resides. If so, you may conclude that one of the two objects might be freed memory that was illegally accessed after being freed.



Related Topics



Leave a reply



Submit