Unanticipated segmentation fault in C - linux

I'm writing a Linux shell code exploit. My target C code is:
char code[] = "\xb0\x01\x31\xdb\xcd\x80";
int main(int argc, char **argv)
{
int(*func)();
func = (int (*)()) code;
(Int)(*func)();
}
Why does compiling and running this C program raise a segmentation fault error? The string is shell code that exits the program using the system call Int 0x80/EAX=1. The original exploit code in assembly is:
b0 01 mov al,0x1
31 db xor ebx,ebx
cd 80 int 0x80

You are not setting eax=0x1, you are setting al=0x1, so if you don't know what instructions are executed before that your shellcode, you will have eax=xxxxxx01.
As the comments said you, you have to do a xor eax, eax on the beginning of your shellcode.

Related

Is it possible to use both 64 bit and 32 bit instructions in the same executable in 64 bit Linux?

A 64 bit CPU (amd64) supports 32 bit Intel instructions in the compatibility mode. Also, a 64 bit Linux installation allows running ELFs containing 32 bit instructions if the ELF header says it is a 32 bit executable.
I was wondering if it is possible to put some assembly instructions inside the ELF which switches the CPU to 32 bit compatibility mode in the middle of a program (and then later back again)? If these assembly instructions are not permitted by the kernel, is there perhaps some way we can get the kernel to switch an already running process to 32 bit?
This is mainly a question out of curiosity since I cannot really see any use-cases for it.
Switching between long mode and compatibility mode is done by changing CS. User mode code cannot modify the descriptor table, but it can perform a far jump or far call to a code segment that is already present in the descriptor table. I think that in Linux (for example) the required compatibility mode descriptor is present.
Here is sample code for Linux (Ubuntu). Build with
$ gcc -no-pie switch_mode.c switch_cs.s
switch_mode.c:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
extern bool switch_cs(int cs, bool (*f)());
extern bool check_mode();
int main(int argc, char **argv)
{
int cs = 0x23;
if (argc > 1)
cs = strtoull(argv[1], 0, 16);
printf("switch to CS=%02x\n", cs);
bool r = switch_cs(cs, check_mode);
if (r)
printf("cs=%02x: 64-bit mode\n", cs);
else
printf("cs=%02x: 32-bit mode\n", cs);
return 0;
}
switch_cs.s:
.intel_syntax noprefix
.code64
.text
.globl switch_cs
switch_cs:
push rbx
push rbp
mov rbp, rsp
sub rsp, 0x18
mov rbx, rsp
movq [rbx], offset .L1
mov [rbx+4], edi
// Before the lcall, switch to a stack below 4GB.
// This assumes that the data segment is below 4GB.
mov rsp, offset stack+0xf0
lcall [rbx]
// restore rsp to the original stack
leave
pop rbx
ret
.code32
.L1:
call esi
lret
.code64
.globl check_mode
// returns false for 32-bit mode; true for 64-bit mode
check_mode:
xor eax, eax
// In 32-bit mode, this instruction is executed as
// inc eax; test eax, eax
test rax, rax
setz al
ret
.data
.align 16
stack: .space 0x100

Shell launched from shellcode immediatly stop upon launching

I will preface by saying that i did the research but couldn't found the answer to my basic problem.
I want to launch a shell from a shellcode through a basic program.
This is the shellcode used, that should be working by now:
0: 31 c0 xor eax, eax
2: 50 push eax
3: 68 2f 2f 73 68 push 0x68732f2f
8: 68 2f 62 69 6e push 0x6e69622f
d: 89 e3 mov ebx, esp
f: 50 push eax
10: 53 push ebx
11: 89 e1 mov ecx, esp
13: b0 0b mov al, 0xb
15: 31 d2 xor edx, edx
17: cd 80 int 0x80
The weird thing is this shellcode is working when used like so:
char *shellcode = "\x31[...]x80";
int main(void)
{
(*(void(*)()) shellcode)();
return 0;
}
But not when read from stdin with this program (compiled with the following flags:
gcc vuln.c -o vuln -fno-stack-protector -m32 -z execstack):
Code:
#include [...]
typedef void (*func)(void);
int main(void)
{
char input[4096];
read(0, input, 4096);
((func)&input)();
return 0;
}
What happen with the second program is that the program simply quits with no error code and no shell spawned.
Strace shows me that in the second program, a shell is properly launched:
read(0, "1\300Ph//shh/bin\211\343PS\211\341\260\v1\322\315\200", 4096) = 26
execve("/bin//sh", ["/bin//sh"], NULL) = 0
strace: [ Process PID=3139 runs in 64 bit mode. ]
But this line near the end is highly suspicious since I'm not asked to do anything:
read(0, "", 8192) = 0
It seems that I'm sending a null byte somehow to the spawned shell and it kills it. I first though that I'm not properly setting up my shellcode file, but those are the commands I use:
perl -e 'print "\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"' > payload.bin
./vuln < payload.bin
I also tried using this command but got the same result:
perl -e 'print "[...]" | ./vuln
I also checked the chars inside the file, but the file weights 25 oct. for a shellcode of the same size so this shouldn't be the problem.
Am i using the proper way to give a shellcode from stdin or is there another way ?
If no, where does the problem come from?
Thanks
The problem is that in the second program, you've redirected standard input to the pipe. The shell that's spawned tries to read from the pipe, gets EOF, so it exits.
You can redirect standard input back to the terminal before running the shellcode.
#include [...]
typedef void (*func)(void);
int main(void)
{
char input[4096];
read(0, input, 4096);
freopen("/dev/tty", "r", stdin);
((func)&input)();
return 0;
}

