I am trying to use VSCode debugger for a complex application zsim (https://github.com/s5z/zsim). GDB works fine on it but I do not know how to set launch.json to support zsim debugging in VSCode.
zsim is a simulator based on intel PIN (https://software.intel.com/sites/landingpage/pintool/docs/81205/Pin/html/index.html#DEBUGGING). As the document says, it has several distinct approaches for debugging. When in GDB console, I append "-pause_tool 5" to PIN command to force whole application to stop temporarily and output program's PID and additional symbol location for you to manually add. During the five seconds, I have to launch gdb, attach that PID and execute add-symbol-file provided by PIN.
Fortunately zsim wraps up all arguments in gdb to form one command looks similar to this: "gdb -p 15326 -ex set confirm off -ex add-symbol-file /build/debug/libzsim.so 0x7ffff5db17a0 -s .data 0x7ffff642ab80 -s .bss 0x7ffff642c540 -ex handle SIGTRAP nostop noprint -ex set confirm on -ex c". I tried to modify my launch.json to the following:
"request": "attach",
"processId": "15326",
It does not work. When I select the correct PID, VSCode turns to debug mode but nothing happens. Then after 5 seconds ZSim starts simulating as it is not being attached. Does someone know why this happens?
Related
I debug a remote Linux process with GdbServer. And I want to put a breakpoint in some function.
The problem is that this process use ASLR so each time that process load in another address. I can watch in /proc/PID/maps the base address of the process and calculate where the function is located but this is tedious.
Is there a way to put break point with GDB in address the rebase? So the GDB will automatically calculate the rebase of the process?
Is there a way to put break point
All the ways you can put a breakpoint in GDB are documented here.
You want something like $image_base(myprogram) + image_offset, which is not a supported address location.
What you could do is write a shell wrapper which computes the desired address and invokes GDB. Something along the lines of:
#/bin/bash
PID="$1" # process we'll attach.
IMAGE_BASE="0x$(grep myprogram /proc/$PID/maps | sed -e 's/-.*//' -eq)"
IMAGE_OFFSET=0x1234 # use whatever offset corresponds to your function
exec gdb -p "$PID" -ex "break *($IMAGE_BASE+$IMAGE_OFFSET)"
I'm new to exploit development and looking for advice.
My question is: how can I keep giving input from one terminal and debug my program on another?
I usually use gdb.debug from pwntools when having graphical interface, but now I can only SSH remote to the machine which runs the binary, which means gdb.debug cannot create a new terminal.
I saw a video of a demonstration doing that technique in VIM. How can I achieve that?
gdb.debug should still work if you're using SSH as long as you set context.terminal to the right value (e.g. tmux).
How to use pwnlib.gdb
Here's a copy and paste of a response to a similar question:
You can use the pwnlib.gdb to interface with gdb.
You can use the gdb.attach() function:
From the docs:
bash = process('bash')
# Attach the debugger
gdb.attach(bash, '''
set follow-fork-mode child
break execve
continue
''')
# Interact with the process
bash.sendline('whoami')
or you can use gdb.debug():
# Create a new process, and stop it at 'main'
io = gdb.debug('bash', '''
# Wait until we hit the main executable's entry point
break _start
continue
# Now set breakpoint on shared library routines
break malloc
break free
continue
''')
# Send a command to Bash
io.sendline("echo hello")
# Interact with the process
io.interactive()
The pwntools template contains code to get you started with debugging with gdb. You can create the pwntools template by running pwn template ./binary_name > template.py. Then you have to add the GDB arg when you run template.py to debug: ./template.py GDB.
If you get [ERROR] Could not find a terminal binary to use., you might need to set context.terminal before you use gdb.
If you're using tmux, the following will automatically open up a gdb debugging session in a new horizontally split window:
context.terminal = ["tmux", "splitw", "-h"]
And to split the screen with the new gdb session window vertically:
context.terminal = ["tmux", "splitw", "-v"]
(To use tmux, install tmux on your machine, and then just type tmux to start it. Then type python template.py GDB.
If none of the above works, then you can always just start your script, use ps aux, find the PID, and then use gdb -p PID to attach to the running process.
Vim Explanation
You don't need to use vim to use pwntools's gdb features like the guy did in the video you linked, but here's an explanation on what he did (vim's also a nice tool regardless):
While editing his pwn script in vim, the guy first executed the following command:
:!./%
: enters command mode in vim
! executes a shell command
% is basically the name of the file you're currently editing in vim
So if your exploit script was named template.py running :!./% in vim would be the same as running ./template.py in your terminal. This just runs the exploit and enters interactive mode.
It's just a way shortcut to execute your script in vim.
Later, the guy also uses :!./% GDB to actually launch the pwntools gdb session. It's the same thing as running python template.py GDB.
i run my program in background as follows:
nohup ./program -c config.cfg &
So i saw segmentation fault in my program and decided to run my program with gdb. My program has some infinite loops and may take some hours to deal with a segmentation fault error, again.
So i want to run the program on background.
How should i pass the gdb arguments to nohup?
I tried my hand at getting the gdb debugger to run in the background, but it's designed to be an interactive tool. I think what you are looking for here is a screen. A screen allows you to background the entire shell session by creating a virtual terminal.
Create the screen instance:
me#mybox$ screen -S my_screen_name
Then run:
me#mybox$ gdb --args ./program -c config.cfg
Once you are in the screen, Ctrl-A-D will detach the screen so you can go about your business and it will keep running.
To reattach:
me#mybox$ screen -r my_screen_name
Once you are done, type Ctrl-D in the screen to terminate the screen. For more help with screens, see man screen.
I've established a build process that makes binaries and then separates the debug info from them (build-ids are enabled).
The build can also generate the .gdbinit files with the lines like set debug-file-directory <dir>, so the debugger can find them (there are lots of executables and libraries in the project).
But when I run $ gdb myprogram, gdb can't find the symbols. I have to do (gdb) file myprogram to redo the search for the debug-symbols file. It seems that .gdbinit is executed after opening myprogram.
How to make it automatic?
Basically, .gdbinit file is used to setup debugging environment (add aliases for long commands, load custom commands, setup print modes, etc. ), not a particular debugging session.
Taking a look at gdb startup order and considering that home .gdbinit works ok, it cannot be achieved with local .gdbinit file (order of operations should be set debug-file-directory, file). I think you can modify your build/debug process for using gdb wrapper script with gdb command script (the same as .gdbinit but call it start.gdb for example to avoid confusion):
gdb_x:
#!/bin/sh
gdb -x ./start.gdb "$#"
start.gdb:
# this file is generated for .. by ...
set debug-file-directory <>
set debug-file-directory <>
Or, as a workaround, if you can bare with the fact that commands will run twice:
gdb -x ./.gdbinit <>
which can be avoided with (and deserves again wrapper script):
gdb -iex "set auto-load local-gdbinit off" -x ./.gdbinit <>
I made a memory error that is quite difficult to debug, happening every once in a few command-line runs, each taking about two hours to complete. Because of that, I thought it could be a good idea to create logs like this:
while true; do
valgrind ./command 2>&1 | tee command
grep -q Invalid && break
done
The problem is that my debug logs and stack traces produced by Valgrind aren't enough, so I decided to add --vgdb-error=0 to the command line. Unfortunately, since Valgrind now adds a breakpoint on startup, I need to run the following:
$ gdb ./command
...gdb init string follows...
(gdb) target remote | /usr/lib/valgrind/../../bin/vgdb
Remote debugging using | /usr/lib/valgrind/../../bin/vgdb
relaying data between gdb and process 4361
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
[Switching to Thread 4361]
0x04000840 in ?? () from /lib/ld-linux.so.2
(gdb) continue
Continuing.
How can I script the process so that either Valgrind does not break on startup or a script keeps attaching to vgdb processes and tell them to continue until one of the processes completes abnormally?
The argument to --vgdb-error is the number of errors to expect before valgrind stops the program and attaches the debugger. If you set it to 0, then it will stop immediately before running your program. You want --vgdb-error=1, which will run to the first error then stop. Then you can attach a debugger.