Tags: rev 

Rating:

# xHell

We are given an Excel spreadsheet with around 80 rows and five
columns. The values in the A column are parameters (we will see that
these are instructions later), and columns B to E are computed using a
large formula, except in the first row, where they are user-provided
parameters.

The formula is (example from D14, line breaks and indentation for
clarity):

```
=IF(MID($A14,4,1)=TEXT(COLUMN()-1,"0"),
IF(MID($A14,1,1)="1",
MOD(SUM(
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,2,1))),
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,3,1)))),256),
IF(MID($A14,1,1)="2",
MOD(
SUM(INDIRECT(ADDRESS(ROW()-1,1+MID($A14,2,1))),
-INDIRECT(ADDRESS(ROW()-1,1+MID($A14,3,1)))),256),
IF(MID($A14,1,1)="3",
MOD(PRODUCT(
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,2,1))),
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,3,1)))),256),
IF(MID($A14,1,1)="4",
MOD(MOD(
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,2,1))),
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,3,1)))),256),
IF(MID($A14,1,1)="5",
MOD(BITAND(
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,2,1))),
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,3,1)))),256),
IF(MID($A14,1,1)="6",
MOD(BITOR(
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,2,1))),
INDIRECT(ADDRESS(ROW()-1,1+MID($A14,3,1)))),256),
IF(MID($A14,1,1)="7",
IF(INDIRECT(ADDRESS(ROW()-1,1+MID($A14,2,1)))
=INDIRECT(ADDRESS(ROW()-1,1+MID($A14,3,1))),
1,
0),
"X"))))))),
D13)
```

We can see that this reads an instruction from the A column (a
four-digit number), splits it into digits and uses them to compute the
values in that row. Let's name the digits, in order, `dest`, `x`, `y`
and `op`.

We can treat the spreadsheet as an execution trace for a program which
has four registers `b`, `c`, `d` and `e`, and instructions given in
the A column. The instructions are decoded as:

* take the values in registers `x` and `y` as parameters (where `1`
encodes `b`, `2` encodes `c`, and so on),
* compute the result of operation `op` with parameters `x` and `y`,
where values from `1` to `7` encode addition, subtraction, product,
modulus, bitwise-and, bitwise-or and equality testing,
* take the result modulo 256, and
* write it to the register encoded by `dest`.

The cell which tests if our parameters are accepted checks for three
conditions. For initial values of the registers, we have `b - c == 46`
and `e - d == 119`. Further, the final value of `e` must be `1`. The
first two checks let us compute `c` and `d` from `b` and `e`, so we
can try all possible values for these two registers (from 0 to 255, so
this doesn't take long) to find one that satisfies the final check and
get the flag.