In the windbg commands while setting a breakpoint using bp the address is converted to int
using pwndbg.inthook.xint. This verifies if the argument is actually an address but in case of pie binaries it could be possible that the address is loaded later and then the argument is casted to uint32_t
[/tmp] tail hello.c
#include <stdio.h>
int main(int argc, char **argv) {
puts("Hello World");
return 0;
}
[/tmp] make hello 17:41:43
cc hello.c -o hello
[/tmp] gdb -q hello 17:41:47
pwndbg: loaded 177 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from hello...(no debugging symbols found)...done.
pwndbg> bp 0x00005555555546b0
Breakpoint 1 at 0x555546b0
pwndbg> bl
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000555546b0
pwndbg> r
Starting program: /tmp/hello
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x555546b0
[pwndbg] git --no-pager log -1 --stat 18:07:21 ☁ dev ☀
commit ca17c6dbb0d1bc40ef060331aa48dad0675c5df9
Author: Alisson Bezerra <[email protected]>
Date: Tue Apr 9 05:54:00 2019 -0300
Add xuntil command (#604)
pwndbg/commands/peda.py | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
[pwndbg] lsb_release -a 18:08:01 ☁ dev ☀
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 9.8 (stretch)
Release: 9.8
Codename: stretch
[pwndbg] gdb -q 18:10:56 ☁ dev ☀
pwndbg: loaded 178 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
pwndbg> show version
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
pwndbg> py import sys; print(sys.version)
3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516]
pwndbg>
Thanks for reporting this. Woa, this is an interesting bug.
Would you mind working on a fix for this?
Sure Yea. I'll try to send a PR.
As I was looking at some other unrelated things, I stumbled across this as well.
To debug this a bit more, I added the following right before pwndbg/inthook.py:42
print("sizeof(long): " + str(pwndbg.typeinfo.long.sizeof))
print("sizeof(int64) : " + str(pwndbg.typeinfo.int64.sizeof))
print("sizeof(void *): " + str(pwndbg.typeinfo.pvoid.sizeof))
print("Arch: " + pwndbg.arch.current)
Here is the output I got:
$gdb binary
pwndbg> bp 0x555555554200
sizeof(long): 4
sizeof(int64) : 8
sizeof(void *): 4
Arch: i386
Breakpoint 1 at 0x55554200
pwndbg> start
[Error removed for brevity]
sizeof(long): 8
sizeof(int64) : 8
sizeof(void *): 8
Arch: x86-64
To me, it appears that prior to running the binary, pwndbg has the wrong typeinfo. It seems to be using assuming that the binary is 32 bit. After running the binary, the typeinfo seems to be correct.
I realize this information comes from gdb.lookup_type, which makes this quite strange.
It's especially strange given that gdb doesn't seem to predefine types like int given that gdb.lookup_type doesn't return anything rust/golang binaries that don't have those types (This is from what I recall reading, I can't seem to find anything about it now).
One potential solution to this would just be cast to int64 instead of long if the binary is 64 bit, or potentially always, unless it ends up breaking something.
It also looks like the arch for pwndbg doesn't get changed until the binary is started. It just stays at the default.
The only actual way I could figure out to get if the binary was 64 bit or not was by running info target and parsing that.
Sorry to be replying again, but I found something new.
I'm still not sure why gdb.lookup_type behaves the way it does.
Even still, we can fix this by generating correct typeinfo when the binary is loaded. The reason we currently do not get correct typeinfo is that the update method in typeinfo.py only listens for the start and stop events. I believe a way to fix this would be to have the update method listen for @pwndbg.events.new_objfile to get correct type information.
It doesn't seem like this could break anything, but I would rather have someone with more knowledge of the type system give input.
Sorry to be replying again, but I found something new.
Don't be sorry for replying! That's great that you contribute!
Can it be a bug withing gdb itself? I sometimes stumbled upon certain things not working properly or working a bit differently e.g. for PIE binaries or remote debugging. It could have been a GDB issue or this typeinfo thing...
Regarding the potential fix, I think it is okay if we just subscribe to one more event.
Don't be sorry for replying! That's great that you contribute!
Thanks. I'm new to contributing on github so just trying to feel out the etiquette.
Can it be a bug withing gdb itself? I sometimes stumbled upon certain things not working properly or working a bit differently e.g. for PIE binaries or remote debugging. It could have been a GDB issue or this typeinfo thing...
This behavior doesn't actually appear unique to PIE binaries, it's just that no one tries breaking on high addresses for non-pie binaries.
Regarding the potential fix, I think it is okay if we just subscribe to one more event.
I'll open a pull request.