We start by downloading the provided zip file. It contains a Readme file that explains how to compile the provided Verilog code and how to run the simulation.
We install the required tool:
sudo apt-get install iverilog gtkwave
Now we can look at the provided Verilog code. we are given two files:
module EzLogic_tb #(
parameter FLAG_TO_TEST = "..........................................",
parameter N = 42
)();
Then there is a check at the bottom that checks if the calculated value is equal to the expected value:
wire [0:8*N-1] data_std = 'h30789d5692f2fe23bb2c5d9e16406653b6cb217c952998ce17b7143788d949952680b4bce4c30a96c753;
assign success = (data_std == data_out_all);
Fortunately for us, the parameter
To do this we mark the two parameters:
module EzLogic_tb #(
parameter FLAG_TO_TEST = "<FLAG>",
parameter N = <N>
)();
And add a
#4
$display("result: %h", data_out_all);
if (success) begin
$display("Great! You've found the correct flag!");
end
We can now build a simple python script to brute force the flag character by character.
import string
import subprocess
import os
import re
desired = "30789d5692f2fe23bb2c5d9e16406653b6cb217c952998ce17b7143788d949952680b4bce4c30a96c753"
source_code = ""
with open("problem/EzLogic_tb.v") as f:
source_code = f.read()
charset = string.ascii_lowercase + string.ascii_uppercase + string.digits + "}{_-+-"
flag = ""
for i in range(42):
ok = False
for c in range(len(charset)):
char = charset[c]
test_flag = flag + char
modified_source_code = source_code.replace("<FLAG>", test_flag).replace("<N>", str(len(test_flag)))
with open("problem/EzLogic_tb.v", "w") as f:
f.write(modified_source_code)
# compile
subprocess.run("iverilog -s EzLogic_tb -o EzLogic.vvp ./problem/EzLogic_top_synth.v ./problem/EzLogic_tb.v ./behavioral\ models/*.v", shell=True, capture_output=True)
# run
result = subprocess.run(["vvp", "EzLogic.vvp"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
match = re.search(r"result: (.*?)\n", result.stdout)
if match:
result = match.group(1)
if result == desired[:i*2+2]:
flag = test_flag
print("flag so far:", flag)
ok = True
break
else:
print("No match found!")
if not ok:
with open("problem/EzLogic_tb.v", "w") as f:
f.write(source_code)
exit("Character not in charset!")
with open("problem/EzLogic_tb.v", "w") as f:
f.write(source_code)
After running the script we get the flag:
┌──(pepe㉿kali)-[~/ctf/0ctf/ezlogic]
└─$ python brute.py
flag so far: 0
flag so far: 0o
flag so far: 0op
flag so far: 0ops
flag so far: 0ops{
flag so far: 0ops{a
flag so far: 0ops{aa
flag so far: 0ops{aad
flag so far: 0ops{aadc
flag so far: 0ops{aadc3
flag so far: 0ops{aadc33
flag so far: 0ops{aadc337
flag so far: 0ops{aadc337c
flag so far: 0ops{aadc337c-
flag so far: 0ops{aadc337c-b
flag so far: 0ops{aadc337c-b5
flag so far: 0ops{aadc337c-b5a
flag so far: 0ops{aadc337c-b5a0
flag so far: 0ops{aadc337c-b5a0-
flag so far: 0ops{aadc337c-b5a0-4
flag so far: 0ops{aadc337c-b5a0-4f
flag so far: 0ops{aadc337c-b5a0-4ff
flag so far: 0ops{aadc337c-b5a0-4ff0
flag so far: 0ops{aadc337c-b5a0-4ff0-
flag so far: 0ops{aadc337c-b5a0-4ff0-a
flag so far: 0ops{aadc337c-b5a0-4ff0-ad
flag so far: 0ops{aadc337c-b5a0-4ff0-ad9
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1c
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf4
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf41
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf419
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf4195
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf41956
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf41956f
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf41956f4
flag so far: 0ops{aadc337c-b5a0-4ff0-ad94-9d1cf41956f4}