DefCamp 2022

DefCamp 2022


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

Chào mừng bạn đã quay trở lại với 1 vài bài RE thú vị và khá đơn giản của giải mà phải nói là tôi tham gia ngẫu hứng thui 😁. Không dài dòng nữa vào việc thôi.

1: cryogenics (Solved)

tiêu đề nhiệm vụ

Cái đề bài cũng không có gì (nhưng lúc trong quá trình giải khiến tôi phải tốn thời gian về nó quá)

Bắt đầu với việc tải file (Link nguồn tôi có để trên đầu bài rồi nhá) và kiểm tra xem thông tin file nhỉ: Nay tôi sài phần mềm HxD - phần mềm chỉnh sửa hex:

open

Đó như ta quan sát thấy có dòng .ELF - Executable and Linkable Format - định dạng phổ biến dành cho các mã thực thi, code đối tượng, thư viện được chia sẻ và kết xuất lõi, được xuất bản cho giao diện nhị phân ứng dụng (ABI) của phiên bản hệ điều hành Unix. Đại lại nó phù hợp để chạy trên Ubuntu, linux,…(nó được phát triển từ các OS Unix.

Chú thích: 0x7F theo sau ELF (45 4C 46) và bytes tiếp theo số 5 nếu là 01 thì 32 bit or 02 thì 64 bit nhá.

Tôi mở máy ảo linux và chạy thử:

run

Thử thách yêu cầu đầu vào là Password và output cho ta flag💀. Tôi sẽ chạy IDA để phân tích

open ida

Bắt đầu đọc code nào🫡: (Tôi thấy bài code bị dối và có thể đã có tác động khiến IDA không hiện thi đúng logic của chương trình, bởi đó mình thường sẽ đi kiếm stringscủa chương trình):

find strings

Đó ta nhận thấy có đoạn strings (shortcut key: Shift + F12) output mà ta đã bắt gặp khi chạy. Too cold outside -> cứ tiếp tục theo đó nào. Nhấn đúp chuột:

show add

nhấn X để hiện thị xem câu lệnh nào gọi hay sử dụng đến strings đó

show control

và nhận và ta thấy có câu lệnh test eax, eax kiểm tra để chuyển hướng chương trình:

07

trước câu lệnh test có câu lệnh call đến function để kiểm tra gì đó rồi trả về giá trị eax đem so sánh, và ở dưới đó có lệnh jnz jump if not zeoro - nhảy nếu không bằng hay là output Too... và kết thúc chương trình không thỏa mãn điều kiện.

Đi vào strcmp và sử dụng F5 huyền thoại nhé))

// positive sp value has been detected, the output may be wrong!
__int64 __fastcall strcmp(__int64 a1)
{
  __int64 v1; // rax
  __int64 i; // rax
  char v4[15]; // [rsp+2h] [rbp-26h] BYREF
  char v5[23]; // [rsp+11h] [rbp-17h] BYREF

  qmemcpy(v4, "000000000000000", sizeof(v4)); // đại khái như tôi hiểu là nếu input cho mk mà bé hơn kích thước của biến v4 sẽ chèn 0000000 vào sau input
  v1 = 0LL;
  qmemcpy(v5, &unk_400328, 0xFuLL); // khả năng lấy dữ liệu đã lưu
  do
  {
    v4[v1] = __ROL1__(*(_BYTE *)(a1 + v1), 3); // __ROL1__: circular rotation to the lelf (xoay vòng tròn sang trái) (unit8)
    ++v1;
  }
  while ( v1 != 15 );
  for ( i = 0LL; i != 15; ++i )
    v4[i] = __ROR1__(v4[i], 2); // __ROR1__: circular rotation to the right (xoay vòng tròn sang phải) (unit8)
  return ((__int64 (__fastcall *)(char *, char *, __int64))strncmp)(v4, v5, 15LL); //gọi hàm tiếp
}

Kiểm tra biến &unk_400328 không xác định có địa chỉ:

show var unk

đó là 1 mảng ta định dạng 1 chút nó sẽ trông như này:

09

Như định dạng có nó theo dạng byte (vì đang là unit8), tạo mảng với phím tắt A và kết quả nhận được như hình trên với mảng gồm 15 phần tử.

__ROR1__ và __ROL1__ đại lại là nhân và chia với 2 các cơ số lần. Tôi tham khảo được code python của nó ở 1 trang web này: Link đây nhé

show blog

và thứ chúng ta cần nè code python:

def __ROL__(num, count, bits=8):
    return ((num << count) | (num >> (bits - count))) & ((0b1<<bits) - 1)

def __ROR__(num, count, bits=8):
    return ((num >> count) | (num << (bits - count))) & ((0b1<<bits) - 1)

Tiếp đến ta đi vào hàm strncmp xem thế nào: (với 3 tham số đầu vào: v4 là input của mình đã được ROR và ROL, v5 là mảng được lấy từ nguồn lưu trữ, 15LL là kích thước của input và cũng là kích thước của mảng)


