* Don't catch the error of the heap commands for developers
* Use `pwndbg.config` and re-raise the error
See https://github.com/pwndbg/pwndbg/pull/1270#discussion_r992209956
* Update pwndbg/commands/__init__.py
Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
* Move symbol.py to gdblib
* Renamed private methods
* Renamed pwndbg.symbol to pwndbg.gdblib.symbol
* Cleanup symbol.py
* Fix lint issues
* Handle tls error on symbol lookup
* Fix merge conflicts
* Remove old way of looking up symbols
* Enhance the error handling of the heap command
* Add a new method: `can_be_resolved()` to heap classes to check whether we can resolve the heap after the heap is initialized.
* Add a new function: `get_got_plt_address()` to `pwndbg.glibc`, by doing this, we can determine the location of the symbols without `_IO_list_all` by parsing the output of `info files`.
* Add a new subclass of Exception: `SymbolUnresolvableError` to handle the error when we can't resolve some symbols.
* If we didn't set the GLIBC version manually, we won't get the unnecessary Python error from this now, instead, we tell the user how to set it.
* If we didn't have enough information to resolve some symbols, we show which symbol we lack and tell the user how to set it manually instead of just executing it and showing a Python error.
* Avoid getting the wrong heap config
* List the symbols manually instead of using `locals()`
* Avoid the extra function call by `can_be_resolved`
* Enhance the error handling when finding TLS (#1237)
* Enhance the error handling for more cases
* Add support to use `gdb.lookup_static_symbol` in `pwndbg.symbol`
* Enhance the strategy when handling the heap-related symbols
* Use `pwndbg.symbol.static_linkage_symbol_address()` to get the address of the symbol first
e.g. Let's say we have a file called `FILENAME.c`:
```
void *main_arena = 0xdeadbeaf;
int main(){
free(malloc(0x20));
return 0;
}
```
If we compiled it with `gcc FILENAME.c -g`, the old heap command will fail because it thinks `main_arena` is this 0xdeadbeaf `main_arena`, not the "real" `main_arena` in GLIBC.
With this commit, it should work without this issue.
* Revert "Enhance the error handling when finding TLS (#1237)"
This reverts commit 7d2d1ae6b6.
* Enhance the error handling when finding TLS (#1237)
* Catch the error when reading the address of the static linkage symbol
* Bug fix for `thread_cache` under heuristic mode
* Bug fix for `static_linkage_symbol_address()`
* If `gdb.lookup_static_symbol(symbol)` is None, it will cause the
error.
* Use new code after refactoring
This commit enhances the heap commands UX for statically linked binaries
and removes typeinfo module bloat.
The typeinfo module had this typeinfo.load function that was looking up a given type.
If it didn't find the type, it fallbacked to compiling many many system
headers in order to add a symbol for a given type into the program. This was
supposed to be used for missing glibc malloc symbols like malloc_chunk.
However, the exact reason it was used: the struct malloc_chunk was never
defined in a header file and was always defined in a malloc.c or another
.c file in glibc sources.
Another place the typeinfo.load logic of compiling headers was/is used
is the `dt` command, which is a windbg alias for getting struct layout
type information, e.g.:
```
pwndbg> dt 'struct malloc_chunk'
struct malloc_chunk
+0x0000 mchunk_prev_size : size_t
+0x0008 mchunk_size : size_t
+0x0010 fd : struct malloc_chunk *
+0x0018 bk : struct malloc_chunk *
+0x0020 fd_nextsize : struct malloc_chunk *
+0x0028 bk_nextsize : struct malloc_chunk *
pwndbg>
```
However, the whole big issue with typeinfo.load compilation of headers
was that most of the time it didn't work because e.g. some headers
defined in other paths were missing or that two different headers used
the same struct/function name and the compilation failed.
Since this logic almost never gave good results, I am removing it.
Regarding UX for statically linked binaries: we use `info dll` command
to see if a binary is statically linked. While this method is not
robust, as it may give us wrong results if the statically linked binary
used `dlopen(...)` it is probably good enough.
Now, if a heap related command is executed on statically linked binaries, it
will inform the user and set the resolving of libc heap symbols via
heuristics. Then, it also says to the user they have to set the glibc
version and re-run the command.
* ArgparsedCommand: fix `help cmd` and `cmd --help` behavior
Before this commit there was always a mismatch of what was displayed
when the user did `<command> --help` or `help <command>`.
With those changes, we fetch the help string from the argument parser
and render it as the command object's `self.__doc__`, so that it will be
displayed during `help <command>`.
Previously, we only displayed the command description during help.
* fix the pwndbg [filter] command that was broken in previous commit
This commit cleans up the commands/__init__.py a bit by removing the
`QuietSloppyParsedCommand` that we do not use anymore.
The last command that used it was `brva` which was just an alias for
`breakrva`, so now we just set it as an alias using the
`ArgparsedCommand` as it should be done.
* Add support to use heap commands without debug symbols
* Fix a possible bugs when getting heap boundaries via heuristic
See https://github.com/pwndbg/pwndbg/pull/1029#issuecomment-1189841299
* Fix typo causing issues in `c_malloc_par_2_25`
See https://github.com/pwndbg/pwndbg/pull/1029#issuecomment-1189841299
* Fix a bug for `tcache_perthread_struct` and refactor some codes in `structs.py`
* The bug: `tcache_perthread_struct` for GLIBC < 2.30 is using `char` instead of `uint16_t` for `counts` field
* Fix some bugs about handling `thread_arena` and `tcache` with multithreaded
* Re-initialize the heap when the process stop or the file changed
By doing this, we can attach to another architecture in GDB without any bugs.
* Add guard code for unsupported architectures
* Support heuristic for arm and aarch64
Note: thread_arena and thread_cache for arm still can not work
* Update .pylintrc
* Ignore `import-error` error for `import gdb`
* Ignore `no-member` error for `pwndbg.typeinfo.*`, because most of its members are dynamically generated.
* Ignore `protected-access` warning for `_fields_`, `_type_`, `_length_`, because ctypes don't have other ways to access them.
* Refactor some code and comment to fit pep8 and lint check
* Add a feature to enable users set symbol addresses manually
For example, by using `set main_arena 0xdeadbeaf`, pwndbg will try to find main_arena at 0xdeadbeaf when using heuristic
* Use `__errno_location` to find TLS base for arm
By doing this, we can get `thread_arena` and `tcache` address
* Block other thread before `__errno_location()`
* Fix a bug for arm32 and a typo-caused bug
* Some wrong field names inside `c_heap_info` may cause some bugs in the future if we want to access it
* `pad` size of `heap_info` for arm32 is 0 byte, only i386 is 8 bytes, so I fixed it in a hard-coded way temporary
* Fix#1044 related issues
* Refactor the code about heap related config
* Use `int(address_str, 0)` to auto determine the format (https://github.com/pwndbg/pwndbg/pull/1029#discussion_r939569382)
* Use `OnlyWithResolvedHeapSyms` instead of `OnlyWithLibcDebugSyms` (https://github.com/pwndbg/pwndbg/pull/1029#discussion_r939568687)
* Use `resolve-heap-via-heuristic` instead of `resolve-via-heuristic` (https://github.com/pwndbg/pwndbg/pull/1029#discussion_r939569076)
* Update the description of `resolve-heap-via-heuristic` config (https://github.com/pwndbg/pwndbg/pull/1029#discussion_r939569069)
* Move heap related config into `heap` scope, and add a new command, `heap_config`, to show the config in that scope (https://github.com/pwndbg/pwndbg/pull/1029#discussion_r939569260)
* Refactor code about the config of heap related symbols
* Fix the logic when thread_arena is not found
* Use errno trick as a fallback for i386 and x86-64
* Update pwndbg/heap/ptmalloc.py
Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
* remove py2 coding notations from files
* remove six package use and replace with proper py3 code
* remove py2 futures use
* replace unicode string literals with string literals
* remove python2 urlparse import in favor of python3 urllib.parse
* keep ida_script in py2 version
* remove hashbang python lines as the files are never ran directly
When we moved to argparse command parsing we introduced `gdb_sloppy_parse` which wasn't perfect: e.g. for `gdb.parse_and_eval("__libc_start_main")` would return a `gdb.Value()` whose `.type.name` was `long long`.
As a result when code that used `gdb_sloppy_parse` then casted the result to `int(gdb_value)` it crashed because for some reason GDB errored.
This commit fixes the issues related to it by adding `AddressExpr` and `HexOrAddressExpr` functions.
It also adds tests for some of the windbg compatibility commands and fixes some nifty details here and there.
* 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.
* 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>
* Bug fix: global_max_fast symbol contains the actual value not the address
* heap: return from find_fake_fast if allocator is not initialized
* Bug fix: address method should return the symbol address if it's an intergral symbols
* Revert commit c35152df1c
* add OnlyWhenHeapIsInitialized decorator
* Update heap.py
* hexdump: adjust shown offset from src while repeating
* nearpc: make command repeatable to show further instructions
The pc gets adjusted to the last instructions address making it
visually easy to follow where to continue reading the assembly.
This also forwards repeating of emulate() and pdisass()
* telescope: make command repeatable with adjusted offset from src
This also forwards stack() to be repeatable.
Since the python2 use `from __future__ import unicode_literals`, so the string literals will be `unicode` type in python2.
Use `six.string_types` in `isinstance()` instead of using `str` type.
* Clean up some unnecessary closures in pwndbg.commands
* A bit of cleanup, and a change to split_args
* Move SystemExit except block
* Actually fix command crashes
* A bit of docs
* Attempt to make exception handling a little bit better
* More better errors
* Fix docs
* Simplify command exception debugging and make stdio work correctly
* Make isort happy
* Reorganize exception handler, add default case
* Fix print statement
* Attempt to use ipdb where available
* Sort requirements and add ipdb
* Only use pwndbg.stdio in the exception handler
* Documentation, hook pdb.set_trace()
* Do not require ipdb
* Remove import loop, fix accidental call, set python print-stack
* Use the correct values for print-stack
* Use pdb.Pdb for better set_trace()
* Fix start, entry commands without file loaded in gdb
Both `entry` and `start` commands fails when there is no file loaded in gdb:
```
$ gdb -q
Loaded 106 commands. Type pwndbg [filter] for a list.
pwndbg> entry
Traceback (most recent call last):
File "/home/dc/installed/pwndbg/pwndbg/commands/__init__.py", line 57, in __call__
return self.function(*args, **kwargs)
File "/home/dc/installed/pwndbg/pwndbg/commands/start.py", line 67, in entry
gdb.execute(run, from_tty=False)
gdb.error: No executable file specified.
Use the "file" or "exec-file" command.
```
The patch fixes those issues by introducing `pwndbg.commands.OnlyWithFile` decorator.
* Use pwndbg.commands.OnlyWithFile in rop* commands
* Use pwndbg.commands.OnlyWithFile in elf*, *plt commands
Also refactored the file a bit.
* Use pwndbg.commands.OnlyWithFile in r2 command
* Use pwndbg.commands.OnlyWithFile in errno command
* Use pwndbg.commands.OnlyWithFile in checksec command
* Remove redundant file check in elf.py
* Make save_ida command available only with ida
When there is no file and ida an excetion is thrown:
```
pwndbg> save_ida
Traceback (most recent call last):
File "/home/dc/installed/pwndbg/pwndbg/ida.py", line 57, in init_ida_rpc_client
_ida.here()
File "/usr/lib/python3.6/xmlrpc/client.py", line 1112, in __call__
return self.__send(self.__name, args)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1452, in __request
verbose=self.__verbose
File "/usr/lib/python3.6/xmlrpc/client.py", line 1154, in request
return self.single_request(host, handler, request_body, verbose)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1166, in single_request
http_conn = self.send_request(host, handler, request_body, verbose)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1279, in send_request
self.send_content(connection, request_body)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1309, in send_content
connection.endheaders(request_body)
File "/usr/lib/python3.6/http/client.py", line 1234, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/lib/python3.6/http/client.py", line 1026, in _send_output
self.send(msg)
File "/usr/lib/python3.6/http/client.py", line 964, in send
self.connect()
File "/usr/lib/python3.6/http/client.py", line 936, in connect
(self.host,self.port), self.timeout, self.source_address)
File "/usr/lib/python3.6/socket.py", line 704, in create_connection
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
File "/usr/lib/python3.6/socket.py", line 743, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
OSError: Int or String expected
```