I wrote a program that run some code on the stack without having execution permission on the stack. And before I run the program execute: trap '' SIGSEGV
to ensure the program will ignore the signal.
lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x0x80486be <_IO_stdin_used+2> add (%eax),%al x
x0x80486c0 mov $0x12d687,%eax x
x0x80486c5 mov $0x12d687,%eax x
x0x80486ca mov $0x12d687,%eax x
x0x80486cf mov $0x12d687,%eax x
x0x80486d4 add %ah,0x6c(%esi) x
x0x80486d7 popa x
x0x80486d8 addr16 je,pn 0x8048754 x
x0x80486dc je 0x80486de x
>x0x80486de outsl %ds:(%esi),(%dx) x
x0x80486df jo 0x8048746 x
x0x80486e1 outsb %ds:(%esi),(%dx) x
x0x80486e2 and %ah,0x69(%esi) x
x0x80486e5 insb (%dx),%es:(%edi) x
x0x80486e6 add %dh,%gs:0x65(%edx) x
x0x80486ea popa x
x0x80486eb and %ah,%fs:0x69(%esi) x
x0x80486ef insb (%dx),%es:(%edi) x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj
native process 225742 In: L?? PC: 0x80486de
(gdb) info register eax
eax 0x12d687 1234567
(gdb) si
0x080486d7 in ?? ()
0x080486d8 in ?? ()
0x080486dc in ?? ()
0x080486de in ?? ()
Program received signal SIGSEGV, Segmentation fault.
0x080486de in ?? ()
(gdb)
I know that outsl required higher privileged level and that's why the process terminate. what I don't understand is why the code terminate by SIGSEGV and not another way? because if it will terminate this way it will suppose to ignore the SIGSEGV. In addition I don't understand how the code indeed run on the stack. I thought it will just ignore the signal and skip each instruction in the assembly but the value of eax indeed changed.
checksec child.o
[*] '/tmp/nadav_tiny_hard/child.o'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
// code.c
#include <sys/syscall.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <fcntl.h>
// execute mov eax, 1234567 four times. (not return or finish after that, continue to execute bullshit bits)
unsigned char *shellcode = "\xB8\x87\xD6\x12\x00\xB8\x87\xD6\x12\x00\xB8\x87\xD6\x12\x00\xB8\x87\xD6\x12\x00";
int main()
{
setvbuf(stdout, 0, 2, 0);
int (*ret)() = (int(*)())shellcode;
ret();
return 0;
}
EDIT:
$ ./code
Segmentation fault (core dumped)
don't know how to check which instruction makes the abort, and I would like to know how to survive sigsegv without terminating immediately, for the purpose of using ptrace.
EDIT2:
according to Hyde isn't it strange that my program called just one time strace and not endless number of time?
$ strace ./code
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
...