You are on page 1of 9

CS61: Systems Programming and

Machine Organization
Section Notes
Fall 2009 – Week 2
Week of Sept 21 to Sept 25
Outline for this week:
Out of bounds Memory Access
Buffer Overruns & Stack Exploits


Arrays Pointer Arithmetic C allows arithmetic on pointers. Exercise 1: Say we have the following C code: int *p = (int )0x8048750. int val = (int) (p + 3). The value is scaled according to the size of the data type referenced by the pointer. Element Address Value A[0][0] xa 0 A[0][1] xa+4 1 A[0][2] xa+8 2 A[1][0] xa+12 3 A[1][1] xa+16 4 A[1][2] xa+20 5 A[2][0] xa+24 6 A[2][1] xa+28 7 A[2][2] xa+32 8 A[3][0] xa+36 9 A[3][1] xa+40 10 A[3][2] xa+44 11 Exercise 2: What are the values of the following expressions? A[2][0] = 2 . What is the numeric value of “val” in the above code? Nested Arrays: int A[4][3].

y: next: B.x = ________. sp->p = ________. int y. How many total bytes does this structure require? C: The compiler generates the following assembly code for the body of sp_init: movl 8(%ebp). struct { int x. } s. %eax movl 8(%eax). struct prob *next. } The following procedure (with some expressions omitted) operates on this structure: void sp_init(struct prob *sp) { sp->s. %edx 3 .x: s.A+36 = A[3][-1] = A[0][-1] = Structures: Exercise 3: Consider the following structure: struct prob { int *p. } A: What are the offsets (in bytes) of the following fields? p: s. sp->next = ________.

movl %edx. struct P5 {struct P1 a[2]. }. struct P2 *p. int j. struct P4 {short w[3]. }. char c[3]. E. 12(%eax) On the basis of this information. and its alignment requirement under Linux on an IA32 machine. 20 21 22 pushl %edi pushl %esi pushl %ebx movl 24(%ebp). Function calls Exercise 5: Lets say we are given the following assembly code for a function. %ecx movl %ebx. D. %ebx leal 0(. %ecx addl 8(%ebp). 4(%eax) leal 4(%eax). char* c[3]. %edx popl %ebx popl %esi popl %edi 4 . }.. char d. int j. %eax imull 16(%ebp). char d. struct P2 {int i. Exercise 4: For each of the following structure declarations. struct P3 {short w[3]. char c. %edx movl %edx. fill in the missing expressions in the code for sp_init. %eax. }. the total size of the structure. char c. %eax movl 24(%ebp). }. 4). C. struct P1 { int i. 1 2 3 4 5 6 7 8 9 …. (%eax) movl %eax.. B. determine the offset of each field. A.

%esi. What do 24(%ebp) and 16(%ebp)refer to? Buffer Overruns & Stack Exploits The old %ebp and return address is stored after local variables. Here's the assembly: 0x08048394 0x08048395 0x08048397 0x0804839a 0x080483a1 <some_function+0>: <some_function+1>: <some_function+3>: <some_function+6>: <some_function+13>: push mov sub movl call 5 %ebp %esp. printf("You entered:%s \n".(%esp) 0x80482d4 <printf@plt> . %edx. some_chars).. you'll get a warning. Why are %edi. If we write beyond the local variables.a. and %ecx? b. printf("Please enter 8 characters or less: \n"). } ● How many bytes do you think will be allocated to the some_chars string? When compiled. return.. gets(some_chars). ● ● ● What do you think will happen if you overwrite the old %ebp? What do you think will happen if you overwrite the return address? How can you use this to execute malicious code? Buffer Overrun Example void some_function() { char some_chars[8].%esp $0x80484ec. we'll overwrite the old %ebp and return address. warning: the `gets' function is dangerous and should not be used.%ebp $0x18. and %ebx the only registers saved and restored by this piece of code? What about %eax.

0x4(%esp) $0x8048524. } 0x080483c6 0x080483c7 0x080483c9 0x080483cc 0x080483cf 0x080483d3 0x080483da 0x080483df 0x080483e0 <my_function+0>: <my_function+1>: <my_function+3>: <my_function+6>: <my_function+9>: <my_function+13>: <my_function+20>: <my_function+25>: <my_function+26>: push mov sub mov mov movl call leave ret %ebp %esp. return.%eax %eax.%esp 0x8(%ebp).0x080483a6 0x080483a9 0x080483ac 0x080483b1 0x080483b4 0x080483b8 0x080483bf 0x080483c4 0x080483c5 <some_function+18>: <some_function+21>: <some_function+24>: <some_function+29>: <some_function+32>: <some_function+36>: <some_function+43>: <some_function+48>: <some_function+49>: lea mov call lea mov movl call leave ret 0xfffffff8(%ebp).0x4(%esp) $0x8048511.(%esp) 0x80482b4 <gets@plt> 0xfffffff8(%ebp).%ebp $0x8.%eax %eax.(%esp) 0x80482d4 <printf@plt> Exercise 6: What will the following exploit string do. How can we exploit the stack to execute this function? The corresponding assembly is: void my_function(int i) { printf("parameter passed using buffer overun: 0x%x \n".i).(%esp) 0x80482d4 <printf@plt> Suppose we have another function called my_function in the program that is not called by some_function. if given as an input to the gets function? (Note that this isn't what you'd type—these are the hex values of the bytes) 31 31 31 31 32 32 32 32 33 33 33 33 c6 83 04 08 ef be ad de aa bb cc dd a) Which part changed the old %ebp? b) How did we pass the arguments for my_function? What is the value passed? c) Can we cause the processor to execute the exploit string as instructions? 6 .%eax %eax.

