Execve Shellcode Linux Segmentation Fault

execve shellcode linux segmentation fault

Your problem is that the .text section is not writable by default. The easiest thing to do is put your code into a new custom section that is marked as writable. Add this line at the top of your asm file:

section .shellcode  progbits alloc exec write align=16

You could also pass the -N switch to the linker.

Alternatively, you could rewrite the shellcode so that it uses the stack to create the arguments.

Why does my shellcode segfault when executed from C, but not as a stand-alone executable?

It is normal, because your shellcode is not setting the registers rsi and rdx, and when your C program executes the shellcode will have garbage in the registers rdi and rdx. It is because the syscall execve needs more arguments.

int execve (const char *filename, const char *argv [], const char *envp[]);

As extra information, the segmentation fault is because after your execve syscall you will get an error in rax and you will move 60 to the last 8 bits of rax and call to this syscall that doesn't exist.

Executing shellcode segmentation fault

You forgot to set up edx so it contains whatever the C code last used it for and that's unlikely to be a valid environment pointer. In the standalone code, edx happened to be zero due to the initial startup state of the program. If you use strace you can see that the execve returns with -EFAULT and then execution continues past your code into garbage which then truely segfaults. You can fix the shellcode for example like this:

char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
"\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\x31\xd2\xcd\x80";

(I included a xor edx, edx before the int 0x80.)

execve x86 - Segmentation Fault

As pointed out in the comments the arguments need to be NULL terminated.

Also mov al, 0xb only sets the lower 8 bits of the (32 bit) eax register.
Earlier on you also loaded an address from the stack into eax mov eax, esp and since the stack grows down, the value stored in eax will be much closer to 0xFFFFFFFF that it is to 0. When you later mov al, 0xb you only substitute the last F and eax needs to be exactly 0xb.

Thus you need to either move the value to whole eax register or make sure its upper 24 bits are zeroed beforehand - for example by doing xor eax, eax.

global _start

section .text
_start:

push dword 0x0068732F ; Push /sh
push dword 0x6E69622F ; Push /bin
mov eax, esp ; Store Pointer To /bin/sh In EAX

push dword 0x0000632D ; Push -c
mov ebx, esp ; Store Pointer To -c In EBX

push dword 0x00000068 ; Push h
push dword 0x7361622F ; Push /bas
push dword 0x6E69622F ; Push /bin
mov ecx, esp ; Store Pointer To /bin/bash In ECX

push 0 ; <----- NULL args terminator
push ecx ; Push /bin/bash Pointer
push ebx ; Push -c Pointer
push eax ; Push /bin/sh Pointer

mov ebx, eax ; Move /bin/sh Pointer To EAX
mov ecx, esp ; Store /bin/sh -c /bin/bash Pointer in ECX
xor edx, edx ; Store 0 In EDX
;xor eax, eax ; <----- either xor eax, eax or mov into eax
mov eax, 11 ; sys_execve
int 0x80 ; system call

32 bit shellcode causes a segmentation fault when trying to push /bin//sh to the stack

After main returns into your shellcode, ESP will probably be pointing just above that buffer. And EIP is pointing to the start of it; that's what returning into it means.

A couple push instructions may modify the machine code at the end of the buffer, leading to a SIGILL with EIP pointing at a byte you just pushed.

Probably the easiest fix is add esp, -128 to go all the way past your buffer. Or sub esp, -128 to go higher up the stack. (-128 is the largest magnitude 8-bit immediate you can use, avoiding introducing zeros in the machine code with sub esp, 128 or 1024. If you wanted to move the stack farther, you could of course construct a larger value in a register.)

I didn't test this guess, but you can confirm it in GDB by single-stepping into your shellcode with si from the end of main to step by instructions.

Use disas after each instruction to see disassembly. Or use layout reg. See the bottom of https://stackoverflow.com/tags/x86/info for more GDB debugging tips.


The given solution is more complicated because it apparently sets up an actual argv array instead of just passing NULL pointers for char **argv and char **envp. (Which on Linux is treated the same as valid pointers to empty NULL-terminated arrays: http://man7.org/linux/man-pages/man2/execve.2.html#NOTES).

But the key difference is that it uses jmp/call/pop to get a pointer to a string already in memory. That's only one stack slot not three. (The end of its payload before the return address is data, not instructions, but it would fail in a different way if it did too many pushes and overwrote the string instead of just storing a 0 terminator. The call jumps backwards before the pushed return address actually modifies the buffer, but if it did overwrite anything near the end it would still break.)


@Margaret looked into this in more detail, and spotted that it's only the 3rd push that breaks anything. That makes sense: the first 2 are presumably overwriting the part of the payload that contained the new return address and the saved EBP value. And it just so happened that the compiler put main's buffer contiguous with that.

If you actually used tcc not gcc, that's probably not a surprise. GCC would have aligned it by 16 and probably for one reason or another left a gap between the buffer and the top of the stack frame.

Segmentation fault when i try to run the extracted shellcode even if there is no null

Okay, this looks like it's on Linux. You have to make your stack executable in order to make it work. You basically have to call mprotect() on your region of memory and set its permissions to PROT_EXEC and PROT_READ.

http://linux.about.com/library/cmd/blcmdl2_mprotect.htm

Why is this shellcode causing a segmentation fault?

Writeable data in static storage (such as your code array) usually ends up in the .data section which is usually marked “not executable.” Mark the array as const so it ends up in .rodata resp. .text and can be executed.



Related Topics



Leave a reply



Submit