Вы находитесь на странице: 1из 9

CS61: Systems Programming and

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

Arrays
Pointer Arithmetic
C allows arithmetic on pointers. The value is scaled according to the size of the data type
referenced by the pointer.
Exercise 1: Say we have the following C code:
int *p = (int )0x8048750;
int val = (int) (p + 3);
What is the numeric value of val in the above code?
Nested Arrays:
int A[4][3];
Element

Address

Value

A[0][0]

xa

A[0][1]

xa+4

A[0][2]

xa+8

A[1][0]

xa+12

A[1][1]

xa+16

A[1][2]

xa+20

A[2][0]

xa+24

A[2][1]

xa+28

A[2][2]

xa+32

A[3][0]

xa+36

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

A+36 =
A[3][-1] =
A[0][-1] =

Structures:
Exercise 3:
Consider the following structure:
struct prob {
int *p;
struct {
int x;
int y;
} s;
struct prob *next;
}
The following procedure (with some expressions omitted) operates on this structure:
void sp_init(struct prob *sp)
{
sp->s.x = ________;
sp->p = ________;
sp->next = ________;
}
A: What are the offsets (in bytes) of the following fields?
p:
s.x:
s.y:
next:
B. 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), %eax
movl 8(%eax), %edx
3

movl %edx, 4(%eax)


leal 4(%eax), %edx
movl %edx, (%eax)
movl %eax, 12(%eax)
On the basis of this information, fill in the missing expressions in the code for sp_init.
Exercise 4:
For each of the following structure declarations, determine the offset of each field, the
total size of the structure, and its alignment requirement under Linux on an IA32
machine.
A. struct P1 { int i; char c; int j; char d; };
B. struct P2 {int i; char c; char d; int j; };
C. struct P3 {short w[3]; char c[3]; };
D. struct P4 {short w[3]; char* c[3]; };
E. struct P5 {struct P1 a[2]; struct P2 *p; };

Function calls
Exercise 5:
Lets say we are given the following assembly code for a function.
1
2
3
4
5
6
7
8
9
...
20
21
22

pushl %edi
pushl %esi
pushl %ebx
movl 24(%ebp), %eax
imull 16(%ebp), %eax
movl 24(%ebp), %ebx
leal 0(, %eax, 4), %ecx
addl 8(%ebp), %ecx
movl %ebx, %edx
popl %ebx
popl %esi
popl %edi
4

a. Why are %edi, %esi, and %ebx the only registers saved and restored by this
piece of code? What about %eax, %edx, and %ecx?
b. What do 24(%ebp) and 16(%ebp)refer to?

Buffer Overruns & Stack Exploits


The old %ebp and return address is stored after
local variables. If we write beyond the local
variables, we'll overwrite the old %ebp and return
address.

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];
printf("Please enter 8 characters or less: \n");
gets(some_chars);
printf("You entered:%s \n", some_chars);
return;
}

How many bytes do you think will be allocated to the some_chars string?

When compiled, you'll get a warning...


warning: the `gets' function is dangerous and should not be used.

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

%ebp
%esp,%ebp
$0x18,%esp
$0x80484ec,(%esp)
0x80482d4 <printf@plt>

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),%eax
%eax,(%esp)
0x80482b4 <gets@plt>
0xfffffff8(%ebp),%eax
%eax,0x4(%esp)
$0x8048511,(%esp)
0x80482d4 <printf@plt>

Suppose we have another function called my_function in the program that is not called by
some_function. 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);
return;
}
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,%ebp
$0x8,%esp
0x8(%ebp),%eax
%eax,0x4(%esp)
$0x8048524,(%esp)
0x80482d4 <printf@plt>

Exercise 6:
What will the following exploit string do, if given as an input to the gets function? (Note
that this isn't what you'd typethese 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?

Question Answers:
#1: Since p is of type int *, 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. Not a valid memory reference.
#3:
A: The layout of the structure is as follows:
Offset
Contents

4
p

8
s.x

12
s.y

next

B: 16 bytes
C: The assembly code with annotations:
movl 8(%ebp), %eax # get sp
movl 8(%eax), %edx # get sp->s.y
movl %edx, 4(%eax) # copy to sp->s.x
leal 4(%eax), %edx # get &(sp->s.x)
movl %edx, (%eax) # copy to sp->p
movl %eax, 12(%eax) # sp->next = sp
So the C code looks as follows:
void sp_init(struct prob *sp)
{
sp->s.x = sp->s.y;
sp->p = &(sp->s.x);
sp->next = sp;
}
7

#4: A. struct P1 { int i; char c; int j; char d; };


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

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

Вам также может понравиться