I believe the `arch_to_regs[pwndbg.arch.current][item]` is a dead code.
I stumbled upon this during debugging one of other issues and:
* The `arch_to_regs` is a dict mapping str -> RegisterSet objects
* So `arch_to_regs[pwndbg.arch.current]` gets a `RegisterSet`
* Now, the `RegisterSet` doesn't have a subscription (the `__getitem__` magic method)
This can also be seen below:
```
>>> pwndbg.regs.arch_to_regs
{'i386': <pwndbg.regs.RegisterSet object at 0x7f931020b048>, 'x86-64': <pwndbg.regs.RegisterSet object at 0x7f931020b080>, 'mips': <pwndbg.regs.RegisterSet object at 0x7f9310212f98>, 'sparc': <pwndbg.regs.RegisterSet object at 0x7f9310212b38>, 'arm': <pwndbg.regs.RegisterSet object at 0x7f930ee7a6a0>, 'armcm': <pwndbg.regs.RegisterSet object at 0x7f930ee7aba8>, 'aarch64': <pwndbg.regs.RegisterSet object at 0x7f931020b0b8>, 'powerpc': <pwndbg.regs.RegisterSet object at 0x7f9310212518>}
>>> pwndbg.arch.current
'x86-64'
>>> pwndbg.regs.arch_to_regs[pwndbg.arch.current]
<pwndbg.regs.RegisterSet object at 0x7f931020b080>
>>> pwndbg.regs.arch_to_regs[pwndbg.arch.current]['$rax']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'RegisterSet' object is not subscriptable
>>> pwndbg.regs.arch_to_regs[pwndbg.arch.current][0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'RegisterSet' object does not support indexing
>>>
```
When pyelftools missed a PT_* name, invoking a `xinfo` command on a library with the missing program header crashed the `xinfo` command due to us assuming the ptype will be a string.
Instead, since pyelftoools didn't have the name, this ph is then an int.
So this commit takes this into acccount and omits those program headers that we weren't able to name due to lack of info in pyelftools.
This solution is not ideal as we might miss something, but given that we care about given program header name, I don't think it will be a big deal for us.
This commit fixes the issue described in #749.
During disasm output, we enhance the display to show additional information of the instructions.
When a future instruction executes a branch instruction (jmp/call), we fetch the next instruction based on the jmp/call target, as long as we can calculate it statically.
If we can calculate it statically, we will then display the target of the jmp/call as the next instruction, as e.g. in here:
```
> 0x5555555545fe <main+4> jmp main+4 <0x5555555545fe>
v
> 0x5555555545fe <main+4> jmp main+4 <0x5555555545fe>
```
The issue is, that we mark both instructions as "current", highlighting both of them, making it a bit unambigous "where we are".
While this view is _kinda valid_ as the PC is really the same, we want to mark/hightlight only the first instruction we are on, as it is the one that is being executed right now and the program might go some other path in the future.
This commit fixes this display by simply making it so that the `nearpc` function/command used to display disasm shows the marker only once, for the first time it shows the current PC instruction.
This should fix#726. I am not 100% sure if this is a complete fix, but lets see if it breaks for a few days and if not, we can make a last release with py2 support.
* Update heap implementation
* Heap commands default to using the debugged thread's arena, rather
than the main arena.
* Tcache commands are behind an OnlyWithTcache decorator.
* The "heap" & "top_chunk" commands only print relevant information
about chunks they encounter.
* Integrate _fetch_tcache_addr() into thread_cache().
* Move some code from get_region() into get_heap_boundaries().
* Rename some variables for clarity.
* Argparse descriptions are single-line so they don't get truncated.
* Some PEP8 changes such as whitespace & docstring width.
* Catch initialized heap but no thread arena case
When the main thread's arena has been initialized, but the debugged
thread's arena hasn't, default to the main arena when invoking
heap-related commands.
* Revert how cells are unpacked in vis_heap_chunks()
This corrects an error I introduced in 798bcb6, which resulted in
vis_heap_chunks() printing negative values on the heap with a minus sign
prepended.
* Add a --verbose flag to the heap() command
The -v or --verbose flag causes the heap() command to print every field
of every chunk it comes across, regardless of whether those fields are
in use.
* Remove unnecessary if statement from thread_cache()
Remove a check for whether the 'tcache' variable was 'None', when it
could never have been 'None'.
* Add alternate test for multiple threads
Some versions of GLIBC apparently don't have the __libc_multiple_threads
symbol. In these cases use GDB to determine whether there is more than
one active thread.
* Fixed alignment bug in vis_heap_chunks command
Used code from the "heap" command as a reference to fix this bug that sometimes causes "vis_heap_chunks" to print nothing due to an assumption that was being made in vis_heap_chunks (that the first chunk starts exactly on the heap region start). The specific target that I saw this bug behavior in was bcloud in https://github.com/ctfs/write-ups-2016/tree/master/bctf-2016/exploit/bcloud-200 (from a breakpoint before any heap exploit shenanigans, just legitimate mallocs). This patch fixes this behavior.
* Fixed additonal bug in vis_heap_chunks
* Feature: show ghidra decompiled code in context
With the help of radare2, r2pipe and r2ghidra-dec
* Update FEATURES.md
* Include review comments
* Removed embarrassing auto added guards
Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
* Fix inaccuracies in vis_heap_chunks()
Correct boundary calculation of chunks adjacent to a top chunk and
use a list of boundary addresses to do so, rather than a dictionary of
every quadword in each printed chunk. Ensure that at least 1 chunk is
printed even when a non-sensical value of 0 is passed as the count argument.
* Avoid out-of-bounds read in vis_heap_chunks()
While processing a corrupt heap or using the --naive option, the
vis_heap_chunks command could read out-of-bounds. Add a check to
avoid this scenario.
* Use chunk_flags instead of constants
To find out whether a chunk's prev_inuse bit is set, use chunk_flags() rather than anding with constants.ptmalloc.PREV_INUSE.
Co-Authored-By: Paweł Płatek <e2.8a.95@gmail.com>
* Use main_heap.size_sz
Use main_heap.size_sz in place of pwndbg.arch.ptrsize.
Co-Authored-By: Paweł Płatek <e2.8a.95@gmail.com>
* Replace a magic number with ptr_size
Co-Authored-By: Paweł Płatek <e2.8a.95@gmail.com>
* Calculate color_func variable in 1 line
Co-Authored-By: Paweł Płatek <e2.8a.95@gmail.com>
* Fix crash in get_heap_boundaries()
Don't assume that because an address was supplied to
get_heap_boundaries() that it resides on a legitimate heap. Sometimes a
user may want to print fake chunks elsewhere in memory.
Co-authored-by: Paweł Płatek <e2.8a.95@gmail.com>
The original code that searched for an arena's top chunk via the heuristic method of iterating through each chunk on a heap was written before the OnlyWithLibcDebugSyms decorator was added to all heap-related commands. This decorator makes the heuristic method unnecessary as the 'top' member of a heap's arena will always be accessible.
Remove the get_top_chunk_addr() function as it only uses the heuristic approach. Use symbols in top_chunk() and vis_heap_chunks() rather than heuristics. Use get_arena_for_chunk() in vis_heap_chunks() to find an arena, originally this used get_arena() with no arguments which always returned the main arena. Fix get_arena_for_chunk(), which misidentified a chunk as a malloc_state struct rather than a malloc_chunk struct, and use read_chunk() rather than memory.poi() which didn't account for the size/mchunk_size symbols used in different versions of GLIBC.
* Replace malloc initialization heuristics
Use the __libc_malloc_initialized symbol to determine whether malloc has been initialized rather than checking whether global_max_fast has been populated. This has the advantage of being compatible with older versions of GLIBC that don't have a global_max_fast symbol.
* Update pwndbg/heap/ptmalloc.py
Co-Authored-By: Paweł Płatek <e2.8a.95@gmail.com>
Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
Co-authored-by: Paweł Płatek <e2.8a.95@gmail.com>
* Configure context output per section
* banner respects width of target output
* Fixed context output help
* ui.banner optionaly force a width
* Allow python functions as context output
* Use is for StdOutput type comparison
Co-Authored-By: Disconnect3d <dominik.b.czarnota@gmail.com>
* Use list-function as initial value of default dict
Co-Authored-By: Disconnect3d <dominik.b.czarnota@gmail.com>
* Append final context linebreak only on stdout
* Documented context splitting feature
* Option to hide context section banners
* Option to set width per context section (currently only banner)
* Splitting screenshot
* Fixed empty lines when not clearing
* Fixed auto banner width (using stdin as before instead of stdout)
Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
* command: support alternatives including sub command wrapper like pwn
Additionally speed up the checksec logic by removing the --version
check. Simply try to shell out and use the first working option variant
as we can't easily detect the different available alternatives in a
bulletproof way.
This implementation allows to use the sub command wrapper 'pwn' to call
checksec in case pwntools has been installed using --only-use-pwn-command
To unconditionally unify the usage, the functions cmd attribute stores
the base command to execute in form of a list that can be used to
concatenate an array of options against it and pass the final list to
call_cmd
* checksec: allow a third option variant by only passing the file target
Lets try a third available version of checksec as the lowest order
variant in our cascade that works by only passing the target file
without additional specifier.
* vmmap: add QEMU kernel support
This feature uses GDB's `monitor info mem` to fetch
memory pages for QEMU in kernel mode.
However, at least on QEMU 3.0.0 on `qemu-system-x86_64`
the `monitor info mem` command returns memory pages without the
`executable` permission bit, so for now we assume that all pages are executable.
The `monitor info mem` works only in QEMU kernel mode
and in QEMU-user it does:
```
(gdb) monitor info mem
Target does not support this command.
```
* Update vmmap command docs
* Use monitor_info_mem only on X86/X64
* monitor_info_mem: fix comment about executable perm
* Update vmmap help
Modern maintained checksec >2.0 requires to use "--file=arg" which
we try to detect. The command call is cached anyway so lets try
to find out what version is running.
In case we can't find a verbose variant, we just fall back to the
common old fessioned "--file arg" variant as if nothing has happened.
Fixes#662
* Make size_t and ssize_t the correct sizes, and actually use them for inthook. Fix for #669 along with other issues.
* elif, pointer size support message
This commit adds support for xPSR to be used instead of cPSR on Cortex-M
ARMs. Prior to this commit, pwndbg would crash when attached to a
Cortex-M core. This commit adds a new internal arch "armcm" to describe
Cortex-M ARMs.
Closes#542, fixes the second issue in #264
* Fix source code display
Fixes and simplifies source code display in `context code`. The
reasoning below.
---
It turns out that we determine the source code line for known code in a
tricky and buggy way. It is wrong when we are deep inside many calls and
we go to upper frame via e.g. `up` and then display the `context code`.
And this also occurs after applying the PR #637 before/after this fix.
We also do `except` all exceptions happening in the source code
retrieval which makes it hard to spot potential bugs in this code path.
This commit removes the `except` path and checks for particular edge
cases where we wouldn't have sources available.
---
Also note the `FileNotFoundError` path - in this case the debug symbols
have a source file path there, but it hasn't been found by us. It might
be because the program (or anything else) removed it OR maybe we debug
remotely etc (not sure if this is the case).
This being said, we could potentially inform the users about that BUT...
GDB already does that by itself - maybe in a bit vague way, as it does
it before us displaying the context e.g.:
```
pwndbg> r
Starting program: /home/dc/pwndbg/a.out
Program received signal SIGSEGV, Segmentation fault.
0x000055555555460a in foo () at ./a.c:2
2 ./a.c: No such file or directory.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
// (the rest of the context here)
```
But I am fine with that for now - and I am not sure if we could even
suppress this warning (oh, maybe this string comes to us into prompt
hook/event? I don't know)
* Fix wrong code line if source startswith newlines
For some reason the `pygments.hightlight` remove newlines at start.
We need to preserve them in order to keep proper code lines.
* Use lexer's stripnl=False
TLDR:
1. We read registers from `newest_frame` instead of `selected_frame` for GDB>=7.9.
2. We have two ways to fetch registers - `regs.__getitem__` and
`regs.__getattr__` - one of them didn't invalidate cache and so after
fixing 1st, we still shown the old register after switching frames.
GDB's `up` and `down` commands trigger internal notification about
changed frame. It does not happen for `gdb.Frame.select()` which we use
in our own overrides for `up` and `down` commands.
Because of that, the `list` GDB command does not show proper source code
lines.
This can be worked around by firing `frame` command and this is what
this workaround/PR adds.
This bug has also been reported to GDB bugzilla at
https://sourceware.org/bugzilla/show_bug.cgi?id=24534
- fixed incorrect docs of dumpargs command (`--all` vs `--force`)
- dumpargs command does not require `--force` now if we are not on a
call instruction
* Bin annotations
* ASCII representation
* Addresses formatted w/o ':' (ease terminal copy/paste)
* Implicit addr support (pwndbg> vis_heap_chunks)
* Use top_chunk as sanity end-of-heap check, making it easier to use
during non-top_chunk heap corruption
* Added --naive (-n) to disable end-of-heap check
* Swapped arguments:
pwndbg> vis_heap_chunks addr count -> vis_heap_chunks count addr
Arguably, desired number of chunks v. heap addr is more readily
available
* Use ArgparsedCommand for commands/gdbinit.py
* Use ArgparsedCommand for commands/gdbinit.py
* Use ArgparsedCommand for commands/dt.py
* Use ArgparsedCommand for commands/defcon.py. (Not sure what the other one command in there did, didn't bother making it argparsed
* Use ArgparsedCommand for commands/context.py
* Use argparsed command for commands/argv.py
* Use ArgparsedCommand for commands/heap.py
* Use ArgparsedCommand for commands/ida.py
* Use ArgparsedCommand for commands/misc.py
* Use ArgparsedCommand for commands/next.py and commands/nearpc.py
* Use ArgparsedCommand for commands/peda.py
* Use ArgparsedCommand for commands/pie.py
* Use ArgparsedCommand for commands/procinfo.py
* Use ArgparsedCommand for commands/reload.py
* Use ArgparsedCommand for commands/rop.py
* Use ArgparsedCommand for commands/segments.py
* Use ArgparsedCommand for commands/start.py
* Use ArgparsedCommand for commands/telescope.py
* Use ArgparsedCommand for commands/version.py
* Use ArgparsedCommand for commands/vmmap.py
* Use ArgparsedCommand for commands/windbg.py
* Use ArgparsedCommand for commands/xor.py
* Use ArgparsedCommand for commands/windbg.py
* Fix isort
* Fixes#538 - breakrva on symlink targets
Fixes a bug with `breakrva` and `brva` commands and adds some more
explanation on how certain things works:
* `info auxv` or to be more specific: AUXV's `ET_EXECFN` holds path to
the executable, but if it is a symlink, it is not dereferenced
* because of that we need to call `readlink` in `get_exe_name` in pie.py
* Fix isort
* Add option to redirect context output to other tty or files
The output of context/dashboard can be now be redirected with
"set context-output /dev/pts/x" to everything wich python can open and
offers a file like "write".
* Sorted imports correctly (fixing pwndbg CI)
* Enhance remote QEMU targets debugging experience
- improve vmmap command help and inform user that the result might not
be accurate for QEMU targets
- updating stack pages (`pwndbg.stack.stacks`): skip detecting stack pages if SP is 0 (this lead to displaying memory page that started at -0x1000)
- `pwndbg.vmmap.find` - don't skip addresses below `pwndbg.memory.MMAP_MIN_ADDR` -
this function is used by `pwndbg.color.memory.get` which is used by
`vmmap` command - because we skipped addresses - a memory page starting
below that address wasn't colored on `vmmap` display
- memory pages found with exploration will now display with `<explored>` name in `vmmap`
- skip `proc_pid_maps` for QEMU kernel targets too (this was bug-prone
as QEMU targets have 42000 pid returned by GDB and we potentially tried adding
memory pages from another process, which luckily usually wasn't there)
* Update pwndbg/vmmap.py
TLDR: when context has been displayed the higlighted code is cached; if we change the pygmets style, displaying context again does not show the new style. This commit fixes this issue by resetting the memoized/cached highlighted code.
* Fix tcache and support it on targets w/o -lpthread
Short summary:
* fixes tcache having wrong address
* adds heuristic to retrieve tcache address when binary is compiled w/o
-lpthread (may not work on glibc's other than 2.27)
* fixes `pwndbg.symbol.address` as it could return offsets instead of
an address
---
Long description below.
This commit fixes tcache: we used the address of &tcache instead of
tcache for dereferencing the struct. This can be observed with:
```
pwndbg> p *tcache
$8 = {
counts = '\000' <repeats 63 times>,
entries = {0x0 <repeats 64 times>}
}
pwndbg> tcache
{
counts = "\020`uUUU\000\000\000\000\000\000\000\000\000\000"...,
entries = {0x0, 0x0, 0x7ffff7fd7740, 0x7ffff7fd80a0, 0x7ffff7fd7740, 0x1, 0x0, 0x7025de0aec8a0300, 0x236a7550e4a6104e, 0x0 <repeats 55 times>}
}
```
It also adds possibility to retrieve tcache information from targets
that are compiled without -lpthread [-pthread].
**NOTE: This is experimental and may not work across different glibc
versions. It was tested on Ubuntu 18.04 on 2.27 glibc.**
This is because we get tcache pointer by making an assumption that it
will lie 0x10 bytes before one of the addresses that points to
&main_arena.
It also fixes `pwndbg.symbol.address`'s `info address` path when it
returned addresses that were out of memory maps due to the fact GDB may
return a string containing an offset instead of an address. E.g.:
```
pwndbg> info address tcache
Symbol "tcache" is a thread-local variable at offset 0x40 in the thread-local storage for `/lib/x86_64-linux-gnu/libc.so.6'.
```
* Fix tcache retrieval heuristic
* Check if override built-in command
* Abort on non-whitelisted command override
* Fixes according to PR discussion
* Check if override built-in command
* Abort on non-whitelisted command override
* Fixes according to PR discussion
* Clearer parsing of gdb output
Co-Authored-By: ZetaTwo <calle.svensson@zeta-two.com>
Removes an exception in the tcache/bins command where the exception would be printed as well as an error message.
This is purely a UI fix as described in Issue #535 (https://github.com/pwndbg/pwndbg/issues/535)
* add bugreport cmd
* add newline, fix imports ordering
* fix stuff in bugreport
* add info about bugreport to exception handler
* open browser with body
* isort fix
* bugreport change arg name
* Update exception.py
* fix probeleak command (message.warning -> warn) and small fixes for it
* add warning, change format to %
* fix when read less data than count
* add max_distance arg for probeleak
* add description, change error msg, colorize address