Mở đầu

Giải này mình chưa có thời gian làm crypto nhiều lắm. Nhưng cũng làm được 2 bài re. Nói chung là cũng khá ổn.

Table of Content


[Crypto] LSB oracle attack

Bài này là một bài RSA thuộc dạng LSB oracle. Sad là theo cách giải thông thường thì cần n cố định. Thế nên bài này mình bế tắc luôn.
Sau khi nằm vùng và biết được writeup của tác giả đây. Thì cũng ngộ ra là đúng là có cách để giải LSB oracle mà không cần n không đổi.
Ý tưởng : Extract từng bit của plaintext từ bit nhỏ nhất bằng cách mỗi lần lại decrypt m/2^i.

Ý tưởng khá là giống với cách thông thường nhưng nó cũng khá là khác. Đơn giản mà không nghĩ ra. Cơ bản là mình quá lệ thuộc vào cách giải cũ mà lười suy nghĩ cách giải mới. Đi theo lỗi mòn thế là rơi vào đường cụt. 😭😭😭


[Reverse] Cliche_clickme

Đây là một file Mach-O nhưng reverse không khác gì một file ELF thông thường. Sau khi reverse và đổi tên thì ta có được file readable.

Ta thấy trong hàm main_ có hàm in ra chữ Congratz tức là input của chúng ta là đúng.
Đây thuộc dạng bài keygen. Tức là tìm key để cho ra flag. Chúng ta có các hàm check input là func1 -> func4.
Sau khi reverse các func đó thì mình chốt lại là chỉ cần quan tâm đến func2.

Do ở đây sau khi setup heap trong func1 từ input ban đầu thì nó so sánh với giá trị được lưu trong binary.
Sau khi reverse func3 có thể đưa ra kết luận input là chuỗi kí tự có độ dài 37. Mà từ func2 chúng ta có 666 phương trình mà chỉ có 37 ẩn nên luôn đủ để giải ra nghiệm.

Từ đây đáp vào Z3 để giải thôi.

