New York University
Computer Science Department Courant Institute of Mathematical Sciences
Course Title: Computer Systems Organization Instructor: Jean-
Course Number: CSCI-UA.0201-005 Session: 9
Copyright By PowCoder代写 加微信 powcoder
Machine Level Programming
April 18, 2022 at the beginning of class.
Objectives
The purpose of this programming lab is for you to become more familiar with assembly language, memory layout, security vulnerabilities, and machine level programs debugging. You will achieve this by working on a couple of problems that require extensive use of gdb.
References
Slides and handouts posted on the course Web site for sessions 10-19 Textbook Part I Chapter 3
Lab2 material downloadable from the Cloud.
Software Required
Microsoft Word.
WinZip as necessary.
Linux utilities and programs as needed (e.g., tar, gcc, make, gdb)
Important: You should do all your work on Linux machines to which you have access within the CIMS cluster (please follow the instructions/PDF you received at the beginning of the semester, you should have access to the access or linserv1 server to work on the labs).
Assignment Steps and Questions
Binary Bomb Defusal:
A binary bomb is a program that consists of a sequence of phases. Each phase expects you to type a particular string on stdin. If you type the correct string, then the phase is defused and the bomb proceeds to the next phase. Otherwise, the bomb explodes and terminates. The bomb is defused when every phase has been defused. Your mission is to defuse one bomb before the due date.
You can obtain your bomb by navigating to a Microsoft server located at the following URL: http://40.124.53.8:15213/. Enter your username (i.e., your NYU CIMS ID) and email address (i.e., your nyu.edu email) and hit the Submit button on the form. The server will build a bomb and return it to your browser in a tar file called bombk.tar, where k is the unique number of your bomb. Save the bombk.tar file to a (protected) directory in which you plan to do your work. Then give the command: tar -xvf bombk.tar. This will createadirectorycalled./bombkcontainingthefollowing files:README(identifiesthebomb and its owner), bomb (the executable binary bomb), bomb.c routine and a friendly greeting). If for some reason you request multiple bombs, this is not a problem. Choose one bomb to work on and delete the rest.
You must perform this assignment on the access2.cims.nyu.edu server. The bomb will always explode if run elsewhere and there are several other tamper-proofing devices built into the bomb. You can use many tools to help you defuse your bomb and the best way is to use your favorite debugger to step through the disassembled binary. Each time your bomb explodes it notifies the server, and you lose points in the final score for this problem. Phases 5 and 6 are a little more difficult than the first four phases and are worth more points. Although phases get progressively harder to defuse, the expertise you gain as you move from phase to phase should offset this difficulty. The bomb ignores blank input lines. If you run your bomb with a command line argument (e.g., ./bomb mysol.txt), it will read the input lines from mysol.txt until it reaches EOF (end of file), and then switch over to stdin so you do not have to keep retyping the solutions to phases you have already defused. To avoid accidentally detonating the bomb, you will need to single-step through the assembly code and set breakpoints. You will also need to inspect both the registers and the memory states.
You need to provide screenshots and explanations in your report for this problem. Clarifications and corrections may be posted via the course NYU Classes Google Group. Please note that the bomb will notify your instructor automatically about your progress as you work on this problem. You can keep track of how you are doing by looking at the scoreboard at: http://40.124.53.8:15213/scoreboard. This web page is updated continuously to show your progress defusing each bomb. Your final grade for this problem is a combination of the corrected and quality of the report you submit and your performance in defusing the bomb as per the self-grading scoreboard.
There are many ways of defusing your bomb. You can examine the program in great detail before running it and figure out exactly what it does. You can also run the program using a debugger, watch what it does step by step, and use this information to defuse the bomb. Using a debugger is probably the fastest way of defusing the bomb. Please do not try and use a approach by writing a program that will try every possible key to find the right one. This will not work as every time you guess wrong a message will be sent to the server and you will lose points when the bomb explodes. You could also very quickly saturate the network with messages using a brute force approach and cause the system administrators to revoke your server access. Finally, a brute force approach will not work because you do not know how long the strings are and what characters are in them. Note that even if you made the (incorrect) assumptions that all the strings are less than 80 characters long and only contain
letters, you would have 2680 guesses for each phase. Therefore, a brute approach force would take a very long time to run, and you would not get the answer before the midterm submission deadline.
The best way to defuse your bomb is to use tools that are designed to help you figure out both how programs work, and what is wrong when they work. In particular, the GNU debugger gdb can trace through a program line by line, examine memory and registers, look at both the source code and assembly code (note that you are not given the source code for all the functions in your program), set breakpoints, set memory watch points, and writescripts. Please leverage the gdb resources provided on the course website. To keep the bomb from exploding every time you type in a wrong input, you will need to set breakpoints. For online documentation, help . You can also man gdb info gdb the Linux prompt. You may also run gdb under gdb-mode in emacs if you are familiar with that editor. Another useful tool is objdump and you can print out the symbol table via objdump -t. The symbol table includes the names of all the functions and global variables within the bomb. It also includes the names of all the functions that are called by the bomb as well as their addresses. You may learn something by looking at the function names. Also, objdump -d can be used to disassemble all of the code within the bomb. You can then look at individual functions and reading the assembly language code can tell you how the bomb works.Notethat,althoughobjdump-d givesyoualotofinformation,itdoesnottellyou everything you need to know as calls to system-level functions are displayed in a cryptic form. For example, a call to sscanf might appear as 8048c36: e8 99 fc ff ff call 80488d4 <_init+0x1a0>. Therefore, to determine that the call was to sscanf, you would need to disassemble the program within gdb. Finally, another useful utility is strings, which will display the printable strings in your bomb. Do documentation using the commands apropos, man, and info. In particular, man ascii might be handy. info gas will give you more information than you ever wanted to know about the GNU assembler.
2. Security Exploits Programming:
There are several ways for attackers to exploit security vulnerabilities when programs do not safeguard themselves well enough against buffer overflows. It is therefore important to understand how to write programs that are more secure and use some of the features provided by compilers and operating systems to make programs less vulnerable to attacks at runtime. As part of this problem, you need to generate a total of five attacks on two programs that are custom generated for you and have different security vulnerabilities. This problem tests your understanding of the stack and parameter-passing mechanisms of x86-64 machine code, x86- 64 instructions encodings, and debugging tools such as gdb and objdump.You may also want to review sections 3.10.3 and 3.10.4 of the course textbook.
You can obtain your custom generated files by navigating to a Microsoft server located at the following URL: http://40.124.53.8:15515. The server will create your files and return them to your browser in a tar file called targetk.tar, where k is the unique number of your target programs (note that it takes a few seconds to build and download your
target, so please be patient). Save the targetk.tar file to a (protected) directory in which you plan to do your work. Then give the command: tar -xvf targetk.tar (do not use WinZip or let your browser extract the files as you will risk resetting permission bits on the executable files). This will create a directory called ./targetk containing the following files: README.txt (describes the contents of the directory), ctarget (an executable program vulnerable to code-injection attacks), rtarget (an executable program vulnerable to return- oriented-programming attacks), cookie.txt (an 8-digit hex code that you will use as a unique identifier in your attacks), farm.c ( will use in generating return-oriented programming attacks), and hex2raw (a utility to generate attack strings). If for some reason you download multiple targets, this is not a problem. Choose one target to work on and delete the rest. The following assumes that you have copied the files to a protected local directory on the access2.cims.nyu.edu server, and that you are executing the programs in that local directory as it is necessary to use a machine that is similar to the one that generated your targets.
Target Programs Information:
Bothctargetandrtargetreadstringsfromstandardinput. Theydosowiththefunction getbuf defined below:
unsigned getbuf()
char buf[BUFFER_SIZE]; Gets(buf);
The function Gets is similar to the standard library function gets, it reads a string from \n -of-file) and stores it (along with a null terminator) at the specified destination. In the code shown above, you can see that the destination is an array buf, declared as having BUFFER_SIZE bytes. At the time your targets were generated, BUFFER_SIZE was a compile-time constant specific to your version of the programs. Functions Gets() and gets() have no way to determine whether their destination buffers are large enough to store the string they read. They simply copy sequences of bytes, possibly overrunning the bounds of the storage allocated at the destinations. If the string typed by the user and read by getbuf is sufficiently short, it is clear that getbuf will return 1, as shown by the following execution examples:
access2> ./ctarget
Cookie: 0x1a7dd803
Type string: Keep it short!
No exploit.Getbuf returned 0x1 Normal return
Typically an error occurs if you type a long string:
access2> ./ctarget
Cookie: 0x1a7dd803
Type string: This is not a very interesting string, but it has the property …
Ouch!: You caused a segmentation fault!
Better luck next time
Note that the value of the cookie shown will differ from yours. Program rtarget will have the same behavior. As the error message indicates, overrunning the buffer typically causes the program state to be corrupted, leading to a memory access error. Your task is to be more clever with the strings you feed ctarget and rtarget so that they do more interesting things. These are called exploit strings.
Both ctarget and rtarget take several different command line arguments:
-h: Print list of possible command line arguments
-q: Microsoft Azure server
-i FILE: Supply input from a file, rather than from standard input
Your exploit strings will typically contain byte values that do not correspond to the ASCII values for printing characters. The program hex2raw will enable you to generate these raw strings. See Section 2.3 (part A) for more information on how to use hex2raw.
Important points:
Your exploit string must not contain byte value 0x0a at any intermediate position, \n Gets encounters this byte, it will assume you intended to terminate the string.
hex2raw expects two-digit hex values separated by one or more white spaces. So if you want to create a byte with a hex value of 0, you need to write it as 00. To create the word 0xdeadbeef ef be ad de hex2raw (please note the reversal required for little-endian byte ordering).
When you have correctly solved one of the levels, your target program will automatically send a notification to the Microsoft Azure server. For example:
access2> ./hex2raw < ctarget.l2.txt | ./ctarget
Cookie: 0x1a7dd803
Type string:Touch2!: You called touch2(0x1a7dd803) Valid solution for level 2 with target ctarget
PASSED: Sent exploit string to server to be validated. NICE JOB!
You need to provide screenshots and explanations in your report as part of your solution to this problem. Clarifications and corrections may be posted via the course NYU Classes Google Group. The Microsoft Azure server will test your exploit string to make sure it really works, and it will update the attacklab scoreboard page indicating that your userid (listed by your target number for anonymity) has completed this phase. You can view the scoreboard at http://40.124.53.8:15515/scoreboard.This web page is updated continuously to show your progress. Different from the previous problem, there is no penalty for making mistakes in this problem, therefore feel free to fire away at ctarget and rtarget with any strings you like. You can work on your solution on any Linux machine, but in order to submit your solution, you will need to be running it on access2.cims.nyu.edu. Your final grade for this problem is a combination of the quality and correctness of the report you submit and the progress recorded via the self- grading scoreboard.
Figure 1 below summarizes the five phases to follow to solve this problem. As can be seen, the first three involve code-injection (CI) attacks on ctarget, while the last two involve return-oriented-programming (ROP) attacks on rtarget.
Figure 1: Summary of attack lab phases
2.1. Code Injection Attacks
For the first three phases, your exploit strings will attack ctarget. This program is set up in a way that the stack positions will be consistent from one run to the next and so that data on the stack can be treated as executable code. These features make the program vulnerable to attacks where the exploit strings contain the byte encodings of executable code.
2.1.1. Level 1
For Phase 1, you will not inject new code. Instead, your exploit string will redirect the program to execute an existing procedure.
Function getbuf is called within ctarget by a function test having the following C code:
void test() {
val = getbuf();
printf("No exploit. Getbuf returned 0x%x\n", val);
When getbuf executes its return statement (line 5 of getbuf), the program ordinarily resumes execution within function test (at line 5 of this function). We want to change this behavior. Within the file ctarget, there is code for a function touch1 having the following C representation:
void touch1()
vlevel = 1; /* Part of validation protocol */ printf("Touch1!: You called touch1()\n"); validate(1);
Your task is to get ctarget to execute the code for touch1 when getbuf executes its return statement, rather than returning to test. Note that your exploit string may also corrupt parts of the stack not directly related to this stage, but this will not cause a problem, since touch1 causes the program to exit directly.
Some Advice:
All the information you need to devise your exploit string for this level can be determined by examining a disassembled version of ctarget. Use objdump -d to get this dissembled version.
The idea is to position a byte representation of the starting address for touch1 so that the ret instruction at the end of the code for getbuf will transfer control to touch1.
Be careful about byte ordering.
You might want to use gdb to step the program through the last few instructions of
getbuf to make sure it is doing the right thing.
The placement of buf within the stack frame for getbuf depends on the value of
compile-time constant BUFFER_SIZE, as well the allocation strategy used by gcc. You will need to examine the disassembled code to determine its position.
2.1.2. Level 2
Phase 2 involves injecting a small amount of code as part of your exploit string. Within the file ctarget there is code for a function touch2 having the following C representation:
void touch2(unsigned val)
vlevel = 2; /* Part of validation protocol */ if (val == cookie) {
printf("Touch2!: You called touch2(0x%.8x)\n", val);
validate(2);
printf("Misfire: You called touch2(0x%.8x)\n", val);
fail(2); }
exit(0); }
Your task is to get ctarget to execute the code for touch2 rather than returning to test. In this case, however, you must make it appear to touch2 as if you have passed your cookie as its argument.
Some Advice:
You will want to position a byte representation of the address of your injected code in such a way that the ret instruction at the end of the code for getbuf will transfer control to it.
Recall that the first argument to a function is passed in register %rdi.
Your injected code should set the register to your cookie, and then use a ret
instruction to transfer control to the first instruction in touch2.
Do not attempt to use jmp or call instructions in your exploit code. The encodings of destination addresses for these instructions are difficult to formulate. Use ret
instructions for all transfers of control, even when you are not returning from a call.
See the discussion in Section 2.3 (part B) on how to use tools to generate the byte-
level representations of instruction sequences.
2.1.3. Level 3
Phase 3 also involves a code injection attack but passing a string as argument. Within the file ctarget there is code for functions hexmatch and touch3 having the following C representations:
/* Compare string to hex represention of unsigned value */ int hexmatch(unsigned val, char *sval)
char cbuf[110];
/* Make position of check string unpredictable */ char *s = cbuf + random() % 100;
sprintf(s, "%.8x", val);
return strncmp(sval, s, 9) == 0;
void touch3(char *sval)
vlevel = 3; /* Part of validation protocol */ if (hexmatch(cookie, sval)) {
printf("Touch3!: You called touch3(\"%s\")\n", sval);
validate(3);
printf("Misfire: You called touch3(\"%s\")\n", sval);
fail(3); }
exit(0); }
Your task is to get ctarget to execute the code for touch3 rather than returning to test. You must make it appear to touch3 as if you have passed a string representation of your cookie as its argument.
Some Advice:
You will need to include a string representation of your cookie in your exploit string. The string should consist of the eight hexadecimal digits (ordered from most to least 0x
Recall that a string is represented in C as a sequence of bytes followed by a byte with man ascii of the characters you need.
Your injected code should set register %rdi to the address of this string.
When functions hexmatch and strncmp are called, they push data onto the stack, overwriting portions of memory that held the buffer used by getbuf. As a result, you
will need to be careful where you place t
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com