Machine Level Programming V

Download Report

Transcript Machine Level Programming V

Alignment

Aligned Data

Primitive data type requires K bytes

Address must be multiple of K

Required on some machines; advised on IA32

treated differently by Linux and Windows!

Motivation for Aligning Data

Memory accessed by (aligned) double or quad-words

Inefficient to load or store datum that spans quad word boundaries

Virtual memory very tricky when datum spans 2 pages Compiler

Inserts gaps in structure to ensure correct alignment of fields

– 1 – EECS213, S’08

Specific Cases of Alignment

Size of Primitive Data Type:

1 byte (e.g., char)

no restrictions on address

  

2 bytes (e.g., short )

lowest 1 bit of address must be 0 2 4 bytes (e.g., int , float , char * , etc.)

lowest 2 bits of address must be 00 2 8 bytes (e.g., double )

 

Windows (and most other OS’s & instruction sets):

»

lowest 3 bits of address must be 000 2 Linux:

»

lowest 2 bits of address must be 00 2

»

i.e., treated the same as a 4-byte primitive data type

12 bytes ( long double )

Linux:

»

lowest 2 bits of address must be 00 2

»

i.e., treated the same as a 4-byte primitive data type

– 2 – EECS213, S’08

Satisfying Alignment with Structures

Offsets Within Structure

Must satisfy element’s alignment requirement Overall Structure Placement

Each structure has alignment requirement K

Largest alignment of any element

Initial address & structure length must be multiples of K struct S1 { char c; int i[2]; double v; } *p; Example (under Windows):

c p+0 K = 8, due to double element i[0] i[1] p+4 p+8 p+16 v p+24 Multiple of 4

– 3 –

Multiple of 8 Multiple of 8 Multiple of 8

EECS213, S’08

Linux vs. Windows

Windows:

K = 8, due to double element c p+0 p+4 i[0] p+8 i[1] Multiple of 4 Multiple of 8 struct S1 { char c; int i[2]; double v; } *p; p+16 Multiple of 8 v p+24 Multiple of 8 Linux:

K = 4; double treated like a 4-byte data type c p+0 p+4 i[0] p+8 i[1] p+12 v

– 4 –

Multiple of 4 Multiple of 4 Multiple of 4 p+20 Multiple of 4

EECS213, S’08

Overall Alignment Requirement

struct S2 { double x; int i[2]; char c; } *p; p must be multiple of: 8 for Windows 4 for Linux

– 5 –

x p+0 struct S3 { float x[2]; int i[2]; char c; } *p; p+8 i[0] p p+12 i[1] c p+16 p+0 x[0] p+4 x[1] p+8 i[0] p+12 i[1] c p+16 Windows : p+24 Linux : p+20 must be multiple of 4 (in either OS) p+20

EECS213, S’08

Ordering Elements Within Structure

struct S4 { char c1; double v; char c2; int i; } *p; 10 bytes wasted space in Windows p+8 v c2 p+16 p+20 i p+24 c1 p+0 struct S5 { double v; char c1; char c2; int i; } *p; v p+0 c1 c2 p+8 2 bytes wasted space p+12 i p+16

– 6 – EECS213, S’08

Arrays of Structures

Principle

Allocated by repeating allocation for array type

In general, may nest arrays & structures to arbitrary depth struct S6 { short i; float v; short j; } a[10]; a[1].i

a+12 a+16 a[1].v

a[1].j

a+20 a+24

– 7 –

a+0 a[0] a+12 a[1] a+24 a[2] a+36

• • • EECS213, S’08

Accessing Element within Array

Compute offset to start of structure

Compute 12*

i

as 4*(

i

+2

i

)

Access element according to its offset within structure

Offset by 8

Assembler gives displacement as a + 8

»

Linker must set actual value short get_j(int idx) { return a[idx].j; } struct S6 { short i; float v; short j; } a[10]; # %eax = idx leal (%eax,%eax,2),%eax # 3*idx movswl a+8(,%eax,4),%eax a[0] a+0 a[i].i

a+12i • • • a+12i a[i].v

a[i] a[i].j

a+12i+8 • • •

EECS213, S’08 – 8 –

Satisfying Alignment within Structure

Achieving Alignment

  

Starting address of structure array must be multiple of worst-case alignment for any element

a must be multiple of 4 Offset of element within structure must be multiple of element’s alignment requirement

v ’s offset of 4 is a multiple of 4 struct S6 { short i; float v; short j; } a[10]; Overall size of structure must be multiple of worst-case alignment for any element

Structure padded with unused space to be 12 bytes a[0] • • • a[i] • • • a+0 a+12i a[1].i

Multiple of 4

a+12i

– 9 –

a+12i+4 a[1].v

a[1].j