from z3 import * 
arr = [0xD7,0xCC,0xDD,0xCF,0xE4,0xBD,0xD1,0x9D,0xDD,0xDC,0xC8,0xD1,0xCE,0x9A,0x9A,0xC8,0xD5,0x99,0xDD,0xC8,0x99,0xCF,0xC8,0xE0,0x99,0xDB,0xD4,0xC8,0xE0,0x9D,0xDC,0xC8,0xD2,0xDD,0xA8,0xE6,0xD1,0xE2,0xD4,0xE9,0xC2,0xD6,0xA2,0xE2,0xE1,0xCD,0xD6,0xD3,0x9F,0x9F,0xCD,0xDA,0x9E,0xE2,0xCD,0x9E,0xD4,0xCD,0xE5,0x9E,0xE0,0xD9,0xCD,0xE5,0xA2,0xE1,0xCD,0xD7,0xE2,0xAD,0xEB,0xD7,0xC9,0xDE,0xB7,0xCB,0x97,0xD7,0xD6,0xC2,0xCB,0xC8,0x94,0x94,0xC2,0xCF,0x93,0xD7,0xC2,0x93,0xC9,0xC2,0xDA,0x93,0xD5,0xCE,0xC2,0xDA,0x97,0xD6,0xC2,0xCC,0xD7,0xA2,0xE0,0xDA,0xEF,0xC8,0xDC,0xA8,0xE8,0xE7,0xD3,0xDC,0xD9,0xA5,0xA5,0xD3,0xE0,0xA4,0xE8,0xD3,0xA4,0xDA,0xD3,0xEB,0xA4,0xE6,0xDF,0xD3,0xEB,0xA8,0xE7,0xD3,0xDD,0xE8,0xB3,0xF1,0xE1,0xBA,0xCE,0x9A,0xDA,0xD9,0xC5,0xCE,0xCB,0x97,0x97,0xC5,0xD2,0x96,0xDA,0xC5,0x96,0xCC,0xC5,0xDD,0x96,0xD8,0xD1,0xC5,0xDD,0x9A,0xD9,0xC5,0xCF,0xDA,0xA5,0xE3,0xCF,0xE3,0xAF,0xEF,0xEE,0xDA,0xE3,0xE0,0xAC,0xAC,0xDA,0xE7,0xAB,0xEF,0xDA,0xAB,0xE1,0xDA,0xF2,0xAB,0xED,0xE6,0xDA,0xF2,0xAF,0xEE,0xDA,0xE4,0xEF,0xBA,0xF8,0xBC,0x88,0xC8,0xC7,0xB3,0xBC,0xB9,0x85,0x85,0xB3,0xC0,0x84,0xC8,0xB3,0x84,0xBA,0xB3,0xCB,0x84,0xC6,0xBF,0xB3,0xCB,0x88,0xC7,0xB3,0xBD,0xC8,0x93,0xD1,0x9C,0xDC,0xDB,0xC7,0xD0,0xCD,0x99,0x99,0xC7,0xD4,0x98,0xDC,0xC7,0x98,0xCE,0xC7,0xDF,0x98,0xDA,0xD3,0xC7,0xDF,0x9C,0xDB,0xC7,0xD1,0xDC,0xA7,0xE5,0xA8,0xA7,0x93,0x9C,0x99,0x65,0x65,0x93,0xA0,0x64,0xA8,0x93,0x64,0x9A,0x93,0xAB,0x64,0xA6,0x9F,0x93,0xAB,0x68,0xA7,0x93,0x9D,0xA8,0x73,0xB1,0xE7,0xD3,0xDC,0xD9,0xA5,0xA5,0xD3,0xE0,0xA4,0xE8,0xD3,0xA4,0xDA,0xD3,0xEB,0xA4,0xE6,0xDF,0xD3,0xEB,0xA8,0xE7,0xD3,0xDD,0xE8,0xB3,0xF1,0xD2,0xDB,0xD8,0xA4,0xA4,0xD2,0xDF,0xA3,0xE7,0xD2,0xA3,0xD9,0xD2,0xEA,0xA3,0xE5,0xDE,0xD2,0xEA,0xA7,0xE6,0xD2,0xDC,0xE7,0xB2,0xF0,0xC7,0xC4,0x90,0x90,0xBE,0xCB,0x8F,0xD3,0xBE,0x8F,0xC5,0xBE,0xD6,0x8F,0xD1,0xCA,0xBE,0xD6,0x93,0xD2,0xBE,0xC8,0xD3,0x9E,0xDC,0xCD,0x99,0x99,0xC7,0xD4,0x98,0xDC,0xC7,0x98,0xCE,0xC7,0xDF,0x98,0xDA,0xD3,0xC7,0xDF,0x9C,0xDB,0xC7,0xD1,0xDC,0xA7,0xE5,0x96,0x96,0xC4,0xD1,0x95,0xD9,0xC4,0x95,0xCB,0xC4,0xDC,0x95,0xD7,0xD0,0xC4,0xDC,0x99,0xD8,0xC4,0xCE,0xD9,0xA4,0xE2,0x62,0x90,0x9D,0x61,0xA5,0x90,0x61,0x97,0x90,0xA8,0x61,0xA3,0x9C,0x90,0xA8,0x65,0xA4,0x90,0x9A,0xA5,0x70,0xAE,0x90,0x9D,0x61,0xA5,0x90,0x61,0x97,0x90,0xA8,0x61,0xA3,0x9C,0x90,0xA8,0x65,0xA4,0x90,0x9A,0xA5,0x70,0xAE,0xCB,0x8F,0xD3,0xBE,0x8F,0xC5,0xBE,0xD6,0x8F,0xD1,0xCA,0xBE,0xD6,0x93,0xD2,0xBE,0xC8,0xD3,0x9E,0xDC,0x9C,0xE0,0xCB,0x9C,0xD2,0xCB,0xE3,0x9C,0xDE,0xD7,0xCB,0xE3,0xA0,0xDF,0xCB,0xD5,0xE0,0xAB,0xE9,0xA4,0x8F,0x60,0x96,0x8F,0xA7,0x60,0xA2,0x9B,0x8F,0xA7,0x64,0xA3,0x8F,0x99,0xA4,0x6F,0xAD,0xD3,0xA4,0xDA,0xD3,0xEB,0xA4,0xE6,0xDF,0xD3,0xEB,0xA8,0xE7,0xD3,0xDD,0xE8,0xB3,0xF1,0x8F,0xC5,0xBE,0xD6,0x8F,0xD1,0xCA,0xBE,0xD6,0x93,0xD2,0xBE,0xC8,0xD3,0x9E,0xDC,0x96,0x8F,0xA7,0x60,0xA2,0x9B,0x8F,0xA7,0x64,0xA3,0x8F,0x99,0xA4,0x6F,0xAD,0xC5,0xDD,0x96,0xD8,0xD1,0xC5,0xDD,0x9A,0xD9,0xC5,0xCF,0xDA,0xA5,0xE3,0xD6,0x8F,0xD1,0xCA,0xBE,0xD6,0x93,0xD2,0xBE,0xC8,0xD3,0x9E,0xDC,0xA7,0xE9,0xE2,0xD6,0xEE,0xAB,0xEA,0xD6,0xE0,0xEB,0xB6,0xF4,0xA2,0x9B,0x8F,0xA7,0x64,0xA3,0x8F,0x99,0xA4,0x6F,0xAD,0xDD,0xD1,0xE9,0xA6,0xE5,0xD1,0xDB,0xE6,0xB1,0xEF,0xCA,0xE2,0x9F,0xDE,0xCA,0xD4,0xDF,0xAA,0xE8,0xD6,0x93,0xD2,0xBE,0xC8,0xD3,0x9E,0xDC,0xAB,0xEA,0xD6,0xE0,0xEB,0xB6,0xF4,0xA7,0x93,0x9D,0xA8,0x73,0xB1,0xD2,0xDC,0xE7,0xB2,0xF0,0xC8,0xD3,0x9E,0xDC,0xDD,0xA8,0xE6,0xB3,0xF1,0xBC]
input = [BitVec('input%s' %i, 8) for i in range(37)] 

