EC312 Security Exercise 5 Part 1: Initial Setup Your instructors have prewritten two C programs that you will use for this lab, and have placed them in the ec310code directory. The two programs you will use today are named sx5a.c and sx5b.c . Copy these two files from the ec310code directory to the work directory by carefully entering the following two lines at the home directory prompt: midshipman@EC310:~ $ cp ec310code/sx5a.c work midshipman@EC310:~ $ cp ec310code/sx5b.c work Make sure you are at your home directory! Enter this! If all went well, you should have copies of sx5a.c and sx5b.c in your work directory. Verify that you have sx5a.c and sx5b.c in your work directory by changing to the work directory: cd work and then listing the files in the work directory: ls If you do not have sx5a.c and sx5b.c in in your work directory tech for help. Otherwise, proceed to Part 2. STOP and ask your instructor or lab Part 2: Go Navy You should now be in the work directory: Examine the program sx5a.c using nano. The C program is shown below: #include<stdio.h> #include<string.h> int main( ) { char phrase[ 10 ] = "Go Navy!" ; printf( "%s\n" , phrase ); } Save your program ( Control-o ) and exit nano ( Control-x) and then compile your program using gcc –g sx5a.c and then run your program: ./a.out . If your program is not working as expected instructor for help. Otherwise, proceed to Part 3. 1 STOP and ask your Part 3: Memory Question 1: The array named phrase is a string, and the contents of this string are stored in main memory on the program's stack. We would like to determine the starting address of the string. By using nano, change only a single character in statement printf( "%s\n" , phrase ); to determine the main memory address of where the string named phrase begins. Compile and execute your program. Question 2: How many bytes of memory are required to hold a single character? Question 3: Looking at your source code, what character should be stored at phrase[ 1 ] ? Question 4: Looking at your source code, what character should be stored at phrase[ 8 ] ? Question 5. Complete the printf statement that would allow you to see the address of the character stored at phrase[1] (don't actually make the change using nano, just state what you would do): printf( "The address of phrase[1] is %x " , ______________ ) ; Question 6: Sketch how your array should be stored in memory in the picture shown on your answer sheet. Each box represents a byte in memory. Assume that the array named phrase points to the location shown, and that memory locations are increasing going down the page. For this question all you need to do is fill in the ASCII characters that are stored in each memory location. If, in answering Question 1 above, you made a modification to your program, restore the program to its original form as shown on page 1. 2 Carefully modify your C program (using nano) so that it contains the three new lines shown in bold italics: #include<stdio.h> #include<string.h> int main( ) { char phrase[ 10 ] = "Go Navy!" ; Add these two lines. (You can also add blank lines around these two new lines if you wish.) char *ptr; ptr = phrase; printf( "%s\n" , phrase ); Add this line. (Also add blank lines if you wish.) printf( "%s\n" , ptr ); } Compile and execute your program, examining the output. If your program is not compiling your instructor for help. Otherwise, proceed to Part 4. STOP and ask Part 4: Go Navy Navy Recall that phrase, the name of an array, is really a pointer to an array of characters. In fact, phrase holds the address of the first element of the array. And the variable ptr is also a pointer. Question 7: The line of code ptr = phrase; is an assignment statement. What is being assigned to what? Question 8: Explain your program's output. Carefully modify your C program so that it contains the three new lines shown in bold italics: #include<stdio.h> #include<string.h> int main( ) { char phrase[ 10 ] = "Go Navy!" ; char *ptr; ptr = phrase; Add this line. char *another_ptr; printf( "%s\n" , phrase ); printf( "%s\n" , ptr ); another_ptr = ptr + 3 ; printf( "%s\n" , another_ptr ); Add these two lines. } Compile and execute your program. If your program is not compiling help. Otherwise, proceed to Part 5. 3 STOP and ask your instructor for Part 5: Army Strikes Back Question 9: Explain your program's output. Question 10: In the same sketch as Question 6, fill in: • • the location where ptr points to. the location where another_ptr points to. Carefully modify your C program to add the two new lines shown in bold italics (do not worry about the presence or absence of blank lines in your code): #include<stdio.h> #include<string.h> int main( ) { char phrase[ 10 ] = “Go Navy!” ; char *ptr; ptr = phrase; char *another_ptr; printf( "%s\n" , phrase ); printf( "%s\n" , ptr ); another_ptr = ptr + 3 ; printf( "%s\n" , another_ptr ); strcpy( another_ptr , "Army!" ); printf( "%s\n" , ptr ); Add these two lines. } Recall that the strcpy command provides a means for changing the values of the characters stored in a string. Ensure that you use strcpy to change another_ptr , not ptr (see the code above). Note that we then, in the last line of code, use ptr in the printf command. Compile and execute your program, examining the output. Question 11: Explain the last line of output produced by the program. Specifically, why did the value of the string named ptr change (as reflected by the last line of output) when all you did using the strcpy command was change a different string (the string named another_ptr). Phrasing this question another way: Your program above never directly changes ptr after the line ptr = phrase; but—somehow—the value printed out by the last line reflects a change. What caused this? If you are baffled, STOP and ask your instructor for an explanation. Otherwise, proceed to Part 6. 4 Part 6: Autopsy of the Program Recall that when we execute a program, it is moved from secondary memory (e.g., the hard disk) to main memory (RAM). The particular program's machine language code is moved into main memory, and the program is also given additional space in main memory (called the stack) that it can use to store variable values that it needs to execute. In the figure shown below, the machine language code has been moved into main memory starting at address 0x08048374 and the program's stack is between memory locations 0xbfffff71 and 0xbfffff73. Note that our program is not "stored in the CPU." Rather, the program is stored in main memory. The CPU can interact with the program via the three registers that we have learned about: • The eip register holds the address of the next instruction that will be executed (but has not yet been executed). • The esp register points to the "top" of the stack. • The ebp register points to the bottom of the stack. Note in the figure above the values of the eip, esp and ebp registers. 5 Now, the gdb debugger can be thought of as a microscope that allows us to examine in detail the CPU registers and memory. We have seen that we can use the info command to examine registers. For example, in the context of the figure above, if I entered i r eip I should obtain the value of 0x08048374. Similarly, if I entered x/xb 0x08048374 I should see the value 0x55. We will examine a program using the debugger, and show in particular how we can use the names of pointer variables in debugger commands. And at the end of this Security Exercise (no peeking!) we will show you a useful enhancement to the examine command. 6 Enough of program sx5a.c . I'm sure you are sick of that program! Let's move on to sx5b.c !!! Using nano examine the program sx5b.c . The C program is shown below: #include<stdio.h> #include<string.h> int main( ) { char phrase[ 10 ] = "Go Navy!" ; char *ptr; ptr = phrase; char *another_ptr; printf( "%s\n" , phrase ); printf( "%s\n" , ptr ); another_ptr = ptr + 3 ; printf( "%s\n" , another_ptr ); strcpy( another_ptr , "Army!" ); printf( "%s\n" , ptr ); } Note that this is the same program that you left off with, but we have cleaned it up (e.g., to remove unnecessary blank lines). DO NOT MAKE ANY CHANGES TO THIS PROGRAM! Let’s use the debugger to examine the program on the top of this page a bit more closely. Type the following at the prompt. Do not type the comments! gcc –g sx5b.c gdb –q // The –g provides extra functionality for the debugger. // Recall that gdb is the name of the debugger. ./a.out set dis intel // This displays the assembly code in standard Intel lingo list // This repeats the source code for convenience <Enter> // Just hit the Enter key. This displays the remainder of your source code break 13 // This sets a “breakpoint” at line 13. This is the next to last line of your // program – the line that uses strcpy. run // This starts executing the program up to the breakpoint. After entering all of these commands, your program will have executed up to but not including line 13. Line 13 is the next to last line of your program – the line that uses strcpy. Let's find out the address that phrase holds (remember, the name of an array such as phrase holds the address of the first element in the array). We would also like to know actual contents of this address. Let’s do this by typing x/xb phrase You should see: (gdb) x/xb phrase 0xbffff800: 0x47 7 (Note: You may see a number slightly different from 0xbffff800, but you should see the value of 0x47. If you do not see the value of 0x47 then STOP and ask your instructor for help.) Let's explain the command you just entered. Recall that the first x invokes the examine command, the second x specifies hexadecimal, and the b asks the debugger to display a single-byte quantity. When the examine command is used with array names or pointer variables (such as phrase, ptr and another_ptr), the first item returned will be the contents of the pointer and the second item returned will be the value that the pointer is pointing to. (gdb) x/xb phrase 0xbffff800: 0x47 The address stored in phrase. The memory contents of this specific address. Question 12. Fill in the picture shown on the answer sheet, showing the contents of phrase, and the hexadecimal value stored in the memory location pointed to by phrase. (Note that this figure will be gradually filled in as we complete this lab; for this question, you are only being asked to show the contents of phrase, and the value stored in the memory location pointed to by phrase.) Question 13. What on earth does that 0x47 represent? Question 14. Determine what is stored at the memory location that phrase contains by examining the memory directly using the command: x/xb 0xbffff800 Question 15. On the same figure as Question 12, fill in the contents of ptr and another_ptr. These are both pointers so your answers should be addresses. Question 16. On the same figure as Question 12, draw arrows showing where phrase, ptr and another_ptr all point to; i.e., draw an arrow from the pointer to the memory location with the corresponding address. Question 17. On the same figure as Question 12, show the hexadecimal values stored in the memory locations pointed to by these three pointers phrase, ptr and another_ptr. Question 18. The pointer named another_ptr seems to be pointing to the value 0x4e. What is that? Question 19. On the same figure as Question 12, fill in the addresses of each byte of main memory depicted on the figure, and fill in the contents of each memory location as ASCII characters. You should do this by using the debugger to examine memory one byte at a time. For example, if I wanted to examine the memory location 0xbffff801 I would enter x/xb 0xbffff801 When you have completed your picture, to Part 7. STOP and show it to your instructor. 8 If correct, you can proceed Part 7: Autopsy of the Program Recall that our program has executed up to but not including line 13. Line 13 is the next to last line of your program – the line that uses strcpy. Now, execute the program (using nexti ) until you show line 14 as the next instruction to execute. In other words, keep entering nexti until you see: 14 printf( "%s\n" , ptr ); It should be the case that you have to enter nexti four times to see the line shown above. Question 20. Fill in the picture shown on the answer sheet in its entirety, showing the memory address of all bytes, the contents of all bytes (as ASCII characters) and the contents of the pointers. Now, the C line of code: printf( "%s\n" , ptr ); goes to the memory address pointed to by ptr, and starts printing out characters in memory, one after another, until a NULL is reached. Question 21. What will be printed out by the next statement (printf( ptr ); )? Question 22. You friend is confused. He says: “We never made any changes involving ptr – we only made changes to another_ptr (using the strcpy command).” So, why did we get different results when we executed the line printf( ptr ); ? How do you reply? We can type out multiple bytes with a single x/xb command by specifying the number of bytes to display. For example, we can print out a single byte starting at the address pointed to by phrase by typing x/xb phrase But, if we want to see, say, 8 bytes of data starting at the address pointed to by phrase, we can type x/8xb phrase Question 23. Explain the meaning of the results that you see when you enter x/8xb phrase. Question 24. Explain the meaning of the results that you see when you enter x/8c phrase. 9 10 Security Exercise 5 Name: _____________________ Question 1: Question 2: Question 3: Question 4: Question 5: Question 6 and Question 10: Question 7: Question 8: Question 9: Question 11: 11 Question 12, Question 15, Question 16, Question 17, Question 19 Question 13: Question 14: Question 18: Question 20: Question 21: Question 22: Question 23: Question 24: 12