I am trying to spawn a shell with some shellcode. The payload is in the program itself, however, when I run then program individually I get a segmentation fault, but when running in gdb, my shell opens.
Can someone point out what the problem might be?
MrMox#ubuntu:~/folder$ ./a.out h h
Segmentation fault (core dumped)
MrMox#ubuntu:~/folder$ gdb -q a.out
Reading symbols from /home/folder/a.out...done.
(gdb) run h h
Starting program: /home/folder/a.out h h
process 22119 is executing new program: /bin/dash
$
$
what the problem might be
First, since you do get a core, you could just look in it to understand the crash.
Second, GDB disables address randomization (ASLR) by default (to make it easier for you to debug, so everything stays in one place), whereas running a.out outside of GDB likely has full ASLR, which possibly explains the different behavior of a.out with and without GDB.
You can disable ASLR globally:
sudo -c "echo 0 > /proc/sys/kernel/randomize_va_space"
Or you can enable randomization within GDB:
(gdb) set disable-randomization off
Related
I am debugging in a recompile-debug cycle that looks as follows:
Compile binary
Run debugger gdb prog
Find an error and fix the source
Exit debugger with pressing ctrl+d or typing quit
I would like to add Valgrind in the workflow to break as soon as I faced incorrect out-of-range memory read or write. I found that if I follow the officially documented process of running Valgrind with gdb I have to perform a lot more time-consuming steps.
Compile binary
Run valgrind valgrind --vgdb=yes --vgdb-error=0 prog
Open new terminal window and type gdb prog
Run target remote | vgdb (or, even worse, copy-paste command for connection printed in valgrind window if I am running multiple debug sessions)
Find an error and fix the source
Exit debugger
Kill application with valgrind process with kill -9 (because Valgrind doesn't stops it on gdb exit)
How I can automate these 3 extra steps? Ideally, I would expect to have a command like mygdb as a drop-in replacement for gdb that runs Valgrind under the hood, maybe debug slower, but breaks as soon as Valgrind detects an error.
--vgdb-error=0 indicates to valgrind to stop before it starts executing your program, so that you can connect with GDB and e.g. put breakpoints.
But if you only want to debug once an error is detected, rather give --vgdb-error=1.
With this, as long as valgrind reports no error, there is no need to do the 3 steps in bold, as valgrind will run your program till the end and exit.
When valgrind stops when encountering an error, you have to start a gdb.
You could write a shell script to automate part of the other commands e.g.
gdb -ex 'target remote | vgdb'
This script can extract the vgdb command from a log file output or any other way.
You could also define in your .gdbinit a command such as
define vquit
kill
quit
end
and use vquit instead of quit.
You can also define a gdb command to directly start your application under valgrind and connect gdb to it, e.g. something like:
define vrun
shell valgrind --vgdb-error=0 $arg0 &
target remote | vgdb --wait=10
continue
end
and then inside gdb, you can do:
(gdb) vrun your_application
How I can automate these 3 extra steps?
Not a direct answer to your question, but your entire approach is likely wrong.
You should not use the debugger to tell you about bugs; use unit tests instead. Your cycle should be make && make check.
It also helps to write the test before implementing any new functionality (see test-driven development). The test will fail, and then you'll make it succeed by implementing the new feature.
In addition, you should get into the habit of running all of your tests with the Address and Memory Sanitizers (which together catch many more bugs than valgrind does).
Finally, valgrind report itself usually provides sufficient info to understand the bug. Valgrind's integration with GDB is there for rare cases where the error report is hard to understand without looking at the values of locals, parameters, etc.
I am debugging a program using valgrind and gdb. However I terminate those debugging sessions in a barbaric way… Is it really how it is meant to be done ?
Setting up the debugging session
Following the instructions from the official valgrind website I do the following to run the program :
I run valgrind by entering
valgrind --tool=memcheck --vgdb=yes --vgdb-error=0 ./prgm.run
From another terminal session, I run gdb using
gdb ./prgm.run
I connect gdb to valgrind
(gdb) target remote | vgdb
I run the program from gdb CLI
(gdb) c
So far so good : the program runs in both terminals (the one used for valgrind and the one used for gdb). Then valgrind finds an error, for instance an invalid read, and the program execution is paused.
Terminating the session
At that point, I want to fiddle with my code : perhaps fix something or comment/uncomment stuff from the program's source. As a consequence, the program needs to be compiled anew. A new binary is generated. Following that, I want to stop the on-going valgrind and gdb sessions (that were using the old binary) and start new valgrind and gdb sessions that will use the new binary.
To stop an on-going session, I quit gdb
(gdb) q
Sometimes valgrind notices that gdb is no longer there and quits too. But other times valgrind keeps going even-though no gdb process exist anymore…
In that case I kill the "memcheck-amd64-" process corresponding to my valgrind session. The number of that process is indicated in the valgrind messages e.g. 16195 in ==16195== Invalid read of size 8).
kill -9 16195
A regular kill is not enough : I need to use the -9 option.
I don't think invoking kill -9 is how it is meant to be done… Am I missing something ?
valgrind version : 3.10.1
gdb version : 7.7.1
you can also use the comand
(gdb)monitor v.kill
it was listed on monitor help on gdb.
Just use kill command or simply
k
to get rid of asking use set confirm off in .gdbinit file
The previous answers did not work for me, so I found this which did the trick.
(gdb) info inferiors Should list all inferiors in gdb session, find the one with 'remote target' as its name, take note of the number on the left of it (will be 1 if no other inferiors running in gdb)
(gdb) kill inferiors <number> Replace <number> with inferior number.
(gdb) quit
An OS X binary runs into a segfault when invoked under Yosemite (prints "Segmentation fault: 11" on stderr), but when invoked using lldb, no segfault occurs, and the program ends with error code 0.
Do you have any idea what the reason might be, that the segfault doesn't occur when using lldb? Is there any way to trigger it there (and stop execution when it occurs, so some debugging is possible)?
Try running your program separately and attaching to it. If your binary is called a.out, you would use the process attach --waitfor command like this:
term1$ lldb
(lldb) pr a -w a.out
term2$ a.out
lldb will poll the process table repeatedly until a.out starts up - when it sees the process, it will attach to it. In the lldb terminal, c (continue) the process execution.
Alternatively, you may have a crash report from your process segfaulting in ~/Library/Logs/DiagnosticReports/. This will show you the backtrace at the point where your binary crashed. You may also want to open Console.app and see if any messages are being logged to console at the point where it crashes.
I am new to qemu and I read that it allows for a singlestep mode emulation. This is helpful because I am trying to dump some addresses of the physical ram every cycle. Unfortunately, the qemu documentation is very bad. I know how to enable the singlestep mode from the qemu monitor but I have no idea where to put the code that I want to execute at every step. Does anyone have any information about this?
You can use gdb to attach to the guest with the
--gdb tcp::
option to qemu and then use
$ gdb <binary>
(gdb) symbol-file <sym file>
(gdb) target remote <host>:<port number>
(gdb) b <function>
(gdb) c
'b' sets a breakpoint. 'n' 's' 'i' can be used to step though the code. Entering "info" in gdb mode will show more info
http://www.xenproject.org/help/questions-and-answers/problem-with-vga-passthrough.html
From above link is the command line option for entering singlestep modes for QEMU. Next is to get the source code for QEMU (http://wiki.qemu.org/Download)
The function monitor.c:do_singlestep(Monitor *mon, const QDict *qdict)
just simply set a flag "singlestep". Note this is not the same as the "singlestep_enabled", which is to emulate hardware singlestep emulation.
(global var is declared in vl.c).
Now look into all the functions in targt-i386/translate.c - where "singlestep" flag are tested are:
if (singlestep) {
gen_jmp_im(pc_ptr - dc->cs_base);
gen_eob(dc);
break;
}
This is the place where the binaries are either executed (or "translated" to be more exact), or otherwise hardware exception raised and handler (for example). If there is any behavior you want to modify perhaps u can try here?
From Ubuntu Documentation
-singlestep
Run the emulation in single step mode.
Is there any gcc option I can set that will give me the line number of the segmentation fault?
I know I can:
Debug line by line
Put printfs in the code to narrow down.
Edits:
bt / where on gdb give No stack.
Helpful suggestion
I don't know of a gcc option, but you should be able to run the application with gdb and then when it crashes, type where to take a look at the stack when it exited, which should get you close.
$ gdb blah
(gdb) run
(gdb) where
Edit for completeness:
You should also make sure to build the application with debug flags on using the -g gcc option to include line numbers in the executable.
Another option is to use the bt (backtrace) command.
Here's a complete shell/gdb session
$ gcc -ggdb myproj.c
$ gdb a.out
gdb> run --some-option=foo --other-option=bar
(gdb will say your program hit a segfault)
gdb> bt
(gdb prints a stack trace)
gdb> q
[are you sure, your program is still running]? y
$ emacs myproj.c # heh, I know what the error is now...
Happy hacking :-)
You can get gcc to print you a stacktrace when your program gets a SEGV signal, similar to how Java and other friendlier languages handle null pointer exceptions. See my answer here for more details:
how to generate a stacktace when my C++ app crashes ( using gcc compiler )
The nice thing about this is you can just leave it in your code; you don't need to run things through gdb to get the nice debug output.
If you compile with -g and follow the instructions there, you can use a command-line tool like addr2line to get file/line information from the output.
Run it under valgrind.
you also need to build with debug flags on -g
You can also open the core dump with gdb (you need -g though).
If all the preceding suggestions to compile with debugging (-g) and run under a debugger (gdb, run, bt) are not working for you, then:
Elementary: Maybe you're not running under the debugger, you're just trying to analyze the postmortem core dump. (If you start a debug session, but don't run the program, or if it exits, then when you ask for a backtrace, gdb will say "No stack" -- because there's no running program at all. Don't forget to type "run".) If it segfaulted, don't forget to add the third argument (core) when you run gdb, otherwise you start in the same state, not attached to any particular process or memory image.
Difficult: If your program is/was really running but your gdb is saying "No stack" perhaps your stack pointer is badly smashed. In which case, you may be a buffer overflow problem somewhere, severe enough to mash your runtime state entirely. GCC 4.1 supports the ProPolice "Stack Smashing Protector" that is enabled with -fstack-protector-all. It can be added to GCC 3.x with a patch.
There is no method for GCC to provide this information, you'll have to rely on an external program like GDB.
GDB can give you the line where a crash occurred with the "bt" (short for "backtrace") command after the program has seg faulted. This will give you not only the line of the crash, but the whole stack of the program (so you can see what called the function where the crash happened).
The No stack problem seems to happen when the program exit successfully.
For the record, I had this problem because I had forgotten a return in my code, which made my program exit with failure code.