Lời nói đầu: Đây là những challenge mà mình ra ý tưởng, và những challenge này nếu đã làm quen với python và xài một ít thư viện thôi là có thể giải ra
Một challenge về RSA:
Nếu như các bạn chưa biết về RSA thì bạn có thể tìm hiểu từ nhiều nguồn khác nhau, trong đó có wiki, và nếu như các bạn đã có tìm hiểu qua mảng crypto thì RSA rất phổ biến.
Trong bài này ta cần lưu ý những chi tiết sau:
python=bytes_to_long(FLAG)
là hàm được lấy ra từ thư viện Crypto.Util.number
có chức năng chuyển FLAG
từ bytes sang một dãy số nguyên thập phân tương ứng)c
tức là ciphertext
rút gọn, và thứ ta cần tìm là bytes_to_long(FLAG)
, ta biết được hint1
là p+q
, hint2
là p*q - p - q + 1
và chính là (p-1)*(q-1)
. Từ đây ta có thể tính ra p
và q
bằng cách giải phương trình bậc hai.p
va q
thì ta tính phi
và sau đó là d
, phi
trong bài này sẽ được tính là phi = (p-1)*p*(q-1)*q
vì phi
có cách tính tuỳ theo n
được miêu tả trong trang wiki nàyd
thì ta giải mã FLAG từ c
bằng cách pow(c,d,n)
tức là và FLAG đang là số nguyên, chuyển lại sang bytes thì ta sẽ có flag hoàn chỉnh.Tổng quát:
Mình cũng có một bài viết về cách giải một bài tương tự nhưng khác là cho p*q
chứ không phải là p+q
nhưng cách giải vẫn tương tự trong link
Có nhiều phương pháp và nhiều thư viện khác nhau để giải một trong số đó thuận tiện nhất là sử dụng sympy, z3 và sagemath, hoặc không sử dụng thư viện nào.
Cách giải bằng sympy:
Đây là đề:
Nếu để ý thì sẽ biết ngay đây là phép nhân ma trận vuông với một vector và lặp lại nhiều lần với vector kết quả của phép nhân trước là vector bị nhân của phép nhân sau. Việc này lặp lại 100 lần nên output khá lớn. Ta cần tìm lại vector gốc của toàn bộ vòng lặp nhân ma trận này vì đó chính là flag
(enc = [num for num in flag]
)
Nói đến ma trận, có một đặc tích cần lưu ý đó là kích thước 'shape' của ma trận, khi nhân một ma trận với một ma trận khác hay một vector thì ta cần lưu ý đến điều đó.
Với cách giải thì để thuận tiện mình có thể dùng sagemath hoặc numpy. Sau đây là cách giải bằng sagemath:
Đây là đề:
Đây là nội dung file ciphertext.txt
Xem lướt qua nội dung file ciphertext.txt thì có thể thấy được flag được nằm ở cuối, và ta biết flag format là 'W1{…}', từ đó suy ra nếu ta biết được vị trí key tương xứng với 2 bytes '0b6d' thì ta biết được một phần của key.
Nói đến key thì key chỉ có 4 bytes nhưng được làm kéo dài lên 8 bytes bằng cách cộng thêm 4 bytes đầu lật ngược lại (key[::-1]
) ở dòng 10 (việc lật ngược lại ở đoạn cuối không ảnh hưởng đến key), nên phương án brute-force là có thể thực hiện nhưng sẽ khá lâu (256^4 = 4294967296) vì thế nên dựa vào những gợi ý từ ciphertext
ta có thể dò ra từng byte của key và giải mã message
sẽ nhanh hơn.
Đây là code giải:
Bên trên là cách giải 3 bài của mình, mình rất vui khi đã có thể được tham gia ra đề và được các bạn feedback. Và cũng mong các bạn đã có những giây phút căng thẳng nhưng vui vẻ khi đã tham gia Wannagame Freshman năm nay
#KienSD