WRECKCTF 2022

WRECKCTF 2022


Nguồn ở đây nhá các bạn: 💀👆👆👆💀

Chào mọi người lại quay trở lại với một giải đấu được gọi là vừa sức đối với những người mới và trung bình kinh nghiệm còn thấp của tôi. Sau đây không lòng vòng tôi đi vào mục tiêu chính với 4/6 thử thách RE - Dịch ngược tôi hoàn thành.

Sau chuỗi bài đầu tiên tôi sẽ tinh gọn những bước đơn giản và các bước đầu tiên và sẽ tập trung phân tích và tiếp nạp các kiến thức trong quá trình giải và tìm hiểu kiến thức mới từ các challenges nhá.

1: flag-checker (Solved)

title

Tôi sẽ mở nó bằng IDA pro và nhận được kết quả của hàm main:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[3]; // [rsp+0h] [rbp-40h] BYREF
  char v5[3]; // [rsp+3h] [rbp-3Dh] BYREF
  char v6[3]; // [rsp+6h] [rbp-3Ah] BYREF
  char v7[3]; // [rsp+9h] [rbp-37h] BYREF
  char v8[3]; // [rsp+Ch] [rbp-34h] BYREF
  char v9[3]; // [rsp+Fh] [rbp-31h] BYREF
  char v10[3]; // [rsp+12h] [rbp-2Eh] BYREF
  char v11[3]; // [rsp+15h] [rbp-2Bh] BYREF
  char v12[3]; // [rsp+18h] [rbp-28h] BYREF
  char v13[3]; // [rsp+1Bh] [rbp-25h] BYREF
  char v14[3]; // [rsp+1Eh] [rbp-22h] BYREF
  char v15[3]; // [rsp+21h] [rbp-1Fh] BYREF
  char v16[20]; // [rsp+24h] [rbp-1Ch] BYREF
  unsigned __int64 v17; // [rsp+38h] [rbp-8h]

  v17 = __readfsqword(0x28u);
  fgets(s, 41, _bss_start);
  v16[4] = 0;
  if ( strlen(s) != 40 )  //flag có length = 40
    bad();
  if ( strncmp(v14, "d94", 3uLL) )
    bad();
  if ( strncmp(v6, "db_", 3uLL) )
    bad();
  if ( strncmp(v10, "35t", 3uLL) )
    bad();
  if ( strncmp(v8, "y0u", 3uLL) )
    bad();
  if ( strncmp(v7, "1s_", 3uLL) )
    bad();
  if ( strncmp(v13, "d_6", 3uLL) )
    bad();
  if ( strncmp(v5, "g{g", 3uLL) )
    bad();
  if ( strncmp(v11, "_fr", 3uLL) )
    bad();
  if ( v16[3] != 125 )
    bad();
  if ( strncmp(v12, "13n", 3uLL) )
    bad();
  if ( strncmp(v16, "fa6", 3uLL) )
    bad();
  if ( strncmp(v9, "r_b", 3uLL) )
    bad();
  if ( strncmp(v15, "620", 3uLL) )
    bad();
  if ( strncmp(s, "fla", 3uLL) )
    bad();
  puts("Nice job! Submit your answer as the flag.");
  return 0;
}

Bài check length của flag và các subflag với các string, nếu không thỏa mãn 1 câu lệnh if nào sẽ gọi hàm bad()

Flag: flag{gdb_1s_y0ur_b35t_fr13nd_6d94620fa6} -> Done với thử thách đầu nhé🥸

2: advanced-flag-checker (Solved)

title 2

Tiếp tục với IDA:

open ida pro

Ta nhận ra hàm main có gọi function sys_write để in ra thông báo cần nhập flag và đọc flag nhập vào. Tiếp theo chương trình sử dụng toán tử XOR cho lần lượt 4 byte của input với giá trị tương ứng của đề bài và so sánh giá trị yêu cầu.

Vậy cũng khá dễ để giải quyết bài này🫡. Nhắc lại kiến thức XOR 1 chút là nếu: A xor Value đã biết = value nào đó đã biết thì ta chỉ vần xor với 2 value đã biết đó với nhau thì ta sẽ tìm được A

Dưới đây là code của tôi về bài này:

# Tôi tạo 1 hàm reverse lại kết quả nhận được sau khi xor 2 giá trị đã biết
def rever(a1,a2):
    a = hex(a1 ^ a2)[2:]
    lst = [chr(int(a[6:8],16)),chr(int(a[4:6],16)),chr(int(a[2:4],16)),chr(int(a[:2],16))] 
    # tạo list được chuyển ngược vì nó ngắn nên tôi làm thế nào vì code xấu ae ta thông cảm nhé, mấy giải mới sẽ ngon hơn 🫡
    return ''.join(lst) # trả về chuỗi

print(rever(0x558C4DC,0x6239A8BA),end='')
print(rever(0x71100C9B,0x17F64E0),end='')
print(rever(0xCE3D1DDE,0xA14442BB),end='')
print(rever(0x322958FC,0x415C0789),end='')
print(rever(0x8CBE8F4E,0xF6E1EB2B),end='')
print(rever(0xB14A374B,0xDE2C6878),end='')
print(rever(0xEE9707A,0x669D2F08),end='')
print(rever(0xF98DDD38,0xC8D2AE51),end='')
print(rever(0x5D715F4D,0x6C12677F),end='')
print(rever(0x410B9F90,0x3C3CFBA3),end='')

Có 1 lưu ý là kết quả nhận được 4 bytes liên tiếp nhau thì ta cần tách nó ra thành. Nhưng kiết quả nhận được bố trí theo kiểu Little-endian - 1 dạng sắp xếp các giá trị ít quan trọng nhất được lưu trữ trước. Ví dụ này cho dễ hiểu nhé.😁