s = Solver() 
k = 0 
for i in range(37) : 
    for j in range(i+1,37) :  
        s.add(input[i] + input[j] == arr[k])
        k += 1 
s.check() 
flag= ""
m = s.model() 
for i in range(37) : 
    flag += chr(int(str(m[input[i]]))) 
print flag 

Chúng ta có thể dump giá trị trong binary ra bằng cách bôi đen tất cả các giá trị muốn export (kéo chuột hoặc Shift + mũi tên xuống). Sau đó trong IDA chọn Edit -> Export data -> C unsinged char . Cho vào visual code để fix lại dạng đúng chuẩn python array .


[Reverse] Tic Tac Toe

Bài này lúc vào sẽ bị choáng ngợp bởi số lượng hàm của nó. Mình không biết đi từ đâu về đâu luôn.
Chúng ta có thể bắt đầu từ hàm start.

Nhưng tin mình đi nó sẽ chẳng đi đến đâu cả vì chương trình rất lớn, phần đầu nó thực hiện rất nhiều công đoạn , reverse nó là một nỗ lực lớn. Nhưng có cách ngắn hơn thì tội gì phải đi con đường dài đúng không 😁😁😁. Có một kinh nghiệm là trace theo những hàm quan trọng.
Đây là một ứng dụng windows về trò chơi tic-tac-toe. Khi đi một cơ số nước thì nó sẽ in ra một hộp thoại.

Và chúng ta hi vọng là khi ta đi theo một quy luật nào đó thì nó sẽ in ra cho chúng ta flag. Đó là một viễn cảnh tươi đẹp. 😍😍😍 Nhưng khả năng đi bừa mà ra flag là vô cùng nhỏ. Nên đừng hi vọng nhiều để rồi thất vọng.
Ok đến đây ta có thể nghĩ tới việc trace theo hàm in ra dialog box - MessageBoxW. Vào cửa sổ Imports và search từ mess :

Kích đúp, chọn vào từ khóa MessageBoxW rồi bấm X .

Nó sẽ hiện ra một bảng là những hàm đã gọi hàm này. Chúng ta xem lần lượt từng cái thì thấy hầu hết nó sẽ in ra toàn mấy cái linh tinh.😳😳😳 Duy chỉ có một cái nó in ra Lptext.

Có nghĩa là cái text ấy chưa xác định và thay đổi theo input user nhập vào. 😀😀😀 Đến đây thì cũng đoán được 90% nó là flag rồi.
F5 lần nữa và ta đang ở một hàm kiểu như encode, decode gì đó :

Sau khi encode, decode thì nó sẽ lưu vào Str rồi in ra màn hình.

Hàm này tương tự như một bài keygen nó sẽ checkinput của chúng ta xem có hợp lệ không rồi quyết định in ra flag ko ? Input độ dài 16 . Thấy quen thuộc không ? Ta sẽ có các phương trình và các biến nên là cho hết vào Z3 để giải thôi. Đoạn code của nó hơi dài , nhưng cứ từ từ add vào cẩn thận là ok. Có một mẹo là copy y nguyên code C trong IDA vào visual code rồi sửa thì sẽ đỡ tốn công hơn 😉😉😉.

Flag ra hơi lởm nhưng chữ đầu hoàn toàn đoán được nên cũng OK.

END