[30C3 CTF] fourier (Numbers200)
Heres one for those that like numbers and mathematics…
Mở bài
Chúng ta được cung cấp cho 1 file fourier (elf) và 1 file flag.four (data). File fourier dùng để mã hóa, còn file flag.four, dĩ nhiên, là flag đã được mã hóa.
Thân bài
Sau một chút thời gian (rất dài) bỡ ngỡ khi thấy các thím ấy sử dụng GMP cho việc tính toán, mình cũng thể hiện được phẩm chất vượt trội trong thao tác mò code để mô phỏng lại thuật toán mã hóa như sau (nhìn chung thì khá dễ, mỗi tội hơi khó) :
[python]import random
random.seed(69)
in_file = open(‘flag’, ‘r’).read()
out_file = open(‘flag.four’, ‘wb’)
secret = int(in_file.encode(‘hex’), 16)
while (secret >= 24):
random_number = number_3 = 0
number_3 = secret – 4
number_3 <<= 2
number_3 -= 5
if (number_3 > 0x444):
number_3 = 0x444
random_number = random.randint(0, number_3 – 1)
random_number += 5
number_4 = 0
while (number_4 != random_number):
number_4 += 1
out_file.write(‘4’)
out_file.write(‘ ‘)
number_4 = 4
number_5 = 0
while (number_4 < secret): out_file.write('4') number_5 = number_4 number_4 *= random_number number_4 += 4 secret -= number_5 out_file.write(' ') while (secret != 0): secret -= 1 out_file.write('4') out_file.close()[/python] Ngoại trừ các thao tác mà mình đã đối chiếu và thấy khá tương đồng, vấn đề duy nhất tồn đọng là hàm random. [asm].text:0000000000400CA1 lea rdi, [rsp+98h+random_handle] ; Load Effective Address .text:0000000000400CA6 call ___gmp_randinit_default ; Call Procedure[/asm] Target sử dụng hàm ___gmp_randinit_default và hơi lạ là khi mình debug lại thấy các kết quả random bị lặp lại. Mình cũng mất hơi nhiều thời gian cho việc cài đặt và chạy thử cái GMP này, rồi nhờ luật nhân quả nên sau đó điểm sáng xuất hiện:
[python] number_4 = 0
while (number_4 != random_number):
number_4 += 1
out_file.write(‘4’)[/python]
Ở đây ta thấy rằng chương trình làm một việc, đó là ghi ra giá trị sau khi random (mỗi đơn vị ứng với một byte ‘4‘). Và tổng quan thì cái thuật toán mã hóa khi hiểu đơn giản sẽ như sau:
- Nếu secret còn lớn hơn 24, thì chạy một vòng lặp, mỗi lượt ghi ra 2 giá trị:
- Khi secret nhỏ hơn 24, ghi ra secret.
Như thế, nếu ta chia file flag.four ra các phần ngăn cách bởi dấu cách (0x20), giá trị mỗi phần là độ dài của phần đó (vd ‘444‘ = 3), thì hàm giải mã có nhiệm vụ:
- Đọc ngược từ phần cuối về phần đầu (tức phần đầu tiên được đọc sẽ là phần cuối của file).
- Gán secret = phần đầu.
- Chạy vòng lặp cho đến khi hết nội dung:
- Đọc phần tiếp theo, đó chính là số lần lặp của X_LOOP.
- Đọc phần tiếp theo, đó chính là random_number.
- Tất cả giá trị đều đã đủ, ta có thể tính toán được number_5, và thêm vào secret.
- Chuyển đổi secret từ DEC qua ASCII.
(lý do vì sao lại đọc từ cuối trở về mà không đọc từ đầu trở đi trong khi 2 hướng nó như nhau, thì là vì, mình thích thế đấy
Code minh họa:
[python]cipher = open(‘flag.four’, ‘r’).read()
parts = cipher.split(‘ ‘)
secret = len(parts[len(parts) – 1])
part_index = len(parts) – 2
while (part_index > 0):
loop_count = len(parts[part_index])
random_number = len(parts[part_index – 1])
number_4 = 4
number_5 = 0
for i in range(loop_count):
number_5 = number_4
number_4 *= random_number
number_4 += 4
secret += number_5
part_index -= 2
print hex(secret)[2:-1].decode(‘hex’)[/python]
Kết bài
[sh]30C3_the_challenge_is_named_fourier_what_else_did_you_expect?[/sh]
Recent comments