Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

Root-­The.

NET  
Security  Research  
 
Buffer  Overflow  
Part  2:  Writing  Executable  Shellcode  
 
 
Written  By  :  
Affix  root@root-­the.net  
What  is  a  Shellcode?  
In  computer  security,  a  shellcode  is  a  small  piece  of  code  used  as  the  payload  in  
the  exploitation  of  a  software  vulnerability.  It  is  called  "shellcode"  because  it  
typically  starts  a  command  shell  from  which  the  attacker  can  control  the  
compromised  machine.  Shellcode  is  commonly  written  in  machine  code,  but  any  
piece  of  code  that  performs  a  similar  task  can  be  called  shellcode.  Because  the  
function  of  a  payload  is  not  limited  to  merely  spawning  a  shell,  some  have  
suggested  that  the  name  shellcode  is  insufficient.  However,  attempts  at  replacing  
the  term  have  not  gained  wide  acceptance.  

What  do  I  need  to  get  started?  


Software  
• A  unix  based  operating  system  (Windows  if  you  understand  fully  
debugging  in  windows)  
• A  debugger  (GDB  will  be  used  in  this  guide)  
• A  C  Compiler  (GCC  will  do)  

Knowledge  
• How  processor  Registers  Work  
• Basic  Assembley  Language  
• The  Difference  between  32bit  at  64bit  registers  

 
Recommended  Reading  
• Buffer  Overflow  Part  1  :  Smashing  the  Stack  
 

  2  
Right  I’m  ready  lets  go!  
Shellcode  Application  
In  order  for  us  to  proceed  we  will  need  to  write  a  small  basic  application  that  we  
will  use  to  turn  into  shellcode.  We  do  this  by  writing  the  application  in  C  first  
then  stripping  out  the  parts  we  do  not  need.  For  example  function  names  etc…  So  
here  is  our  basic  application.  
#include <stdlib.h>

void main()
{
exit(0);
}

Hey  as  I  said  it  doesn’t  need  to  be  advanced  or  anything.  It  just  needs  to  work.  
This  is  going  to  be  an  exit  shellcode.  I  know  it  is  useless  to  some  people  but  
others  may  like  it.  
So  now  we  need  to  statically  compile  it  with  GCC.  
[Affix@localhost bof2]$ gcc -static exit.c -o exit

The  reason  we  use  the  static  switch  is  so  the  libraries  are  directly  linked  to  the  
application.  You  can  do  a  test  run  of  this  application  if  you  wish  but  its  kind  of  
useless  it  will  just  exit.  
 

Disassembly!  
Now  we  need  to  disassemble  our  functions  to  get  how  Assembly  code.  Open  up  
exit  in  gdb  
[Affix@localhost bof2]$ gdb exit

GNU gdb (GDB) Fedora (7.2-16.fc14)


Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute
it.
There is NO WARRANTY, to the extent permitted by law. Type
"show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /media/TOOLS/tuts/bof2/exit...(no
debugging symbols found)...done.
(gdb)

  3  
Ok  now  we  will  disassemble  our  main  function  
(gdb) disas main
Dump of assembler code for function main:
0x080482bc <+0>: push %ebp
0x080482bd <+1>: mov %esp,%ebp
0x080482bf <+3>: and $0xfffffff0,%esp
0x080482c2 <+6>: sub $0x10,%esp
0x080482c5 <+9>: movl $0x0,(%esp)
0x080482cc <+16>: call 0x8048e40 <exit>
End of assembler dump.

All  of  the  above  isn’t  needed,  The  highlighted  a  line  above  is  what  we  really  need  
to  pay  attention  to.    
This  is  calling  the  exit  routine.  So  now  lets  disassemble  _exit  
(gdb) disas _exit
Dump of assembler code for function _exit:
0x08053360 <+0>: mov 0x4(%esp),%ebx
0x08053364 <+4>: mov $0xfc,%eax
0x08053369 <+9>: call *0x80d25e4
0x0805336f <+15>: mov $0x1,%eax
0x08053374 <+20>: int $0x80
0x08053376 <+22>: hlt
End of assembler dump.

Ok  this  is  the  _exit  function,  Again  we  do  not  need  all  of  this  code.  Notice  that  I  
have  highlighted  2  lines.  These  are  the  lines  we  wish  to  look  at  in  a  little  more  
detail.  
Lets  start  with  the  Green.  
0x08053364 <+4>: mov $0xfc,%eax
 
we  see  this  is  moving  $0xfc  into  the  eax  register.  $0xfc  in  hex  is  252  this  calls  the  
exit_group  system  call.  If  we  look  at  exit_group  in  man  we  come  up  with  this.  
DESCRIPTION
This system call is equivalent to exit(2) except that it
terminates not only the present thread, but all threads in the
current thread group.

Now  lets  have  a  look  at  the  Blue.  


0x0805336f <+15>: mov $0x1,%eax

This  is  simply  the  exit  system  call.  Lets  check  its  man  page  
DESCRIPTION
The function _exit() terminates the calling process
"immediately". Any open file descriptors belonging to the
process are closed; any children of the process are inherited
by process 1, init, and the process’s parent is sent a SIGCHLD
signal.

That  is  exactly  what  we  want.    

 
  4  
The  following  code  is  what  we  don’t  need  so  we  can  simply  discard  this.  
0x08053364 <+4>: mov $0xfc,%eax
0x08053369 <+9>: call *0x80d25e4

Writing  the  Assembly!  


Now  we  need  to  move  on  and  write  our  assembly  code.  This  is  necessary  as  it  is  
what  the  processor  will  understand  if  we  inject  it  through  buffer  overflow  or  any  
other  means.  
The  following  code  I  have  written  contains  all  the  exit  code  we  have  discovered  
and  needed  to  keep  previously  in  our  examples.  
.text
.global _start

_start :
mov $20, %ebx
mov $1, %eax
int $0x80

Fairly  simple.  If  you  do  not  understand  assembly  language  I  recommend  
researching  a  little  to  find  out  what  all  the  above  means.  

Now  we  need  to  compile  our  code.  


[Affix@localhost bof2]$ as ExitCode.s -o ExitCode.o
[Affix@localhost bof2]$ ld ExitCode.o -o ExitCode

Now  we  have  compiled  out  ELF-­‐executable.  Feel  Free  to  test  it.  But  again  it  will  
just  exit.  
 
So  how  do  we  get  this  as  ShellCode  we  are  used  to.  Well  we  need  to  get  it  in  
MachineCode.  This  is  done  using  the  Object  Dump  utility.  it  should  be  installed  by  
default  on  most  Unix  /  Linux  based  Systems.  
[root@affix bof2]# objdump -d ExitCode

ExitCode: file format elf64-x86-64

Disassembly of section .text:

0000000000400078 <_start>:
400078: bb 14 00 00 00 mov $0x14,%ebx
40007d: b8 01 00 00 00 mov $0x1,%eax
400082: cd 80 int $0x80

Well  now  we  see  some  HEX  Code.  These  are  Known  as  OpCodes.  The  first  Byte  
we  see  (bb  on  the  first  line)  is  our  instruction  code.  Followed  by  4  bytes.  These  4  
bytes  are  the  values  to  pass  to  the  instruction.  
 
 

  5  
To  define  the  ShellCode  in  an  application  simply  we  set  it  as  a  character  array.  
Remember  these  are  HEX  Values  so  we  need  to  use  \x  
#include <stdio.h>
char ShellCode[] = "\xbb\x14\x00\x00\x00"
"\xb8\x01\x00\x00\x00"
"\xcd\x80"

int main()
{
return 0;
}

You  can  compile  this  if  you  wish  but  it  will  return  nothing.  
 

FAQ  
Q  –  Will  this  work  on  64bit  systems?  
A  –  The  process  is  basically  the  same  However  the  example  assembled  code  and  
opcodes  will  only  function  on  32  bit  systems.  
 

Shouts  and  Greetz  


• Boxhead  
• AlphaNiX  
• Root-­‐The.Net  
• Ryan  
• Nevercast  
• BeLegit  Staff  and  Members  
• Ryan1918.com  Members  
• The  Security  Research  Community  

  6  

You might also like