Below are the answers for the 760 Prep Quiz answers. For more details about the course and the quiz, please click here.
1) DEP is to ROP as ASLR is to ____ ?
a. Memory leak
b. Stack smash
c. Control Flow Guard
d. JOP
Answer: A - Return Oriented Programming (ROP) can be used to defeat the Data Execution Prevention (DEP) mitigation because existing executable gadgets are used to gain code execution. Therefore the answer is Memory Leak because we can use one to overcome the Address Space Layout Randomization (ASLR) mitigation.
2) What does MSR stand for in the context of a CPU?
a. Memory Standard Resource
b. Model Specific Register
c. Memory-Synchronized Range
d. Mandatory System Routine
Answer: B - Model Specific Registers hold important CPU information and configuration such as the address of the system call handler and VMX settings. Check out the processor (Intel/AMD) for more information on MSRs.
3) What is the following 64-bit x86 assembly doing (assume it is standalone, no prologue etc.)?
call labellabel:
pop rax
sub rax, 5
a. Making a system call
b. Turning off DEP
c. Subverting control flow guard
d. Getting the current execution address
Answer: D - The call instruction jumps to the address or label provided after pushing the return address onto the top of the stack. At "label" the top of the stack is popped into RAX and then 5 is subtracted, which will get the absolute address of the top of this snippet.
4) Which of the following byte sequences can be used as an x86 64-bit ROP gadget (that's not just a ret or ret X)? Hint: use the Shell-Storm disassembler
a. \xff\xc0\x48\x89\xd8\x48\x31\xf6\xcc\xcd\xc2\xcc
b. \xb6\x2d\x1d\x00\x41\x89\xd8\xff\xc3\x31\xc0
c. \x48\x31\xf6\x48\x89\x43\x08\xb3\xc3\x0f\x05
d. \x0f\x85\xed\x00\xb6\x47\x18\xbb\xc2\x74\x36
Answer: B - Using a disassembler the on each bytecode snippet and slowly peeling bytes off of the front one by one, you'll see that the answer is the only one that has other valid instructions before a ret. The others might result in a ret or ret X but it is the only instruction, which is excluded in the question.
5) Which of the following C code snippets will never cause a buffer overflow on Windows?
a. unsigned char *mem = malloc(2); memcpy(mem, userbuffer, 4);
b. RtlCopyMemory(buf, userbuf, userlen);
c. char *str = malloc(stringsize); strncpy(str, userbuffer, stringsize);
d. int len = sprintf(NULL, "fmt %s", userstr); char *str = malloc(len+1); sprintf(str, "fmt %s", userstr);
Answer: A - Surprisingly, this it is not a buffer overflow condition. The minimum allocation size for the Windows heap allocator is 8 bytes on 32-bit Windows and 16 bytes on 64-bit Windows. This means that even though we tell malloc to give us 2 bytes, it is really giving us 8 or 16 bytes. Copying 4 bytes into the buffer is not technically a buffer overflow in this case. The sprintf option is appealing, but passing NULL to the buffer argument of sprintf on Windows will cause the invalid parameter handler routine to be called. If the invalid parameter handler routine is default, it will invoke watson, which will terminate the application. However, if the invalid parameter handler allows execution to continue, then the function will return -1. The malloc will then be called with an argument of 0 (-1+1), which will cause a one block chunk to be allocated, which will be overflown by a sufficiently large userstr. This one is tricky!
6) In what situation(s) must you allocate data on the heap and not the stack in C/C++?
a. When the size of the data is not known at compile time
b. When the data must outlive the current function
c. When the data is larger than 1 page
d. When the data is sensitive
Answer: B - The heap is used for dynamically sized data that may or may not last beyond the end of the current function's stack frame. Variable sized stack allocations are allowed in C so you don't need to allocate variable sized allocations on the heap.
7) Which of the following is not a component of a fuzzer?
a. Mutator
b. Generator
c. Executor
d. These are all fuzzer components
Answer: D - A mutator changes existing input via a mutation strategy (bit flipping, random byte modification, etc.); a generator generates test cases from scratch; and an executor executes a program given the output from the generator so the answer is that they are all potential components of a fuzzer!
8) True or False: In general, all Windows API functions use the stdcall calling convention, where arguments are put in registers (64-bit) and then the stack in reverse order and the caller is responsible for cleaning up the stack space allocated.
Answer: False - The Windows API does use the stdcall calling convention for the most part, but the function that is called (callee) is responsible for cleaning up the stack spaced used via a ret X instruction, where X is the number of bytes to clean up.
9) Which of the following is not a valid way of getting execution from a stack buffer overflow, despite the presence of a canary?
a. Repair the canary
b. Cause an exception before the canary is checked
c. Use a ROP chain to avoid the canary all together
d. Jump to or call an indirect function pointer you control
Answer: C - Since we are talking about a stack overflow, the way to get execution is via overwriting the return pointer. If we cannot get past the canary, we cannot execute any ROP gadgets, so this one won't work. Now, I suppose you could make the case for a different function pointer being on the stack before the canary; in that case ROP would work just fine. The rest are all valid strategies for getting execution in the presence of a canary.
10) Which of the following statements are true regarding the difference between hardware and software breakpoints?
a. Hardware and software breakpoints can only be triggered on code execution
b. Hardware breakpoints cannot be removed with code, while software breakpoints can
c. Hardware breakpoints are set in registers, while software breakpoints are set by overwriting instructions
d. An unlimited number of hardware breakpoints can be set, while only a limited number of software breakpoints can be set
Answer: C - The CPU has hardware debug registers (dr0-dr7) for setting a limited number of hardware breakpoints. Software breakpoints are set by overwriting existing code with a \xCC instruction and then restoring the original byte when the processor goes to execute again. Hardware breakpoints can be set to trigger on execute, read, or write of a memory location, while software breakpoints only work on execution. Both can also be removed with code, though the method to remove each is different (setting registers vs. overwriting memory).