Tags: excel reverse

Rating:

# Excellent Crackme
We know one can do pretty much everything in Excel spreadsheets, but this...

[excel_crackme](VolgaCTF_excel_crackme.xlsm)

Open the excel file:
![Capture](Capture.PNG)

Unzipping the xlsm file and decompiled the vba source code using pcode2code:

pcode2code xl/vbaProject.bin -o decompile

Analyse the code, only **VolgaCTF function** is important for finding the flag

vb6
Private Sub VolgaCTF()
Dim input As String
Dim solution As Long
Dim number As Long
input = Range("L15") 'L15 is the flag input box cell
For i = 1 To Len(input) 'i will loop to 1 to length of input
solution = 0
For j = 1 To Len(input) 'j will loop to 1 to length of input
number = CInt(Cells(99 + i, 99 + j).Value)
'Get a character from input from index j
c = Mid(input, j, 1)
'Add the number times the ASCII value of c to solution
solution = solution + number * Asc(c)
Next j
'Get the value of cell and assign to answer
answer = CLng(Cells(99 + i, 99 + Len(input) + 1).Value)
'If answer not equal solution means wrong flag
MsgBox "Wrong Flag!"
Exit Sub
End If
Next i
'Only if all answer equal to all solution then the flag is correct
MsgBox "Congratz"
End Sub

After I reversing the code, immediately found a secret number table starts at (CV,100), because of Cells(99 + i, 99 + j) and i j starts at 1

![Screenshot](Screenshot1.png)

It is a 45*46 table, and I notice last column of the table is quite large compared to other number:

![Screenshot2](Screenshot2.png)

After more deep analysing, I found these are **Simultaneous equations!**

Assume abcdefgh (unknown) is the input characters
First row:
620a +340b +895c -39d +945e +321f +586g +487h... = 490493
Second row:
-19a +85b -456c +228d -127e -777f +191g +605h... = -7845
etc

Therefore, the flag length must be 45 (45 column)

I decide to use z3 solver in python to solve this:
py
from z3 import *
n = 45
inp = [Int('inp%i' %i) for i in range(n)]
numbers = [i.strip().split(" ") for i in open("numbers.txt",'r').read().split("\n")]
solver = Solver()
for i in range(9,45):
for i in range(44):
condition = ""
for j in range(n):
condition += "("+ numbers[i][j] + "* inp[%i])+" % j
print(solver.check())
modl = solver.model()
print(''.join([chr(modl[inp[i]].as_long()) for i in range(n)]))

It took around 2 minutes to solve:

time python solve2.py
sat
VolgaCTF{7h3_M057_M47h_cr4ckM3_y0u_3V3R_533N}

real 1m41.494s
user 1m41.331s
sys 0m0.095s

## Flag

VolgaCTF{7h3_M057_M47h_cr4ckM3_y0u_3V3R_533N}


## Better Solution
After the CTF ends, I saw better solution that can solve faster:
[Unhappi writeups](https://ilovectf.github.io/jekyll/update/2020/03/29/Volga.html#excellent-crackme-150-points)
[Better solution](solve3.py)

It use matrix to solve like the picture below:
![Matrix](Matrices.png)

Original writeup (https://github.com/Hong5489/VolgaCTF2020/tree/master/excellent_crackme).