// positive sp value has been detected, the output may be wrong!
__int64 __fastcall strncmp(__int64 a1, __int64 a2, __int64 a3)
{
  __int64 v3; // r8
  unsigned __int8 *v4; // r9
  unsigned __int8 v5; // al
  char v6; // cl

  v3 = 0LL;
  do
  {
    v4 = (unsigned __int8 *)(a2 + v3);
    if ( a3 == v3 )  // so sánh với kích thước
      return 0LL; // kết quả return mong muốn mà ta muốn đây rồi
    v5 = *(_BYTE *)(a1 + v3);   //lấy giá trị phần tử thứ v3 (input) trong mảng
    if ( !v5 ) //if not tồn tại giá trị v5 dừng vòng lặp do while
      break;
    v6 = *(_BYTE *)(a2 + v3++); // lấy value phần tử thứ v3 của a2 (nguồn) trong mảng rồi tăng giá trị của v3 lên 1
  }
  while ( (char)v5 == (v6 ^ 0xC) + 6 ); //kiểm tra v5 với v6 xor với 0xC + 6
  return v5 - (unsigned int)*v4; 
}

Thế là ý tưởng của bài đã được hé lộ rồi, giờ tôi sẽ sử dụng python để viết ra đoạn mã cần -> flag🏴 Dưới là code python solve của tôi nhé:

def __ROL__(num, count, bits=8):
    return ((num << count) | (num >> (bits - count))) & ((0b1<<bits) - 1)

def __ROR__(num, count, bits=8):
    return ((num >> count) | (num << (bits - count))) & ((0b1<<bits) - 1)

lst = [166, 166, 108, 226, 226, 222, 132, 188, 124, 236, 226, 120, 152, 166, 166]

for i in lst:
    for x in range(256):
        if  (i ^ 12) + 6 == __ROR__(__ROL__(x,3),2):
            print(chr(x), end="")

Kết quả nhận được đúng theo yêu cầu đề bài là được đóng băng, kết thúc bằng XX: XX3zzlG[;sz=MXX và mã hóa sha256là xong -> Kết quả nhận được CTF{a41f954f18646f115d653d28213175a6d9ef0d383c80c99ac0ee060c217b99c6} -> Done 1 bài thú vị.

Lúc đầu tôi chơi nhìn qua thì họ đánh lừa tôi tới 2 lần (lần 1 là đoạn strings công khai kiến tôi tưởng là so sánh với nó và –> game easy, but not; lần 2 là hàm strncmp làm tôi lần tưởng chỉ so sánh và trả về 0 hoặc âm dương không thôi ai dè có cũng còn xor and add six🥶 mới ra).

2: new-buldozer (Solved)

title

Đến với thử thách này ta được làm quen với chương trình trên điện thoại di động, cụ thể là Android.

Tôi sử dụng tool apktool để giải mã và đọc nó xem sao nhá:

run apktool

Nó sẽ trả về cho chúng ta 1 thư mục mà công cụ có thể giải mã được. Tiếp đến tôi mở ra và kiếm kiểm tra các file và mở chúng bằng tool jadx-gui (Thường là các file có đuôi .smail):

open jadx

Tôi kiểm tra qua hết tất cả thì không thấy có gì đó cả toàn các hàm của chương trình thực thi bằng java. Tiếp đến tôi thấy nghi ngờ file private.taz được nén vào mà tôi chưa đọc:

ex

Ồ có hẳn 3 file trong đó và giờ tôi vào đọc nó, format file .pyc - là file thông dịch Python khi nó chuyển đổi code thành mã bytecode được biên dịch.

Tôi thử kiếm strings trong file trước xem sao:

strings main.pyc 
 X3c
m       Z
1.0.9)
Builder)
GridLayout)
NumericProperty)
Appz
<HelloWorldScreen>:
    cols: 1
    Label:
        text: 'Welcome to the Hello world'
    Button:
        text: 'Click me! %d' % root.counter
        on_release: root.my_callback()
HelloWorldScreenr
The button has been pushed
V1ROU2JXVjZaRzFPVkZKc1RWUldhVmt5V1hsYVZFNXFUVmRaTVU1NlVUVlplbWhvVG5wU2JVMVVRVEJOYW1jeFdXcGplRnBYV1RKWk1sVjZUVlJCZUZsNmJHMU9SMVY2VFZkU2ExbHRVbXhOVkZVMFRsUlZlazlFU2prPQ==)
print
counter
self
H/home/lucian/Desktop/ctf/new-buldozer/dev/.buildozer/android/app/main.py
my_callback
HelloWorldScreen.my_callbackN)
__name__
__module__
__qualname__r
HelloWorldAppc
build
HelloWorldApp.buildN)
__main__)
kivyZ
requireZ        kivy.langr
kivy.uix.gridlayoutr
kivy.propertiesr
kivy.appr
load_stringr
runr
<module>

Ồ có 1 đoạn mã base64 kìa decode xem sao nhá và kết quả khi ném nó lên CyberChefthì thật bất ngờ:

decode

Thật là Magic luôn khi tôi chỉ giải mã base64 1 lần còn lại do web gợi í và đúng như ý muốn.😜

Và tất nhiên rồi flag: ctf{7f54e15bcf2e3c1f5749c8a74f104285b71ef6ce3101c9f4e31ddbde15855382}.

3: xrypto (Unsolved)

__int8, __int16, __int32, __int64 - Tương ứng với biến khai biến có kích thước 8, 16, 32, 64 bit.

__readfsbyte, __readfsdword, __readfsqword, __readfsword đọc bộ nhớ từ một vị trí được chỉ định bởi một phần bù so với đầu của offset FS:[Offsett]

results matching ""

    No results matching ""