EECS213, S’08 Multiple of 4

Alignment Quiz

For each struct, give the offset of each field, total size, and struct alignment (1, 2 or 4 byte) required in Linux.

struct P1 {int i; char c; int j; char d; }; i: _1_ c: _2_ j: _3_ d: _4_ total: _5_ alignment: _6_ struct P2 {int i; char c; char d; int j; }; i: _7_ c: _8_ d: _9_ j: _10_ total: _11_ alignment: _12_ struct P3 {struct P1 a[2]; struct P2 *p; }; a: _13_ p: _14_ total: _15_ alignment: _16_

– 10 – EECS213, S’08

Union Allocation

Principles

Overlay union elements

Allocate according to largest element

Can only use one field at a time union U1 { char c; int i[2]; double v; } *up; up+0 struct S1 { char c; int i[2]; double v; } *sp; c

(Windows alignment)

i[0] v up+4 sp+0 c sp+4 i[0] sp+8 i[1] sp+16 v i[1] up+8 sp+24

EECS213, S’08 – 11 –

Using Union to Access Bit Patterns

typedef union { float f; unsigned u; } bit_float_t; float bit2float(unsigned u) { bit_float_t arg; arg.u = u; return arg.f; } u f 0 4

Get direct access to bit representation of float

bit2float generates float with given bit pattern

NOT the same as (float) u

float2bit generates bit pattern from float

NOT the same as (unsigned) f unsigned float2bit(float f) { bit_float_t arg; arg.f = f; return arg.u; }

– 12 – EECS213, S’08

Byte Ordering Revisited

Idea

Short/long/quad words stored in memory as 2/4/8 consecutive bytes

Which is most (least) significant?

Can cause problems when exchanging binary data between machines Big Endian

Most significant byte has lowest address

PowerPC, Sparc Little Endian

Least significant byte has lowest address

Intel x86, Alpha

– 13 – EECS213, S’08

Byte Ordering Example

union { unsigned char c[8]; unsigned short s[4]; unsigned int i[2]; unsigned long l[1]; } dw; c[0] c[1] s[0] c[2] c[3] s[1] i[0] l[0] c[4] c[5] s[2] c[6] c[7] s[3] i[1]

– 14 – EECS213, S’08

– 15 –

Byte Ordering Example (Cont).

int j; for (j = 0; j < 8; j++) dw.c[j] = 0xf0 + j; printf("Characters 0-7 == [0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x]\n", dw.c[0], dw.c[1], dw.c[2], dw.c[3], dw.c[4], dw.c[5], dw.c[6], dw.c[7]); printf("Shorts 0-3 == [0x%x,0x%x,0x%x,0x%x]\n", dw.s[0], dw.s[1], dw.s[2], dw.s[3]); printf("Ints 0-1 == [0x%x,0x%x]\n", dw.i[0], dw.i[1]); printf("Long 0 == [0x%lx]\n", dw.l[0]);

EECS213, S’08

Byte Ordering on x86

Little Endian ( least significant byte has lowest address )

f0

c[0]

f1

c[1]

f2

c[2]

f3

c[3]

f4

c[4]

f5

c[5]

f6

c[6]

f7

c[7] LSB MSB s[0] LSB LSB i[0] MSB s[1] MSB LSB MSB LSB MSB s[2] LSB LSB i[1] MSB s[3] MSB l[0] Output on Pentium: Characters 0-7 == [0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7] Shorts 0-3 == [0xf1f0,0xf3f2,0xf5f4,0xf7f6] Ints 0-1 == [0xf3f2f1f0,0xf7f6f5f4] Long 0 == [f3f2f1f0]

– 16 –

Print

EECS213, S’08

Byte Ordering on Sun

Big Endian ( most significant byte has lowest address )

f0

c[0]

f1

c[1]

f2

c[2]

f3

c[3]

f4

c[4]

f5

c[5]

f6

c[6]

f7

c[7] MSB LSB s[0] MSB MSB i[0] LSB s[1] LSB MSB LSB MSB LSB s[2] MSB MSB s[3] LSB LSB i[1] l[0] Print Output on Sun: Characters 0-7 == [0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7] Shorts 0-3 == [0xf0f1,0xf2f3,0xf4f5,0xf6f7] Ints 0-1 == [0xf0f1f2f3,0xf4f5f6f7] Long 0 == [0xf0f1f2f3]

– 17 – EECS213, S’08

Byte Ordering on Alpha

Little Endian

f0

c[0]

f1

c[1]

f2

c[2]

f3

c[3]

f4

c[4]

f5

c[5]

f6

c[6]

f7

