Chapter 34 Exercises: Reverse Engineering

Warm-Up Exercises

Exercise 34.1 — Syntax conversion Convert the following AT&T syntax instructions to Intel syntax:

movq %rbx, %rax
addl $5, %ecx
leaq (%rsp), %rdi
movb $0x41, (%rdi)
subq $0x20, %rsp

Exercise 34.2 — objdump flags For each task, write the exact objdump command: a) Disassemble the binary ./mystery using Intel syntax b) Show the symbol table of ./server c) Show the dynamic symbols of /usr/bin/curl d) Show all sections and their addresses in ./program e) Dump the contents of the .rodata section as hex

Exercise 34.3 — Compiler pattern identification Label each assembly snippet with the C construct it represents:

; Snippet A:
xor    eax, eax
jmp    .check
.body:
call   process
inc    eax
.check:
cmp    eax, 10
jl     .body
; Snippet B:
cmp    edi, 3
ja     .default
lea    rax, [rip+.table]
mov    rax, [rax + rdi*8]
jmp    rax
; Snippet C:
mov    rax, [rdi]
mov    rax, [rax+0x18]
call   rax
; Snippet D:
test   edi, edi
jle    .else
call   positive_case
jmp    .end
.else:
call   non_positive_case
.end:

Static Analysis Exercises

Exercise 34.4 ⭐ — Disassembly annotation Annotate the following disassembly with comments explaining each instruction's purpose. Reconstruct the equivalent C function.

0000000000401160 <????>:
  401160: 55                    push   rbp
  401161: 48 89 e5              mov    rbp,rsp
  401164: 48 89 7d f8           mov    [rbp-0x8],rdi
  401168: 48 89 75 f0           mov    [rbp-0x10],rsi
  40116c: c7 45 e8 00 00 00 00  mov    DWORD [rbp-0x18],0x0
  401173: eb 13                 jmp    0x401188
  401175: 48 8b 45 f8           mov    rax,[rbp-0x8]
  401179: 0f b6 00              movzx  eax,BYTE [rax]
  40117c: 84 c0                 test   al,al
  40117e: 75 05                 jne    0x401185
  401180: ff 45 e8              inc    DWORD [rbp-0x18]
  401183: eb 03                 jmp    0x401188
  401185: 48 ff 45 f8           inc    QWORD [rbp-0x8]
  401189: 48 8b 45 f0           mov    rax,[rbp-0x10]
  40118d: 48 39 45 f8           cmp    [rbp-0x8],rax
  401191: 72 e2                 jb     0x401175
  401193: 8b 45 e8              mov    eax,[rbp-0x18]
  401196: 5d                    pop    rbp
  401197: c3                    ret

What are the parameters? What is returned? What does this function compute?

Exercise 34.5 — Jump table analysis The following disassembly includes a jump table. Identify: a) The bounds check instruction b) The jump table load c) How many cases exist d) Reconstruct the switch statement structure

  4011a0: 83 ff 04              cmp    edi, 0x4
  4011a3: 77 2c                 ja     0x4011d1
  4011a5: 89 ff                 mov    edi, edi
  4011a7: 48 8d 35 52 0e 00 00  lea    rsi, [rip+0xe52]    ; .jumptable
  4011ae: 48 63 04 be           movsxd rax, DWORD [rsi+rdi*4]
  4011b2: 48 01 f0              add    rax, rsi
  4011b5: ff e0                 jmp    rax

Exercise 34.6 — String extraction Given this disassembly snippet from a program that prints a message:

  401204: 48 8d 3d f9 0d 00 00  lea    rdi, [rip+0xdf9]
  40120b: e8 30 fe ff ff        call   0x401040 <puts@plt>

The instruction at 0x40120b is at address 0x40120b and is 5 bytes long. The constant loaded into RDI is rip + 0xdf9 where RIP is the address of the next instruction. Calculate the address of the string and explain how you would read its contents.


Dynamic Analysis Exercises

Exercise 34.7 ⭐ — GDB commands Write the GDB commands to accomplish each task. Assume a stripped binary (no symbols):

a) Set a breakpoint at address 0x40128c b) Run the program with arguments hello world c) Display the next 10 instructions from the current position d) Show the value of all general-purpose registers e) Show 8 64-bit words from memory at RSP f) Print the string pointed to by RDI g) Step one instruction without following calls h) Step one instruction, following calls i) Continue until next breakpoint j) Show a backtrace (even in stripped binary — addresses only)

Exercise 34.8 — GDB Python script Write a GDB Python script that: 1. Sets a breakpoint at 0x401196 (a hypothetical strcmp call site) 2. When the breakpoint is hit, prints both string arguments (RDI and RSI) 3. Does NOT stop execution — continues automatically 4. Logs all calls to a file named strcmp_log.txt

Exercise 34.9 — pwndbg workflow List five pwndbg commands (not standard GDB commands) that would be useful when analyzing a binary for security research, and describe what each shows.


Pattern Recognition Exercises

Exercise 34.10 — Identify the construct For each disassembly snippet, identify whether it shows: (a) a function call, (b) a virtual method call, (c) a function pointer call through a struct, (d) a tail call, or (e) a leaf function with no frame.

; Pattern 1:
mov    rax, [rdi+0x10]
call   rax

; Pattern 2:
mov    rax, [rdi]
mov    rax, [rax+0x28]
call   rax

; Pattern 3:
jmp    helper_function    ; at the end of a function

; Pattern 4:
push   rbp
mov    rbp, rsp
; ... body with no sub rsp ...
pop    rbp
ret

; Pattern 5:
sub    rsp, 0x8
call   some_function
add    rsp, 0x8
ret

Exercise 34.11 — Magic constant identification Identify the algorithm or context associated with each constant:

Constant Likely Algorithm/Use
0x5A4D ?
0x7F454C46 ?
0xCAFEBABE ?
0x9E3779B9 ?
0x67452301 ?
0xDEADBEEF ?
0x80000000 ?
0x0000FFFF ?

Exercise 34.12 ⭐ — Reconstruct from assembly Reconstruct the complete C source for this function:

; Function takes two arguments
strlen_bounded:
    push    rbp
    mov     rbp, rsp
    mov     [rbp-8], rdi    ; arg1: const char *str
    mov     [rbp-16], rsi   ; arg2: size_t maxlen
    mov     QWORD [rbp-24], 0   ; size_t n = 0
.loop:
    mov     rax, [rbp-24]
    cmp     rax, [rbp-16]
    jae     .done           ; if n >= maxlen, stop
    mov     rax, [rbp-8]
    mov     rdx, [rbp-24]
    movzx   eax, BYTE [rax+rdx]  ; str[n]
    test    al, al
    je      .done           ; if str[n] == '\0', stop
    inc     QWORD [rbp-24]  ; n++
    jmp     .loop
.done:
    mov     rax, [rbp-24]
    pop     rbp
    ret

Reverse Engineering Challenges

Exercise 34.13 — Crackme analysis Consider a program that calls the following validation function. Without running the program, determine what input produces a return value of 1:

validate:
    push    rbp
    mov     rbp, rsp
    sub     rsp, 0x10
    mov     [rbp-8], rdi    ; input string pointer

    ; Check length == 6
    mov     rdi, [rbp-8]
    call    strlen
    cmp     rax, 6
    jne     .fail

    ; Check first char is 'A' (0x41)
    mov     rax, [rbp-8]
    movzx   eax, BYTE [rax]
    cmp     al, 0x41
    jne     .fail

    ; Check last char is 'Z' (0x5A)
    mov     rax, [rbp-8]
    movzx   eax, BYTE [rax+5]
    cmp     al, 0x5A
    jne     .fail

    ; Check sum of middle 4 chars == 0x100
    mov     rax, [rbp-8]
    movzx   ecx, BYTE [rax+1]
    movzx   edx, BYTE [rax+2]
    add     ecx, edx
    movzx   edx, BYTE [rax+3]
    add     ecx, edx
    movzx   edx, BYTE [rax+4]
    add     ecx, edx
    cmp     ecx, 0x100
    jne     .fail

.success:
    mov     eax, 1
    jmp     .done
.fail:
    xor     eax, eax
.done:
    leave
    ret

a) What are all the conditions the input must satisfy? b) Give three different valid inputs. c) Could you automate finding all valid inputs? Describe how.

Exercise 34.14 — Tool selection For each scenario, choose the most appropriate RE tool and justify your choice:

a) Quick check of what library functions a binary imports b) Deep analysis of a complex, obfuscated malware sample with many cross-references c) Finding all calls to a specific address in a binary while it is running d) Automated analysis of 500 malware samples to find those using RC4 encryption e) Understanding the decompiled logic of a stripped function

Exercise 34.15 ⭐ — Compiler detective The following two disassemblies compile the same C code, but with different optimization levels. Identify which is -O0 and which is -O2, and explain three specific differences you observe:

; Version A:
f:
    push    rbp
    mov     rbp, rsp
    sub     rsp, 0x10
    mov     [rbp-4], edi
    mov     [rbp-8], esi
    mov     eax, [rbp-4]
    add     eax, [rbp-8]
    leave
    ret
; Version B:
f:
    lea     eax, [rdi+rsi]
    ret

Deep-Dive Exercises

Exercise 34.16 — Ghidra workflow Describe the step-by-step process for using Ghidra to analyze a password-protected binary where you want to find the validation logic. Include: where to start, how to navigate, what to look for, and how to confirm your analysis.

Exercise 34.17 — Stripped binary navigation A stripped x86-64 ELF binary's entry point is at 0x401080. The _start code calls __libc_start_main. Describe in detail how you would use GDB to find the address of main() in this binary without symbols.

Exercise 34.18 — Cross-architecture RE How does reverse engineering ARM64 binaries differ from x86-64? Specifically: a) What are the equivalent patterns for function prologue/epilogue? b) How does the calling convention affect register usage patterns? c) How do you identify a function's return value in ARM64? d) What Ghidra settings or considerations are different?

Exercise 34.19 — Obfuscation recognition Describe how you would identify and handle each of these obfuscation techniques encountered while reverse engineering: a) UPX-packed executable (the binary is compressed) b) Opaque predicates (always-taken or never-taken branches) c) String encryption (strings are decrypted at runtime) d) Control flow flattening (all basic blocks dispatched through a central switch)

Exercise 34.20 ⭐ — Complete RE exercise You are given a binary with no symbols. Using the skills from this chapter:

  1. It prints something when run with the right argument
  2. strings shows: "Correct!", "Wrong!", "Usage: crackme <key>"
  3. The validation function (which you found by following strings cross-refs) is 40 instructions long

Write out the complete analysis workflow you would follow, the GDB commands you would use, and how you would extract the correct key. You do not need to analyze a real binary — describe the methodology in detail, step by step.