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