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 –
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
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
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 droh@cs.cmu.edu
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
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 philbucking@yahoo.com
– 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