Nếu số ta có là 0xFFAA0322 thì sẽ được sắp xếp là 22 03 AA FF vì nếu lấy 1 bytes thì quan trọng nhất là 22 còn lại về sau sẽ không quan trọng phải không, còn nếu lấy nhiều hơn thì tiếp tục (những cũng chắc chắn số đó sẽ to rồi😜 mà ta thường sử dụng các số bé thì sẽ thuận tiện hơn thì phải). Đây là ảnh minh họa và cũng là kết thúc của thử thách 2 nhé:

little endian

À mà quên flag đây nhá: flag{hope_you_used_z3_for_this_128c13d7}.

3: reverser (Solved)

title 3

Với thử thách này code bằng python:


#!/usr/local/bin/python

import os

def check_license(license):         #check license của mình với target đã được thay đổi qua 1 2 3 ...
    characters = set('0123456789abcdef')
    s = [9]
    for c in license:
        if c not in characters:
            return False
        s.append((s[-1] + int(c, 16)) % 16)  # đại lại là lấy số dư của (cái trước + cái sau) với 16
    target = '51c49a1a00647b037f5f3d5c878eb656'
    return ''.join(f'{c:x}' for c in s[1:]) == target #kết quả list vừa nhận được sẽ tạo thành chuỗi đem so sánh với target nếu thỏa mãn trả về true

print('welcome to reverser as a service!')
license = input('please enter your license key: ') #nhận input license của mình

if not check_license(license):
    print('sorry, incorrect key!')
    exit()

string = input('what should i reverse? ')
print(f'output: {string[::-1]}') # cho vào cho vui))))
print(os.environ.get('FLAG', 'no flag given')) # nếu không exit() ở trên thì chắc chắn có flag rồi

Và ý tưởng như đã phân tích đó tôi đã viết keygen cho chương trình này nhé: (với input đầu vào như trên là target đó và output đương nhiên là license chính hiệu cần tìm rồi)

license_enc = input("\nInput lincense encode: ")
# license_enc = "51c49a1a00647b037f5f3d5c878eb656"

lst_lin_enc = [9]
for i in license_enc:
    lst_lin_enc.append(int(i,16))

# [9, 5, 1, 12, 4, 9, 10, 1, 10, 0, 0, 6, 4, 7, 11, 0, 3, 7, 15, 5, 15, 3, 13, 5, 12, 8, 7, 8, 14, 11, 6, 5, 6]

lst = []
for i in range(len(lst_lin_enc)-1,0,-1):  # reverse lại các hàm chương trình chính làm thôi)))
    temp = lst_lin_enc[i]-lst_lin_enc[i-1]
    if temp <0:
        temp += 16
    lst.append(temp)

print("License: ", end='')
print(''.join(hex(i)[2:] for i in lst)[::-1]) 

Và kết quả nó sẽ thế này:

result license

Và ném cái license nhận được lên và nhận kết quả thôi:

flag

Vẫn như thường lệ Flag: flag{clock_math_too_hard}

4: my-frob (Solved)

title

Mở IDA và kiếm hàm main thôi các pro:

open

Có một số hàm đáng chú ý như lload_flag():

show func load flag

Giải thích 1 chút về hàm này:

  • mở file flag.txt với quyền read;
  • The C library function int fseek(FILE *stream, long int offset, int whence) sets the file position of the stream to the given offset. (Đặt vị trí file stream thành phần bù đã cho) - tôi hiểu nó là đọc bao nhiêu ký tự từ vị trí nào😁;
  • The C library function long int ftell(FILE *stream) - dùng để lấy tổng kích thước của tệp sau khi di chuyển con trỏ tệp ở cuối tệp. Như trong bài là lấy kích thước của flag trong file flag.txt.

Tiếp tục ta đi vào hàm my_memfrob:

func my_mem

Dễ nhận thấy hàm này sẽ XOR lần lượt các phân tử của flag với giá trị truyền vào là a3.

Quay lại hàm main thì ta thấy hàm này sẽ gọi lại hàm my_memfrob 1 vài lần nếu v7 vẫn khác 233.

main

Ta thấy giá trị ban đầu của v7 = 1 sau khi gọi hàm nó sẽ được lưu tạm vào v5 và sẽ cộng thêm với giá trị v8, rồi ta thấy v8 = v5 gán lại giá trị v7 chứng tỏ v7 sau bằng tổng của 2 số v7 trước cộng lại.

Cộng với kết quả đã được encode nhận được:

encode

Giờ tôi code decode thôi:

#nhận kết quả từ trên nc ....
flag_encode = "af a5 a8 ae b2 a5 a0 a7 bc b1 96 ba a1 a6 bc a5 ad 96 a8 ad ad 96 a4 b0 96 a4 ac a4 af bb a6 ab b4"

lst_from_flag = flag_encode.split(" ") # tách và chuyển thành list

lst_int_fe = []
for i in lst_from_flag:
    lst_int_fe.append(int(i,16))

# [175, 165, 168, 174, 178, 165, 160, 167, 188, 177, 150, 186, 161, 166, 188, 165, 173, 150, 168, 173, 173, 150, 164, 176, 150, 164, 172, 164, 175, 187, 166, 171, 180]

v7 = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144][::-1] # list các số xor nên ngược lại là ...

for i in lst_int_fe:
    for j in v7:
        i = i ^ j
    print( chr(i) ,end='')

Và kết quả nhận được là flag: flag{linux_should_add_my_memfrob}. Vậy là kết thúc 4 challenges đã giải được qua mùa giải này nhé.

results matching ""

    No results matching ""