y next B: 16 bytes C: The assembly code with annotations: movl 8(%ebp). p+3 would evaluate (in C) to: 0x8048750 + (3 * sizeof(int)) = 0x8048750 + 12 = 0x804875C #2: A[2][0] = 6 A+36 = 9 A[3][-1] = 8 A[0][-1] = Unknown. (%eax) # copy to sp->p movl %eax.x = sp->s. %eax # get sp movl 8(%eax). 4(%eax) # copy to sp->s. 12(%eax) # sp->next = sp So the C code looks as follows: void sp_init(struct prob *sp) { sp->s.x leal 4(%eax). } 7 .y movl %edx.x 12 s.x). #3: A: The layout of the structure is as follows: Offset Contents 0 4 p 8 s. sp->p = &(sp->s.y.Question Answers: #1: Since p is of type int *.x) movl %edx. sp->next = sp. %edx # get sp->s. %edx # get &(sp->s. Not a valid memory reference.

}. 8 total size 20 alignment 4 E. [16 byte struct] [16 byte struct] [pointer] offsets 0. 32 total size 36 alignment 4 #5: a. struct P4 {short w[3]. 16(%ebp) refers to the 3rd argument passed to this function. %esi. 8 total size 12 alignment 4 C. struct P2 {int i. and the word above that with 0xDDCCBBAA a. the old ebp (with 0x3). Registers are %edi. char* c[3]. struct P3 {short w[3]. [short][short] [short][c][c] [c][1 bytes pad] offsets 0.#4: A. }. the return address. offsets 0. char d. char c. 24(%ebp) refers to the 5th argument passed to this function. struct P5 {struct P1 a[2]. the next above the return address with 0xDEADBEEF. 4. The 33 33 33 33 bytes overwrite the old ebp 8 . }. 5. #6: This input string will overwrite the buffer (with 0x31 and 0x32). %eax. struct P2 *p. and %edx are caller saved registers. char d. int j. offsets 0. char c[3]. and %ebx are callee saved registers. struct P1 { int i. }. }. char c. int j. 8. 6 total size 10 alignment 2 D. 4. b. %ecx. 12 total size 16 alignment 4 B. with 0x080483c6 (note endianness!). [short][short] [short][pad] [pointer] [pointer] [pointer] offsets 0.

and then change the return address bytes to be that address. After the ret instruction. Yes. 9 . and then use 8(%ebp) to access its argument—this will be the 0xDDCCBBAA word. We just need to use gdb to figure out what the address of buf is. c.b. my_function will push the (corrupted) old ebp onto the stack.