c[7] LSB MSB s[0] LSB LSB i[0] MSB s[1] MSB LSB LSB MSB s[2] LSB LSB i[1] MSB s[3] MSB MSB l[0] Print Output on Alpha: Characters 0-7 == [0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7] Shorts 0-3 == [0xf1f0,0xf3f2,0xf5f4,0xf7f6] Ints 0-1 == [0xf3f2f1f0,0xf7f6f5f4] Long 0 == [0xf7f6f5f4f3f2f1f0]

– 18 – EECS213, S’08

Summary

Arrays in C

Contiguous allocation of memory

Pointer to first element

No bounds checking Compiler Optimizations

Compiler often turns array code into pointer code ( zd2int )

Uses addressing modes to scale array indices

Lots of tricks to improve array indexing in loops Structures

Allocate bytes in order declared

Pad in middle and at end to satisfy alignment Unions

Overlay declarations

– 19 – EECS213, S’08

EECS213 Machine-Level Programming V: Miscellaneous Topics Apr 28, 2008

Topics

Buffer Overflow

Floating Point Code

Internet Worm and IM War

November, 1998

Internet Worm attacks thousands of Internet hosts.

How did it happen?

July, 1999

Microsoft launches MSN Messenger (instant messaging system).

Messenger clients can access popular AOL Instant Messaging Service (AIM) servers AIM client MSN server MSN client AIM server AIM client

– 21 – EECS213, S’08

Internet Worm and IM War (cont.)

August 1999

Mysteriously, Messenger clients can no longer access AIM servers.

Microsoft and AOL begin the IM war:

AOL changes server to disallow Messenger clients

Microsoft makes changes to clients to defeat AOL changes.

At least 13 such skirmishes.

How did it happen?

The Internet Worm and AOL/Microsoft War were both based on

stack buffer overflow

exploits!

many Unix functions do not check argument sizes.

allows target buffers to overflow.

– 22 – EECS213, S’08

String Library Code

Implementation of Unix function gets

No way to specify limit on number of characters to read /* Get string from stdin */ char *gets(char *dest) { int c = getc(); char *p = dest; while (c != EOF && c != '\n') { *p++ = c; c = getc(); } *p = '\0'; return dest; }

– 23 – 

Similar problems with other Unix functions

strcpy : Copies string of arbitrary length

scanf , fscanf , sscanf , when given %s conversion specification

EECS213, S’08

– 24 –

Vulnerable Buffer Code

/* Echo Line */ void echo() { char buf[4]; /* Way too small! */ gets(buf); puts(buf); } int main() { printf("Type a string:"); echo(); return 0; }

EECS213, S’08

– 25 –

Buffer Overflow Executions

unix>./bufdemo Type a string:123 123 unix>./bufdemo Type a string:12345 Segmentation Fault unix>./bufdemo Type a string:12345678 Segmentation Fault

EECS213, S’08

Buffer Overflow Stack

Stack Frame for main Return Address Saved %ebp [3][2][1][0] buf %ebp

/* Echo Line */ void echo() { char buf[4]; /* Way too small! */ gets(buf); puts(buf); }

Stack Frame for echo

echo: pushl %ebp movl %esp,%ebp subl $20,%esp pushl %ebx # Save %ebp on stack # Allocate space on stack # Save %ebx addl $-12,%esp leal -4(%ebp),%ebx # Compute buf as %ebp-4 pushl %ebx # Allocate space on stack # Push buf on stack call gets . . .

# Call gets

EECS213, S’08 – 26 –

Buffer Overflow Stack Example

unix> gdb bufdemo (gdb) break echo Breakpoint 1 at 0x8048583 (gdb) run Breakpoint 1, 0x8048583 in echo () (gdb) print /x *(unsigned *)$ebp $1 = 0xbffff8f8 (gdb) print /x *((unsigned *)$ebp + 1) $3 = 0x804864d

Stack Frame for main Stack Frame for main

Before call to gets

– 27 – Return Address Saved %ebp [3][2][1][0] buf %ebp Saved %ebp

0xbffff8d8

Stack Frame for echo Stack Frame for echo

8048648: call 804857c 804864d: mov 0xffffffe8(%ebp),%ebx # Return Point

EECS213, S’08

Buffer Overflow Example #1

Before Call to gets

Stack Frame for main Return Address Saved %ebp [3][2][1][0] buf %ebp Stack Frame for echo

Input = “123”

Stack Frame for main Saved %ebp

0xbffff8d8

buf Stack Frame for echo

No Problem

EECS213, S’08 – 28 –

Buffer Overflow Stack Example #2

Stack Frame for main Stack Frame for main

Input = “12345”

– 29 – Return Address Saved %ebp [3][2][1][0] buf %ebp Stack Frame for echo Saved

00 35

Stack Frame for echo

0xbffff8d8

buf

