---
title: "Debugging Continued"
author: ["Thalita Vergilio", "Tom Shaw", "Z. Cliffe Schreuders"]
license: "CC BY-SA 4.0"
description: "Advanced dynamic analysis using GDB debugger with 8 challenging CTF exercises covering XOR encryption, memory analysis, register examination, and advanced debugging techniques."
overview: |
  Building upon the skills acquired in the previous lab, this hands-on debugging session takes your expertise to the next level with a fresh set of challenges. These new exercises further enhance your dynamic analysis capabilities using the GNU Debugger (GDB). In the world of reverse engineering and cybersecurity, debugging is an indispensable skill, particularly when the source code remains elusive. This lab provides the ideal platform to fortify your skills by introducing unique challenges, each designed to push the boundaries of your GDB proficiency.

  You'll set breakpoints, scrutinize register values, and decipher assembly instructions to uncover concealed passwords and flags. For example, in the "XorStr" challenge, you'll leverage GDB to identify an XOR mask and use it to decrypt a string, while "StaticInt" will have you focusing on EAX values and local variables to print the flag. By the conclusion of this lab, you will have cemented your debugging abilities and effectively surmounted eight new challenges, solidifying your expertise in dynamic analysis for situations where source code accessibility is restricted.

  In your home directory you will find some binaries that you need to reverse engineer in order to determine the password that the program expects. Once you have found the password, run the program and enter the password to receive the flag.
tags: ["gdb", "dynamic-analysis", "debugging", "advanced", "ctf", "xor", "memory-analysis", "register-analysis"]
categories: ["software_and_malware_analysis"]
lab_sheet_url: "https://docs.google.com/document/d/11A7tZppId1pxbcclZDPr6e-zwWPKqPnJMgyAtcARR2s/edit?usp=sharing"
type: ["ctf-lab", "lab-sheet"]
difficulty: "intermediate"
cybok:
  - ka: "MAT"
    topic: "Malware Analysis"
    keywords: ["analysis techniques", "analysis environments", "DYNAMIC ANALYSIS"]
---


## Introduction {#introduction}

Debugging is a practical skill, so the best way for you to become proficient is by getting plenty of hands-on practice within realistic reverse-engineering contexts (i.e. where the source code is not available to you). This week, we continue to focus on dynamic analysis using the GNU Debugger (GDB) whilst solving eight more challenges.

## Advanced GDB Techniques {#advanced-gdb-techniques}

Before diving into the advanced CTF challenges, let's cover some essential GDB techniques that you'll need for the more complex debugging scenarios ahead.

### Backtrace and Stack Analysis {#backtrace-and-stack-analysis}

When a program crashes or you want to understand the call chain, use the backtrace command:

```bash
bt
```

This shows you the sequence of function calls that led to the current point in execution.

To examine the values pushed to the stack before a function call:

```bash
x/10x $rsp
```

This shows the top 10 values on the stack, which often include function parameters.

### Function Call Analysis {#function-call-analysis}

Understanding how function parameters are passed is crucial for advanced debugging:

> Note: In x86-64 Linux, function parameters are passed in registers:
> - 1st parameter: RDI
> - 2nd parameter: RSI  
> - 3rd parameter: RDX
> - 4th parameter: RCX

To examine the first parameter to a function:

```bash
x/s $rdi
```

To examine the second parameter:

```bash
x/s $rsi
```

### XOR Operations and Encryption {#xor-operations-and-encryption}

XOR is commonly used in encryption and obfuscation. In assembly, you'll see instructions like:

```nasm
xor eax, 0x12345678
```

> Tip: When you see XOR operations, one operand is often the data and the other is the encryption key.

To examine XOR operations, look for the xor instruction in the disassembly and note the values being XORed together.

### Advanced Memory Examination {#advanced-memory-examination}

Here are different format specifiers for the x command:

```bash
x/s $rdi          # Read as string
x/x $rax          # Read as hexadecimal
x/d $rax          # Read as decimal
x/c $rax          # Read as character
x/10i $rip        # Read as 10 instructions
```

To examine strings in memory, use:

```bash
x/s $rdi
```

The `/s` format specifier reads the data as a null-terminated string.

### Setting Breakpoints in Function Calls {#setting-breakpoints-in-function-calls}

To set a breakpoint just before a function call:

```bash
break *main+0x123
```

This allows you to examine the parameters being passed to the function.

Use the `fin` command to step out of a function and return to the caller:

```bash
fin
```

