Last Updated: 2021-10-22 Fri 15:54
CSCI 2021 Project 3: Assembly Coding and Debugging
Due: 11:59pm Wed 11/10/2021 on Gradescope
Approximately 3.0-4.0% of total grade
Projects are individual work: no collaboration with other students is allowed. Seek help from course staff if you get stuck
for too long.
CODE/TEST DISTRIBUTION: p3-code.zip
CHANGELOG:
Fri Oct 22 03:48:42 PM CDT 2021
Fixed a few bad references from a old version of the project (set_display_from_tod() rather than
set_display_bits_from_tod()). Added a note about overcoming difficulties in division.
Table of Contents
1. Introduction
2. Download Code and Setup
3. Problem 1: Clock Display Assembly Functions
3.1. Hand-Code Your Assembly
3.2. General Cautions when coding Assembly
3.3. Iterative Development Strategy
3.4. Structure of clock_update_asm.s
3.5. set_tod_from_secs()
3.6. set_display_from_tod
3.7. clock_update
3.8. Grading Criteria for Problem 1
4. Problem 2: The Binary Bomb
4.1. Quick Links
4.2. Overview
4.3. Machines on which bombs run
4.4. Bomb Download and Setup
4.5. Scoring and Scoreboard (50%)
4.6. WARNING on Downloading Multiple Bombs
4.7. Advice
1 Introduction
This project will feel somewhat familiar in that it is nearly identical to the preceding project: there is a coding problem and a
puzzle-solving problem. The major change is that everything is at the assembly level:
Problem 1 re-works the Clock functions from the previous project in x86-64 Assembly rather than C
Problem 2 involves analyzing a binary executable to provide it with the correct input to “defuse” the executable much like
the previous project’s Puzzlebox problem
Working with assembly will get you a much more acquainted with the low-level details of the x86-64 platform and give you a
greater appreciation for “high-level” languages (like C).
2 Download Code and Setup
https://www.gradescope.com/
https://www-users.cse.umn.edu/~kauffman/2021/p3-code.zip
Download the code pack linked at the top of the page. Unzip this which will create a project folder. Create new files in this folder.
Ultimately you will re-zip this folder to submit it.
File State Notes
Makefile Provided Problem 1 Build file
clock.h Provided Problem 1 header file
clock_main.c Provided Problem 1 main() function
clock_sim.c Provided Problem 1 simulator functions
clock_update_asm.s CREATE Problem 1 Assembly functions, re-code C in x86-64, main file to edit for problem 1
clock_update.c CREATE Problem 1 C functions, COPY from Project 2 or see a staff member to discuss
test_clock_update.c Testing Problem 1 testing program for update functions
test_clock.org Testing Problem 1 testing data file
test_hybrid.org Testing Problem 1 testing data file for mixed C/Assembly
testy Testing Problem 1 test running script
bombNN.zip Download Problem 2 Debugging problem, download from server
bombNN/ Directory Created by unzip bombNN.zip and contains the below files
bombNN/bomb.c Unpack Problem 2 main() for bomb
bombNN/bomb Unpack Problem 2 Executable to debug: this is the important one
bombNN/README Unpack Problem 2 Describes “owner” of the bomb
input.txt Edit Problem 2 Input for bomb, fill this in to defuse stages
3 Problem 1: Clock Display Assembly Functions
The functions in this problem are identical to a previous project in which code to support an LCD clock display was written.
These functions are:
int set_tod_from_secs(int time_of_day_sec, tod_t *tod)
Given the number of seconds from the start of the day, set the fields of the struct pointed to by tod to have the correct
hours, minutes, seconds, and pm indication.
int set_display_from_tod(tod_t tod, int *display)
Given a tod_t struct, reset and alter the bits pointed to by display to cause a proper clock display.
int clock_update()
Update global CLOCK_DISPLAY_PORT using the TIME_OF_DAY_SECS. Call the previous two functions.
The big change in this iteration will be that the functions must be written in x86-64 assembly code. As C functions each of these is
short, up to 85 lines maximum. The assembly versions will be somewhat longer as each C line typically needs 1-4 lines of assembly
code to implement fully. Coding these functions in assembly give you real experience writing working assembly code and working
with it in combination with C.
The code setup and tests are mostly identical for this problem as for the previous C version of the problem. Refer to original
Clock LCD Display Problem description for a broad overview of the simulator and files associated with it.
3.1 Hand-Code Your Assembly
https://www-users.cs.umn.edu/~kauffman/2021/p2.html
As discussed in class, one can generate assembly code from C code with appropriate compiler flags. This can be useful for getting
oriented and as a beginning to the code your assembly versions of the functions. However, code that is clearly compiler-generated
with no hand coding will receive 0 credit.
No credit will be given on manual inspection
Penalties will be assessed for Automated Tests which lower credit to 0
Do not let that dissuade you from looking at compiler-generated assembly code from you C solution to the functions. Make sure
that you take the following steps which are part of the manual inspection criteria.
Base your Assembly code on your C code
The files to be submitted for this problem include
clock_update.c: C version of the functions
clock_update_asm.s: Assembly version of the functions
Graders may examine these for a correspondence between to the algorithm used in the C version to the Assembly version.
Compiler generated assembly often does significant re-arrangements of assembly code with many intermediate labels that hand-
written code will not have.
If you were not able to complete the C functions for the Project 2 display problem from the previous project, see a course staff
member who will help you get them up and running quickly.
Annotate your Assembly Thoroughly
Comment your assembly code A LOT. While good C code can be quite self-explanatory with descriptive variable names and clear
control structures, assembly is rarely so easy to understand. Include clear commentary on your assembly. This should include
Subdividing functions into smaller blocks with comments describing what the blocks accomplish.
Descriptions of which “variables” from the C side are held in which registers.
Descriptions of most assembly lines and their effect on the variables held in the registers.
Descriptions of any data such as bitmasks stored in the assembly code.
Use informative label names like .ROUNDING_UP to convey further meaning about what goals certain positions in code
are accomplishing.
Use Division
While it is a slow instruction that is cumbersome to set up, using idivX division instruction is the most human-readable means
to compute several results needed in the required functions. Compiler generated code uses many tricks to avoid integer division so
a lack of idivX instructions along this line will be a clear sign little effort has been put into the assembly code.
3.2 General Cautions when coding Assembly
1. Get your editor set up to make coding assembly easier. If you are using VS Code, the following video will show you how to
install an extension to do syntax highlighting and block comment/uncomment operations in assembly:
2. Be disciplined about your register use: comment what “variables” are in which registers as it is up to you to keep track.
The #1 advice from past students to future students is “Comment the Crap out of your assembly code” on this project.
3. Be Careful with constants: forgetting a $ in constants will lead to a bare, absolute memory address which will likely
segfault your program. Contrast:
movq $0,%rax # rax = 0
movq 0, %rax # rax = *(0): segfault
# bare 0 is memory address 0 – out of bound
Running your programs, assembly code included, in Valgrind can help to identify these problems. In Valgrind output, look
for a line number in the assembly code which has absolute memory addresses or a register that has an invalid address.
4. Recognize that in x86-64 function parameters are passed in registers for up to 6 arguments. These are arranged as follows
1. rdi / edi / di (arg 1)
2. rsi / esi / si (arg 2)
3. rdx / edx / dx (arg 3)
4. rcx / ecx / cx (arg 4)
5. r8 / r8d / r8w (arg 5)
6. r9 / r9d / r9w (arg 6)
and the specific register corresponds to how argument sizes (64 bit args in rdi, 32 bit in edi, etc). The functions you will
write have few arguments so they will all be in registers.
5. Use registers sparingly. The following registers (64-bit names) are “scratch” registers or “caller save.” Functions may alter
them freely (though some may contain function arguments).
rax rcx rdx rdi rsi r8 r9 r10 r11 # Caller save registers
No special actions need to be taken at the end of the function regarding these registers except that rax should contain
the function return value.
Remaining registers are “callee save”: if used, their original values must be restored before returning from the function.
rbx rbp r12 r13 r14 r15 # Callee save registers
This is typically done by pushing the callee registers to be used on the stack, using them, them popping them off the stack
in reverse order. Avoid this if you can (and you probably can in our case).
6. Be careful to adjust the stack pointer using pushX/popX or subq/addq . Keep in mind the stack must be aligned to 16-
byte boundaries for function calls to work correctly. Above all, don’t treat rsp as a general purpose register.
7. When using the idivX instruction, incorrect results can be included if you don’t fully extend the sign of the ax-family
register. As demoed in the assembly basics lecture, the right way to do this for a 16-bit value and a 64-bit division is as
follows:
Using different sequences or small division like idivw may work but many students have encountered problems when not
following the above sequence.
For reference, here is a picture that appears in the lecture slides that summarizes the names and special uses for the registers in
x86-64.
movw $-17, %ax # load rax with a 16-bit value
cwtl # extend sign to eax
cltq # extend sign to rax
cqto # extend sign across to rdx
movq $3, %rcx # set up divisor in rcx
idivq %rcx # perform division of -17 / 3
Figure 1: Summary of general purpose register usages in x86-64.
3.3 Iterative Development Strategy
With working C versions of the three required functions, you should be able to employ an iterative strategy while developing
assembly versions: focus on one assembly function while using working C functions for the remaining code. The Makefile and
support code are specifically set up for this and details iterative development are as follows.
1. In clock_update_asm.s, comment all code/declarations of global symbols except for set_tod_from_sec.
2. In clock_update.c, comment out the definition of the set_tod_from_sec() function. This leaves working C
versions of the other two functions.
3. Write some assembly code for set_tod_from_sec. Attempt to compile it on its own with
> make clock_update_asm.o
gcc -Wall -Werror -g -c clock_update_asm.s
which will report assembler errors if any are present.
4. When there appear to be no assembler errors, create a hybrid main program which will combine the uncommented
assembly and C functions
5. One can then experiment with the hybrid_main to see if the written assembly function is working correctly.
Something clearly looks wrong in the above so some debugging of the assembly function seems in order.
6. When ready, run the “hybrid tests” which will do automated testing on the hybrid codes.
7. When all seems to be working correctly with the first assembly function, move on. Comment another C function and
uncomment the corresponding assembly, write some code and repeat.
3.4 Structure of clock_update_asm.s
Below is a rough outline of the structure of required assmebly file. Consider copying this file as you get started and commenting
parts of it out as needed.
>> make hybrid_main
gcc -Wall -Wno-comment -Werror -g -c clock_main.c
gcc -Wall -Wno-comment -Werror -g -c clock_sim.c
gcc -Wall -Wno-comment -Werror -g -c clock_update_asm.s
gcc -Wall -Wno-comment -Werror -g -c clock_update.c
gcc -Wall -Wno-comment -Werror -g -o hybrid_main clock_main.o clock_sim.o clo
>> ./hybrid_main 3812
TIME_OF_DAY_SEC set to: 3812
result = set_tod_from_secs( 3812, &tod );
result: 0
tod = {
.hours = -15
.minutes = 0
.seconds = 1206
.ampm = 17
}
…
>> make test-hybrid
gcc -Wall -Wno-comment -Werror -g -o test_hybrid_update test_clock_update.o c
…
./testy test_hybrid.org
============================================================
== test_hybrid.org : Problem 1 test_hybrid_update and hybrid_main tests
== Running 35 / 35 tests
1) test_hybrid_update tod-midnight : ok
2) test_hybrid_update tod-after-midnight : ok
3) test_hybrid_update tod-after-1am : ok
4) test_hybrid_update tod-nearly-noon : ok
5) test_hybrid_update tod-is-noon : ok
…
.text
.global set_tod_from_secs
## ENTRY POINT FOR REQUIRED FUNCTION
set_tod_from_secs:
## assembly instructions here
3.5 set_tod_from_secs()
Note that this function uses a tod_t struct which is in clock.h described here:
Assembly Implementation Notes set_tod_from_secs
## a useful technique for this problem
movX SOME_GLOBAL_VAR(%rip), %reg # load global variable into register
# use movl / movq / movw / movb
# and appropriately sized destination
### Data area associated with the next function
.data
my_int: # declare location an single int
.int 1234 # value 1234
other_int: # declare another accessible via name ‘other_int’
.int 0b0101 # binary value as per C ‘0b’ convention
my_array: # declare multiple ints in a row
.int 10 # for an array. Each are spaced
.int 20 # 4 bytes from each other
.int 30
.text
.global set_display_from_tod
## ENTRY POINT FOR REQUIRED FUNCTION
set_display_from_tod:
## assembly instructions here
## two useful techniques for this problem
movl my_int(%rip),%eax # load my_int into register eax
leaq my_array(%rip),%rdx # load pointer to beginning of my_array into r
.text
.global clock_update
## ENTRY POINT FOR REQUIRED FUNCTION
clock_update:
## assembly instructions here
int set_tod_from_secs(int time_of_day_sec, tod_t *tod);
// Accepts time of day in seconds as an argument and modifies the
// struct pointed at by tod to fill in its hours, minutes,
// etc. fields. If time_of_day_sec is invalid (negative or larger
// than the number of seconds in a day) does nothing to tod and
// returns 1 to indicate an error. Otherwise returns 0 to indicate
// success. This function DOES NOT modify any global variables
//
// CONSTRAINT: Uses only integer operations. No floating point
// operations are used as the target machine does not have a FPU.
// Breaks time down into 12-hour format
typedef struct{
short hours;
short minutes;
short seconds;
char ampm;
} tod_t;
1. The function takes two arguments
an int which will be in register edi
a pointer which will be in rsi.
Note the 32-bit versus 64-bit registers.
2. Return values or functions are to be placed eax for 32 bit quantities as is the case here (int).
3. Use comparisons and jump to a separate section of code that is clearly marked as “error” if you detect a bad arguments.
4. Make use of division to “break down” the argument time_of_day_secs. Keep in mind that the idivl instruction
must have eax as the dividend, edx zeroed out. Any 32-bit register can contain the divisor. After the instruction, eax
will hold the quotient and edx the remainder. With cleverness, you’ll only need to do a couple divisions.
5. A pointer to a tod_t struct can access its fields using the following offset table which assume that %reg holds a pointer
to the struct (substitute an actual register name).
Destination Assembly
C Field Access Offset Size Assign 5 to field
tod->hours 0 bytes 2 bytes movw $5,0(%reg)
tod->minutes 2 bytes 2 bytes movw $5,2(%reg)
tod->seconds 4 bytes 2 bytes movw $5,4(%reg)
tod->ampm 6 bytes 1 byte movb $5,6(%reg)
You will need to use these offsets to set the fields of the struct near the end of the routine.
3.6 set_display_from_tod
Assembly Implementation Notes set_display_from_tod
1. Arguments will be
a packed tod_t struct in %rdi
an integer pointer in rsi
2. The packed tod_t struct is entirely in the 64-bit %rdi register which has the following layout.
Bits Shift
C Field Access in %rdi Required Size
tod.hours 00-15 None 2 bytes
tod.minutes 16-31 Right by 16 2 bytes
tod.seconds 32-47 Right by 32 2 bytes
int set_display_from_tod(tod_t tod, int *display);
// Accepts a tod and alters the bits in the int pointed at by display
// to reflect how the LCD clock should appear. If any fields of tod
// are negative or too large (e.g. bigger than 12 for hours, bigger
// than 59 for min/sec), no change is made to display and 1 is
// returned to indicate an error. Otherwise returns 0 to indicate
// success. This function DOES NOT modify any global variables
//
// May make use of an array of bit masks corresponding to the pattern
// for each digit of the clock to make the task easier.
Bits Shift
C Field Access in %rdi Required Size
tod.ampm 48-57 Right by 48 1 byte
To access individual fields of the struct, you will need to do shifting and masking to extract the values from the rdi
register.
3. Use comparisons and jump to a separate section of code that is clearly marked as “error” if you detect bad fields in the
tod struct argument.
4. As was the case in the C version of the problem, it is useful to create a table of bit masks corresponding to the bits that
should be set for each clock digit (e.g. digit “1” has bit patter 0b0000110). In assembly this is easiest to do by using a
data section with successive integers. An example of how this can be done is below.
Adapt this example to create a table of useful bit masks for digits. The GCC assembler understands binary constants
specified with the 0b0011011 style syntax.
5. Make use of division again to compute “digits” for the ones and tens place of the hours and minutes for the clock. Use
these digits to reference into the table of digit bit masks you create to progressively build up the correct bit pattern for the
clock display.
6. Use shifts and ORs to combine the digit bit patterns to create the final clock display bit pattern.
3.7 clock_update
Assembly Implementation Notes for clock_update
1. No arguments come into the function.
.section .data
array: # an array of 3 ints
.int 200 # array[0] = 200
.int 300 # array[1] = 300
.int 400 # array[3] = 400
const:
.int 17 # special constant
.section .text
.globl func
func:
leaq array(%rip),%r8 # r8 points to array, rip used to enable re
movq $2,%r9 # r9 = 2, index into array
movl (%r8,%r9,4),%r10d # r10d = array[2], note 32-bit movl and des
movl const(%rip),%r11d # r11d = 17 (const), rip used to enable rel
int clock_update();
// Examines the TIME_OF_DAY_SEC global variable to determine hour,
// minute, and am/pm. Sets the global variable CLOCK_DISPLAY_PORT bits
// to show the proper time. If TIME_OF_DAY_SEC appears to be in error
// (to large/small) makes no change to CLOCK_DISPLAY_PORT and returns 1
// to indicate an error. Otherwise returns 0 to indicate success.
//
// Makes use of the set_tod_from_secs() and
// set_display_from_tod() functions.
//
// CONSTRAINT: Does not allocate any heap memory as malloc() is NOT
// available on the target microcontroller. Uses stack and global
// memory only.
2. To access global symbols/variables which are not defined in the assembly file, use the relative position from the
instruction pointer register which allows the linker to handle the task. Specifically relevant examples are
3. Call the two previous functions to create the struct and manipulate the bits of an the display. Calling a function requires
that the stack be aligned to 16-bytes; there is always an 8-byte quantity on the stack (previous value of the rsp stack
pointer). This means the stack must be extended with a pushq instruction before any calls. A typical sequence is
4. If several function calls will be made, a single push is all that is needed as in the below
5. In order to call the set_tod_from_secs() function, this function will need to allocate space on the stack for a
tod_t. As described previously, this struct can be packed to fit in 8 bytes so a pushq $0 will put a “zero” tod_t struct
on the stack and %rsp is then a pointer to it which can be copied to other registers.
6. Similarly, to call the set_display_from_tod() function, one will need a packed tod_t in a register. If the
preceding set_tod_from_secs() call succeeded, this packed struct can be read from memory into a register with a
movq instruction. That stack space can re-used if needed.
7. Keep in mind that you will need to do error checking of the return values from the two functions: if they return non-zero
values jump to a clearly marked “error” section and return a 1. If an error occurs, don’t forget to pop any values off the
stack that have been pushed before returning.
3.8 Grading Criteria for Problem 1 grading 50
Weight Criteria
AUTOMATED TESTS
35 make test-prob1 which uses programs test_clock_update and clock_main
Provides 35 tests for functions in clock_update_asm.s
1 point per test passed
Note: can run make test-hybrid to run tests on mixed C/assembly during development but this
will not be done for evaluation so ensure that make test-prob1 compiles and produces results.
MANUAL INSPECTION CRITERIA
movl TIME_OF_DAY_SEC(%rip), %edx # copy global var to reg edx
movl %r8d,CLOCK_DISPLAY_PORT(%rip) # copy reg r8d to global var
pushq %rdx # push any 64-bit register onto the stack
call some_func # stack aligned, call function
## return val from func in rax or eax
popq %rdx # restore the stack
pushq %rdx # push any 64-bit register onto the stack
call some_func1 # stack aligned, call function
## return val from func in rax or eax
## do some more stuff
call some_func2 # stack aligned, call function
## return val from func in rax or eax
popq %rdx # restore the stack
Weight Criteria
5 General Criteria for all Functions
Clear signs of hand-crafted assembly are present.
Detailed documentation/comments are provided showing the algorithm used in the assembly
There is a clear relation of the code to the C algorithm used in clock_update.c
Use of good label names to indicate jump targets: .NEG_SECS is good, .L32 is bad
High-level variables and registers they occupy are documented in comments
Error checking on the input values is done with a clear “Error” section/label for each function
Any callee save registers used (rbx rbp r12 r13 r14 r15) are pushed at the top of functions and popped at
the end
5 set_tod_from_ports()
Clear use of the division instruction to compute the seconds, minutes, hours
There is a clearly documented section which updates struct fields in memory
No function calls are made that would alter the stack contents
10 set_display_from_clock()
There is a clearly documented .data section in assembly setting up useful tables of bitmasks
Struct fields are unpacked from an argument register using shift operations
The idivX instruction is used to compute quotients and remainders that are needed.
No function calls are made that would alter the stack contents
5 clock_update()
Memory is pushed onto the stack for local variables that must be passed by reference
Function calls to the earlier two functions are made with appropriate arguments passed
The stack is properly aligned at an 8-byte boundary for function calls, likely through a subq/pushq
Changes to the stack for local variables / alignment are undone via a complementary addq/popq instruction
NOTE: Passing all tests and earning all manual inspection criteria will earn up to 10 Points of Project Makeup Credit which will
offset past and future loss of credit on projects.
4 Problem 2: The Binary Bomb
4.1 Quick Links
Available only on Lab Machines or Vole
Download Bombs http://atlas.cselabs.umn.edu:15213/
Score Board http://atlas.cselabs.umn.edu:15213/scoreboard
2021 GDB Quick Guide/Assembly https://www-users.cs.umn.edu/~kauffman/2021/gdb.html
More details on these are described in subsequent sections.
4.2 Overview
The nature of this problem is similar to the previous project’s puzzlebox: there is a program called bomb which expects certain
inputs from a parameter file or typed as input. If the inputs are “correct”, a phase will be “defused” earning points and allowing
access to a subsequent phases. The major change is that the bomb program is in binary so must be debugged in assembly.
Below is a summary of useful information concerning the binary bomb.
Bombs are Individual
The bomb you will download contains subtle variations so that the solution to yours will not work on other bombs. Feel
free to discuss general techniques with classmates but know that you’ll need to ultimately defuse your own bomb.
Bombs are Binary
A small amount of C code with the main() function is included but the bulk of the code is binary which will require
using gdb to debug the assembly code.
Bombs only Run on Lab Machines
To stay in contact with the scoring server, bombs won’t run on your laptop. You’ll need to work on them on lab machines.
Bombs Take Input
Similar to puzzlebox, create an input.txt file which will contain your answers. Run bombs with this input file. Note
that if the bomb runs out of input, you can type input directly into the bomb though this may look a little funny in the
debugger.
Defusing Phases Earns Points
As with the earlier puzzlebox, points for this problem are earned based on how many phases are completed. Each
phase that is completed will automatically be logged with the scoring server
Bomb Explosions Lose Points
If incorrect input is entered and the bomb runs to completion, it will “explode” which causes credit to be deducted. See the
scoring system for details. This can be prevented by setting breakpoints prior to the explosion sequence and restarting the
bomb when those breakpoints are hit.
Use GDB to work with Bombs
The debugger is the best tool to work with running bombs. It may be tempting to try to brute force the bomb by trying
many possible inputs but this may lead to many explosions or crashing the scoring server. Both of these are a bad idea so
work with your bomb by hand.
4.3 Machines on which bombs run
The binary bomb makes frequent contact with a scoring server so you can only run it on a list of prescribed machines. These
comprise most of the valid CSELabs machines and are listed in the table below.
Machine Login Address Location
atlas csel-atlas.cselabs.umn.edu Machine Room
apollo csel-apollo.cselabs.umn.edu Machine Room
Vole csel-vole-01.cselabs.umn.edu Virtual
csel-vole-02.cselabs.umn.edu
…
csel-vole-99.cselabs.umn.edu
http://atlas.cselabs.umn.edu:15213/
http://atlas.cselabs.umn.edu:15213/scoreboard
https://www-users.cs.umn.edu/~kauffman/2021/gdb.html
http://vole.cse.umn.edu/
Machine Login Address Location
4-250 Lab csel-kh4250-01.cselabs.umn.edu Keller 4-250
…
csel-kh4250-49.cselabs.umn.edu
4-240 Lab csel-kh4240-01.cselabs.umn.edu Keller 4-240
…
csel-kh4240-10.cselabs.umn.edu
Lind Lab csel-lind40-01.cselabs.umn.edu Lind Hall 40
…
csel-lind40-43.cselabs.umn.edu
Attempting to run a bomb on an un-authorized machine will error out immediately as in
4.4 Bomb Download and Setup
Download your bomb from the following web address
http://atlas.cselabs.umn.edu:15213/
This site must be accessed from wired UMN machines or Vole as it is behind the campus firewall. Using a browser on Vole
or a FASTX connection is the easiest way get a bomb onto your CSELabs account when you are working remotely (and
will let you tell friends “I’ve used a browser inside a browser.”).
Enter your UMN X.500 information in the required fields: IDs that don’t correspond to members of the class will be
rejected. If you have problems getting a bomb, mail Prof Kauffman.
The bomb will download as a .zip file. On Unix machines, extract the contents using the command unzip as in
The resulting bomb is unique for the downloader and the owner is in the README and logged on the download server.
> ./bomb
Initialization error: illegal host ‘ck-laptop’.
Legal hosts are as follows:
csel-apollo
csel-atlas
csel-vole-01
csel-vole-02
…
> ls
bomb10.zip
> unzip bomb10.zip
bomb10/README
bomb10/bomb.c
bomb10/bomb
> ls
bomb10.zip bomb10/
> cd bomb10
> ls
bomb* bomb.c README
http://atlas.cselabs.umn.edu:15213/
http://vole.cse.umn.edu/
https://www-users.cse.umn.edu/~kauffman/tutorials/unix-environment.html#orge1638c2
The file bomb (sometimes listed with a * to indicate it is executable) is a compiled binary so employ your assembly gdb
skills to cracking it.
Create a file input.txt. The bomb can be run with it as in
> ./bomb input.txt
but you’ll likely want to do this in gdb to avoid exploding the bomb.
Unlike previous puzzles, if input.txt runs out of input, the bomb will prompt for you to type input. This can be a way
to explore ahead a little bit in the bomb after solving a phase.
4.5 Scoring and Scoreboard (50%) grading 50
Scoring is done according to the following table.
Pts Phase Notes
10 Phase 1
10 Phase 2
10 Phase 3
10 Phase 4
10 Phase 5
5 Phase 6 Not Required
5 Bonus Reduced when Explosions occur
50 60 Max 50 pts is full credit
Explosion Penalty: 0.5 points are deducted for each explosion up to 10 explosions. 5pt bonus is reduced for every 2 explosions.
On successfully defusing stages, the bomb will contact a server which tracks scores by number. The scoreboard is here:
http://atlas.cselabs.umn.edu:15213/scoreboard
The server is reachable only on UMN hardwired machines such as lab machines or Vole
You’ll need to know your bomb number to see your score but can also see the scores of others.
Examples of Scoring
Phases Final
Defused Explosions Computation Score Notes
6 1 55 + (5 – floor(0.5*1) ) 60 1 explosion for free
6 4 55 + (5 – floor(0.5*4) ) 58
6 10 55 + (5 – floor(0.5*10)) 55
6 20 55 + (5 – floor(0.5*10)) 55 Only count 10 explosions
5 7 50 + (5 – floor(0.5*7)) 52 Round down for explosion penalties
4 4 40 + (5 – floor(0.5*4)) 43
http://atlas.cselabs.umn.edu:15213/scoreboard
Phases Final
Defused Explosions Computation Score Notes
1 0 10 + (5 – floor(0.5*0)) 15
0 2 0 + (5 – floor(0.5*2)) 4 Even trying with an explosion gets something
0 10 0 + (5 – (floor(0.5*10) 0
Getting Credit for the Problem
Ensure that the score listed on the Scoreboard site reflects your progress.
Ensure your input.txt along with your bombNN/ directory are in your project directory with the rest of your code.
4.6 WARNING on Downloading Multiple Bombs
It is possible to download multiple bombs but this will NOT reset your explosion count. Quite the opposite: the default scoring
system for the server uses the following conventions.
Only the maximum phase defused in any bomb adds points
Total explosions across ALL bombs subtract points with each separately downloaded bomb contributing up to -5.
Since more bombs likely means more explosions, you are strongly advised to download a single bomb and work with it.
4.7 Advice
If you accidentally run the bomb from the command line, you can kill it with the Unix interrupt key sequence Ctrl-c
(hold control, press C key).
Most of the time you should run the bomb in gdb as in
> gdb ./bomb
Refer to the Quick Guide to GDB if you have forgotten how to use gdb and pay particular attention to the sections on
debugging assembly.
Figure out what the explosion routine is called and always set a breakpoint there. This will allow you to stop the bomb
Make use of other tools to analyze the binary bomb aside from the debugger. Some of these are described at the end of the
Quick Guide to GDB. They will allow you to search for “interesting” data in the executable bomb. The author of the
bomb is encoded in the binary as a string somewhere which may be relevant to inputs for some phases.
Disassemble the executable to look at its entire source assembly code as a text file. The Quick Guide to GDB shows how
to use objdump to do this. Looking at the whole source code reveals that one cannot hide secrets easily in programs.
Feel free to do some internet research. The “bomb lab” assignment has a long history and there are some useful guides out
there that can help you through rough patches. Keep in mind that your bomb will differ but the techniques to defuse it
may be similar to others.
> ./bomb
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
^C
So you think you can stop the bomb with ctrl-c, do you?
Well…OK. 🙂
>
http://www-users.cs.umn.edu/~kauffman/2021/gdb
https://www-users.cs.umn.edu/~kauffman/2021/gdb.html#orgbeec3e9
Author: Chris Kauffman ( )
Date: 2021-10-22 Fri 15:54
mailto: