# ACS 2023: babyrev

## TL;DR

> Flag checker with library call path explosion designed to thwart Angr's symbolic execution. This pitfall can be resolved via Angr's Dynamic Memory implementation.

## Challenge Overview

babyrev is yet another flag checker program, but connects over socket to increase its complexity.

<figure><img src="/files/GISMbu3lfH5HpktuqsOK" alt=""><figcaption></figcaption></figure>

Angr is known to struggle against library calls. The use of socket to receive user input is similar to one of the common roadblocks in Angr where library functions such as `scanf` are used.

<figure><img src="/files/A770c14JvNFzawubYiMW" alt=""><figcaption></figcaption></figure>

I came across this [tutorial](https://blog.notso.pro/2019-04-10-angr-introduction-part3/) by Federico that uses Angr's symbolic memory to hook library calls.

## Determine Start Address

To overcome this roadblock, we will try to avoid all instructions that are related to socket, and configure Angr's Simulation Manager to start directly from the flag-checking logic.

```python
initial_state = project.factory.blank_state(addr=0x40CC5A)
```

<figure><img src="/files/uSDsCnFVsSkmDspCdn0H" alt=""><figcaption></figcaption></figure>

## Symbolic Memory

First, we create a symbolic bitvector `flag` that will substitute our input. In our case, the original input that `recv()` receives is stored in `rbp-0xd0`; hence we would also define our symbolic bitvector to store in the same memory address.

```python
flag_chars = [claripy.BVS(f"c_{i}", 8) for i in range(FLAG_LEN)]
flag = claripy.Concat(*flag_chars)

initial_state.memory.store(initial_state.regs.rbp-0xd0, flag)
# Define the address at which the symbolic bitvector will be stored.
```

<figure><img src="/files/7DLZBNXEwH5VZwtJXVi4" alt=""><figcaption></figcaption></figure>

## Determine Good & Bad Address

The rest is pretty much straightforward, which involves performing light-reversing to find good and bad addresses.

<figure><img src="/files/iF45wg139fUEutXWfqZw" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/mHxGEraWLg7OSZ2FbMOh" alt=""><figcaption></figcaption></figure>

## Solution

Angr solved this pretty quickly, taking only 4 minutes.

<figure><img src="/files/vMqaimAwVBXxXHUVQya3" alt=""><figcaption></figcaption></figure>

**Flag:** ACS{V2l0aCBncmVhdCBwb3dlciBjb21lcyBncmVhdCByZXNwb25zaWJpbGl0eS4gLSBTcGlkZXItbWFuIGZpbG1zCg==}

## Final Script

```python
#!/usr/bin/env python3

import angr
import claripy
import logging

FLAG_LEN = 88

find_addr  = 0x40CD50 # SUCCESS
avoid_addr = 0x40CCFA # FAILURE
start_addr = 0x40CC5A

project = angr.Project("babyrev", load_options={"auto_load_libs": False})
flag_chars = [claripy.BVS(f"c_{i}", 8) for i in range(FLAG_LEN)]
flag = claripy.Concat(*flag_chars)

logging.getLogger('angr').setLevel('INFO')
initial_state = project.factory.blank_state(
        stdin=flag,
        addr = start_addr,
        add_options={
        angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY,
        angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS,
        angr.options.LAZY_SOLVES
    }
)

initial_state.memory.store(initial_state.regs.rbp-0xd0, flag)

# Add constraints that all characters are printable
for f in flag_chars:
    initial_state.solver.add(f >= 0x20)
    initial_state.solver.add(f < 0x7f)

sm = project.factory.simulation_manager(initial_state)
sm.explore(find=find_addr, avoid=avoid_addr)

if sm.found:
    solution_state = sm.found[0]
    solution = solution_state.solver.eval(flag, cast_to=bytes)
    print(solution)
else:
    raise Exception('Could not find the solution')
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jesuscries.gitbook.io/home/ctf-writeups/reverse-engineering/acs-2023-babyrev.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