> Tip: The `fin` command is particularly useful when you've stepped into a function and want to return to the calling function. 

## CTF Challenges {#ctf-challenges}

There are eight challenges this week and, as you would expect, there is more than one way to solve them \- feel free to explore different approaches.

### General tips {#general-tips}

> Tip: Don't forget to change your GDB configuration settings so programs are disassembled using the Intel notation (GDB defaults to AT&T).

==action: Run:==

```bash
vi ~/.gdbinit
```

==action: Add the following line:==

```bash
set disassembly-flavor intel
```

==action: Save and close the file.==

> Flag: For all the challenges, once you have found the password, run the program again **outside of GDB** to get your flag.

> Tip: If at any point your console layout looks jumbled, with the text you type overwriting the text on the screen, hit Ctrl + L to fix it.

> Tip: Remember to use these essential GDB commands:

| Command | Description |
| :---- | :---- |
| `run` | execute the program from within GDB |
| `si` | "step into" the next assembly instruction |
| `ni` | "step over" the next assembly instruction (don't step into functions) |
| `fin` | "step out" of the function |
| `c` | continue, or "play" |

### XorLong {#xorlong}

> Hint: There are different ways to solve this challenge. One of them is to find the cmp in main() that controls whether printflag() will be called. Put a breakpoint there. Print the values of the registers being compared (as hexadecimal numbers). One of them will be the password.

### XorStr {#xorstr}

> Hint: One of the ways to solve this challenge is to put a breakpoint before the call to strlen(), then examine the value of rdi (as a string) when the execution stops there. 

> Hint: Next, look for the XOR line in the disassembled code. See if you can find the mask.

> Hint: Write a simple C program that goes through every character of the string (char array) and XORs it against the mask.

### SegvBacktrace {#segvbacktrace}

> Hint: Run the program in gdb. When the execution fails following a wrong password, run "bt".

> Hint: Put a break in each of the functions, just before they call the next function.

> Hint: When execution stops, examine the value of the rdi register (as a string) in each of them.

### 2DArrays {#2darrays}

> Hint: Using GDB to obtain this flag could almost be considered cheating… but since our focus this week is to get as much practice with GDB as possible, you are allowed (and indeed encouraged) to use it.

> Hint: Disassemble main() and find the cmp instruction that compares a register with a hardcoded value. 

### InputFormat {#inputformat}

> Hint: The password is made up of three three-digit values, separated by a space: an integer, a character and a hexadecimal number. When testing, enter something like 111 aaa 222. For this challenge, you will need to work on one value at a time.

> Hint: First, set the breakpoints:

> Hint: 1. Find the call to scanf() that takes user input. Then find the cmp instruction that follows it. Put a breakpoint there.

> Hint: 2. Find the call to strcmp() a little further down and put a breakpoint there.   

> Hint: 3. Finally, find the next cmp instruction and put a breakpoint there.

> Hint: Run the program in GDB. When it stops at the first cmp instruction, examine the values being compared. One of them is your input, the other is the answer.

> Hint: Run the program again, this time replacing the integer/character/decimal part of the answer with the value you found. When the execution breaks, examine the values being pushed onto the stack before strcmp() is called. You should be able to find your second value.

> Hint: Run the program one more time, replacing the two parts of the answer you now know with the correct values. When the execution stops, once again, examine the values being compared to find your third and final value.

### StaticInt {#staticint}

> Hint: Disassemble main(). See that EAX needs to be set to not zero for it to print the flag, and the code that sets the value of EAX is inside the check_code() function.

> Hint: Use breakpoints in check_code() to read the value of a local variable just before the cmp instruction is executed. Remember to examine it as a double-word decimal.

### StaticRE {#staticre}

> Hint: This one is fairly straightforward. Disassemble main(). Put a breakpoint on the cmp based on which the flag will be printed.

> Hint: Run the program and check the values compared. Remember to examine the local variable as a double-word decimal.

### StaticStrcmp {#staticstrcmp}

> Hint: Find the call to strcmp (it doesn't show the name, just the function address). Put a breakpoint just before the function is called and examine the values pushed to the stack.

## Conclusion {#conclusion}

At this point you have:

* Become more confident in using GDB to step through a program’s execution at assembly level, without having access to the source code;  
* Solved practical challenges using MetaCTF and found 8 more flags\!

Well done\!

By now, you will have had plenty of exposure to GDB and should have started to feel confident performing advanced dynamic analysis on malware for which the source code is not available.