Saved value of %ebp to 0xbfff0035 set echo code: Bad news when later attempt to restore 8048592: push %ebx 8048593: call 80483e4 <_init+0x50> # gets 8048598: mov 0xffffffe8(%ebp),%ebx 804859b: mov %ebp,%esp 804859d: pop %ebp

# %ebp gets set to invalid value

804859e: ret %ebp

EECS213, S’08

Buffer Overflow Stack Example #3

Stack Frame for main Stack Frame for main

Input = “12345678”

Return Address Saved %ebp [3][2][1][0] buf %ebp Saved %ebp

0xbffff8d8

buf – 30 – Stack Frame for echo Stack Frame for echo

Invalid address %ebp and return address corrupted No longer pointing to desired return point 8048648: call 804857c 804864d: mov 0xffffffe8(%ebp),%ebx # Return Point

EECS213, S’08

return address A

Malicious Use of Buffer Overflow

Stack after call to gets() void foo(){ bar(); ...

} void bar() { char buf[64]; gets(buf); ... } data written by gets() B B pad exploit code foo stack frame bar stack frame

Input string contains byte representation of executable code

– 31 –  

Overwrite return address with address of buffer When bar() executes ret , will jump to exploit code

EECS213, S’08

Exploits Based on Buffer Overflows

Buffer overflow bugs allow remote machines to execute arbitrary code on victim machines.

Internet worm

Early versions of the finger server (fingerd) used gets() to read the argument sent by the client:

finger [email protected]

Worm attacked fingerd server by sending phony argument:

finger “exploit-code padding new-return-address”

exploit code: executed a root shell on the victim machine with a direct TCP connection to the attacker.

– 32 – EECS213, S’08

Exploits Based on Buffer Overflows

Buffer overflow bugs allow remote machines to execute arbitrary code on victim machines.

IM War

AOL exploited existing buffer overflow bug in AIM clients

exploit code: returned 4-byte signature (the bytes at some location in the AIM client) to server.

When Microsoft changed code to match signature, AOL changed signature location.

– 33 – EECS213, S’08

Date: Wed, 11 Aug 1999 11:30:57 -0700 (PDT) From: Phil Bucking Subject: AOL exploiting buffer overrun bug in their own software! To: [email protected] Mr. Smith, I am writing you because I have discovered something that I think you might find interesting because you are an Internet security expert with experience in this area. I have also tried to contact AOL but received no response.

I am a developer who has been working on a revolutionary new instant messaging client that should be released later this year.

...

It appears that the AIM client has a buffer overrun bug. By itself this might not be the end of the world, as MS surely has had its share. But AOL is now *exploiting their own buffer overrun bug* to help in its efforts to block MS Instant Messenger.

....

Since you have significant credibility with the press I hope that you can use this information to help inform people that behind AOL's friendly exterior they are nefariously compromising peoples' security.

Sincerely, Phil Bucking Founder, Bucking Consulting [email protected]

– 34 –

It was later determined that this email originated from within Microsoft!

EECS213, S’08

Code Red Worm

History

June 18, 2001. Microsoft announces buffer overflow vulnerability in IIS Internet server

July 19, 2001. over 250,000 machines infected by new virus in 9 hours

White house must change its IP address. Pentagon shut down public WWW servers for day When We Set Up CS:APP Web Site

Received strings of form GET /default.ida?NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN....NNNN

NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN%u9090%u6858%ucbd3%u780 1%u9090%u6858%ucbd3%u7801%u9090%u6858%ucbd3%u7801%u9090%u909 0%u8190%u00c3%u0003%u8b00%u531b%u53ff%u0078%u0000%u00=a HTTP/1.0" 400 325 "-" "-"

– 35 – EECS213, S’08

Code Red Exploit Code

Starts 100 threads running

Spread self

Generate random IP addresses & send attack string

Between 1st & 19th of month

Attack www.whitehouse.gov

Send 98,304 packets; sleep for 4-1/2 hours; repeat

 »

Denial of service attack Between 21st & 27th of month

Deface server’s home page

After waiting 2 hours

– 36 – EECS213, S’08

Code Red Effects

Later Version Even More Malicious

Code Red II

As of April, 2002, over 18,000 machines infected

Still spreading Paved Way for NIMDA

Variety of propagation methods

One was to exploit vulnerabilities left behind by Code Red II

– 37 – EECS213, S’08

Avoiding Overflow Vulnerability

/* Echo Line */ void echo() { char buf[4]; /* Way too small! */ fgets(buf, 4, stdin); puts(buf); } Use Library Routines that Limit String Lengths

fgets instead of gets

 

strncpy instead of strcpy Don’t use scanf with %s conversion specification

Use fgets to read the string

– 38 – EECS213, S’08