Flare-On 11 Writeup (6-10)

bloke2

Flare-On 11 Writeup (1-5)에서 이어지는 글이다.

Problem Level Type Remarks
bloke2 6
Reversing
Verilog

Level(1-10) : Score / Highest Score


bloke2

Verilog 프로젝트가 제공된다. VerilogFPGA(Field-Programmable Gate Array) 등을 설계하는 데에 사용되는 HDL이라고 한다. 아래와 같은 시나리오가 주어졌으며, 숨겨진 비밀 메시지를 찾아야 한다.

One of our lab researchers has mysteriously disappeared. He was working on the prototype for a hashing IP block that worked very much like, but not identically to, the common Blake2 hash family. Last we heard from him, he was working on the testbenches for the unit. One of his labmates swears she knew of a secret message that could be extracted with the testbenches, but she couldn’t quite recall how to trigger it. Maybe you could help?


문제 분석

Verilog 언어 자체가 너무 생소하다. 그나마 문제 파일에 makefile이 포함되었으므로 이용하여 make를 해본다.

VVP=vvp
IVERILOG=iverilog

VVPFLAGS=
IVERILOGFLAGS=-g2012

targets=bloke2.out

test_targets=f_sched.test bloke2b.test bloke2s.test

deps_bloke2=bloke2.v f_sched.v f_unit.v g_over_2.v g.v g_unit.v data_mgr.v bloke2s.v bloke2b.v

deps_f_sched.test=f_sched.v f_sched_tb.v

deps_bloke2b.test=$(deps_bloke2) bloke2b_tb.v
deps_bloke2s.test=$(deps_bloke2) bloke2s_tb.v

all: $(targets)

tests: $(test_targets)

clean:
	rm -rf $(targets)

.SECONDEXPANSION:

%.out: $$(deps_$$*)
	iverilog $(IVERILOGFLAGS) -o $@ $^

%.test: %.test.out
	vvp $(VVPFLAGS) $^


일반 컴파일 파일을 실행 시에는 특이사항이 없다. 대신 tests로 빌드한 경우 다음과 같이 특별한 출력 값을 가진다.

image.png


문제 시나리오에서도 테스트벤치에 대한 언급이 존재하므로, tests 빌드 중 어떤 트리거를 만족시켜야 하는 듯 하다.

secret message that could be extracted with the testbenches


Testbenches

Testbenchbloke2s, bloke2b에 대하여 각각 1개 총 2개가 존재한다. 각 Testbench는 테스트하고자 하는 모듈의 인스턴스를 생성한다.

//bloke2s_tb.v
...
bloke2s uut (
		.clk(clk),
		.rst(rst),

		.start(start),
		.finish(finish),

		.din(din),
		.din_valid(din_valid),
		.din_ready(din_ready),
		.din_end(din_end),

		.dout(dout),
		.dout_valid(dout_valid),
		.dout_end(dout_end)
	);
...


각 모듈은 bloke2를 호출하여 데이터를 처리하도록 위임하고, bloke2data_mgr.v를 호출한다.

//bloke2.v
...
	data_mgr #(
		.W(W)
	) dmgr (
		.clk(clk),
		.rst(rst),

		.start(start),
		.finish(finish),

		.data_in(din),
		.dv_in(din_valid),
		.drdy_out(din_ready),

		.msg_strobe(msg_strobe),
		.m_out(m),
		.t_out(t),
		.f_out(f),

		.h_in(h_out),
		.h_rdy(f_dv),

		.data_out(dout),
		.dv_out(dout_valid),
		.data_end(dout_end)
	);
...


data_mgr.v에서 secret message의 재료로 의심되는 TEST_VAL과 이를 처리하는 연산 코드들이 눈에 띈다. h_in, tst 등의 값을 건드려서 출력되는 Received Message 값을 바꿔줘야 할 듯 하다.

...
	always @(posedge clk) begin
		if (rst | start) begin
			m   <= {MSG_BITS{1'b0}};
			cnt <= {CNT_BITS{1'b0}};
			t   <= {(W*2){1'b0}};
			f   <= 1'b0;
			tst <= finish;
...
    localparam TEST_VAL = 512'h3c9cf0addf2e45ef548b011f736cc99144bdfee0d69df4090c8a39c520e18ec3bdc1277aad1706f756affca41178dac066e4beb8ab7dd2d1402c4d624aaabe40;
...
	always @(posedge clk) begin
		if (rst) begin 
			out_cnt <= 0;
		end else begin
			//$display("%t dmgr dout oc %h", $time, out_cnt);
			if (h_rdy) begin
				//$display("%t dmgr dout h %h t %b", $time, h_in, tst);
				out_cnt <= W;
				h <= h_in ^ (TEST_VAL & {(W*16){tst}});
			end else if(out_cnt != 0) begin
				//$display("%t dmgr dout d %h dv %b de %b oc %h", $time, data_out, dv_out, data_end, out_cnt);
				out_cnt <= out_cnt - 1;
				h <= {8'b0, h[W*8-1:8]};
			end
		end
	end
...


PoC

먼저 tst 와 관련 있는 finish 값을 0에서 1로 바꿔보자.

		// Set our start and finish lines correctly.
		start <= 1'b1;
		finish <= 1'b0;  // 이걸 b1로 수정


어라? flag가 출력되었다. 이 언어에 대해서 더이상 자세히 알고 싶지 않으므로 면밀한 분석은 생략한다.

image.png


fullspeed

작성중…