GDB - Assembly program returns /bin/sh: 0: Can't open �

I am presently learning 64-bit assembly language from the related Pentester Academy course. The code I'm working on creates the following error when ran in GDB:
/bin/sh: 0: Can't open �
[Inferior 1 (process 4049) exited with code 0177]
I have googled the error and exit code and haven't found anything helpful. I tried analyzing the code in GDB over and over, but all the right values seem to be in the right registers. I can't seem to find what's wrong.
You can find the code below. My goal is simply to invoke the execve syscall using the jump-call-pop technique.
global _start
section .text
_start:
jmp bash
code:
xor rax, rax
pop rdi
mov [rdi +7], al
push rdi
mov rsi, rsp
push rax
mov rdx, rsp
mov al, 59
syscall
bash:
call code
string: db '/bin/shABBBBBBBBCCCCCCCC'
EDIT:
Here is how I built the program:
nasm -f elf64 -o execve_stack_jcp.o execve_stack_jcp.asm
ld -o execve_stack_jcp execve_stack_jcp.o
I then use objdump -M intel -d execve_stack_jcp to output the disassembly which I then input in this c program:
#include <stdio.h>
#include <string.h>
unsigned char code[] = \
"\xeb\x13\x48\x31\xc0\x5f\x88\x47\x07\x57\x48\x89\xe6\x50\x48\x89\xe2\xb0\x3b\x0f\x05\xe8\xe8\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x42\x42\x42\x42\x43\x43\x43\x43\x43\x43\x43\x43";
int main(void) {
printf("Shellcode length: %d\n", (int)strlen(code));
int (*ret)() = (int(*)())code;
ret();
return 0;
}
Finally, I compile the c program using:
gcc -fno-stack-protector -z execstack -o shellcode shellcode.c
execve in Linux is defined this way:
int execve(const char *filename, char *const argv[],
char *const envp[]);
[snip]
argv is an array of argument strings passed to the new program. By convention, the first of these strings (i.e., argv[0]) should contain the filename associated with the file being executed. envp is an array of strings, conventionally of the form key=value, which are passed as environment to the new program. The argv and envp arrays must each include a null pointer at the end of the array.
If you were to run your program through strace ./shellcode you'd probably see something similar to this:
execve("/bin/sh", ["/bin/sh", "\270", "\1", "\353\23H1\300_\210G\7WH\211\346PH\211\342\260;\17\5\350\350\377\377\377/bin/s"...], [/* 0 vars */]) = 0
You'll notice the second argument argv has a bunch of extra entries in the array. This is because you didn't NULL terminate the argv array. To correct this you could modify your code by pushing 0 (via RAX) onto the stack like this:
xor rax, rax
pop rdi
mov [rdi +7], al
push rax ; NULL terminates the `argv` array
push rdi
mov rsi, rsp
push rax
mov rdx, rsp
If you were to run this change through strace again you'd see something like:
execve("/bin/sh", ["/bin/sh"], [/* 0 vars */]) = 0
This should end up being a successful execve call.

How to ShellCode in linux with x64 processor.

I am working my way through this tutorial, but it is written for 32 bit processors. I have found this note on 64 bit linux syscall. I can compile, run and objdump it.
My question is, why is the following code generated a segmentation fault.
/* shellcodetest.c */
char code[] = "\x48\x31\xc0\xb0\x3c\x48\x31\xff\x0f\x05";
int main(int argc, char **argv){
int (*func)();
func = (int (*)()) code;
(int)(*func)();
}
/*
exitt: file format elf64-x86-64
Disassembly of section .text:
0000000000400078 <_start>:
400078: 48 31 c0 xor %rax,%rax
40007b: b0 3c mov $0x3c,%al
40007d: 48 31 ff xor %rdi,%rdi
400080: 0f 05 syscall
*/
For reference syscall 60 (\x3c) is exit(). So this should just be calling exit(0);
The answer was to turn of DEP as suggested by #tylerl tylerl in the Information Security forum. #Adam-Miller explains how in the answer to
how to turn off DEP (Data Execution Prevention) without reboot? where he says, 'In linux, you can use the compiler flag "-z execstack"'

Modifying a character array, the modified part shows up backwards

I have just started learning assembly, and I am trying to modify a character array.
This is my assembly code:
.data
data byte 'Five', 0
.code
Asm proc
lea rax, data
mov dword ptr[rax], 'Four'
ret
Asm endp
end
And my C++ code:
#include <stdio.h>
#include <conio.h>
// external function
extern "C" char* Asm();
// main function
int main()
{
printf(Asm());
_getch();
}
When I comment out mov dword ptr[rax], 'Four', the result is that the console prints: "Five". But, with the above code uncommented, the result is "ruoF", instead of what I expected it to be, which is obviously "Four".
Why is this happening? How can I get the text to output in the correct direction without having to do some cheap workaround like this: mov dword ptr[rax], 'ruoF'?
You can use:
mov ebx,'Four'
bswap ebx
mov [rax],ebx
Or, on Intel Atom processors that support movbe (can be confirmed with cpuid):
mov ebx,'Four'
movbe [rax],ebx

Resources