Check Solve


👊👆🤲

[CRYPTO] rps

Bài này là một bài hash , nhưng hash lại có thể dịch ngược được nên không có gì khó cả :))))


👊👆🤲

[CRYPTO] ayyMessage

Bài này là một bài ECC digital signature + AES CTR. Chúng ta được cho một đoạn mã hóa.

  • ECC digital signature : ta có thể dễ dàng pass vì có thể thay đổi public key thành key mình tự gen.
  • AES CTR :

Sau khi đã giả chữ kí, chúng ta có thể giải mã bất kì đoạn message nào và thu được SHA256 của nó.
Đầu tiên, ta thực hiện mã hóa đoạn mã một kí tự. Sau đó bruteforce từ 0 -> 256 để tìm ra được đoạn giải mã p của nó. Ta thu được D(aeskey, nonce) = p xor m.
Tiếp tục làm như vậy, ta thu được D(aeskey, nonce) -> giải mã được đoạn mã hóa.


👊👆🤲

[RE] years 3000

Bài này giống bài Defcon CTF 2017 Sorcery mình đã trình bày ở đây
Dùng angr để explore path xong capstone để đọc câu lệnh assemble, từ đó tìm kiếm thông tin thôi.
Bài này có cách khác là đọc file, vì vị trí của các kí tự cần tìm ở vị trí xác định :)))


👊👆🤲

[PWN] kid

Bài này mình không làm ra trong thời gian thi vì một số lỗi vớ vẩn. *(  ̄皿 ̄)/#_
Checksec ta có :

Chương trình chỉ có một hàm main đơn giản :

Chương trình này cho phép chúng ta lần đầu thực hiện sẽ được phép nhập số liệu vào v7 từ đó thay đổi thanh ghi rsp -> lỗi buffer overflow. Cần thực nghiệm vài lần thì sẽ tìm ra được số cần nhập để đạt yêu cầu.
Mình thử nghiệm thì nhập giá trị : 1 << 63 + 0x280 thì được esp mới cách địa chỉ trở về của hàm main là 136 kí tự. Chúng ta được quyền nhập dx = 0x280 kí tự. Đủ để tràn tới địa chỉ trở về.
😥 Bằng một cách magic nào đó mà khi tắt ASLR thì hàm đọc sẽ không đọc đủ kí tự.Mặc dù mình debug thấy edx = 0xffff mà nó vẫn không đọc kí tự nào. Cũng vì vậy mà lúc đầu mình tốn khá nhiều thời gian tại đây khi mọi thứ hoạt động không như mong muốn.

😅😅😅 Mình nhận ra lỗi này đầu tiên. Mãi về sau mới phát hiện ra một lỗi cơ bản khác là format string.

Step 1 : Leak information

Tận dụng lỗi format string, mình dùng %30$p thì leak được địa chỉ của 0x750. Trừ đi ta có địa chỉ PIE.
Cũng có thể leak địa chỉ LIBC thông qua lỗi formatstring nhưng vì mình phát hiện lỗi tràn trước nên là mình leak libc theo kiểu : tràn tới 2 bytes cuối của địa chỉ trở về của hàm main, khi in nó sẽ in luôn ra địa chỉ trở về.

Step 2 : Ret2main

Chúng ta thực hiện tràn trước khi biết được địa chỉ trở về. Cho nên không thể tràn về main ngày được.
Địa chỉ trở về của hàm main ban đầu là : __libc_start_main. Hàm này được gọi ở start.

0x00007f08acbdfb84 <+212>:	mov    rsi,QWORD PTR [rsp+0x8]
0x00007f08acbdfb89 <+217>:	mov    edi,DWORD PTR [rsp+0x14]
0x00007f08acbdfb8d <+221>:	mov    rdx,QWORD PTR [rax]
0x00007f08acbdfb90 <+224>:	mov    rax,QWORD PTR [rsp+0x18]
0x00007f08acbdfb95 <+229>:	call   rax         // call main 

Do chưa biết địa chỉ của hàm nào nên chỉ có thể sửa 2 byte cuối của __libc_start_main thôi. (ta đã biết 3 bytes, bruteforce 1 bytes).
Khi debug, tận dụng stack mình thấy nếu gọi __libc_start_main + 224, thì rax = main. Tức chúng ta có thể trở về hàm main bằng cách này. :))) Nó luôn luôn hoạt động vì hàm start lúc bắt đầu có push main.

Step 3 : Overwrite exit

Do Sau khi trở lại main lần 2, unk_20105C = 1 nên nó sẽ vào in ra JK, You lose rồi exit mà không thực hiện ret2main.
Điều này khá đơn giản vì chúng ta đã có lỗi format string để ghi đè.
(*  ̄︿ ̄)Đó là mình nghĩ thế còn khi viết script thì chật vật mãi mới xong. Mình có viết được một hàm automatic gen formatstring write , lưu lại sau dùng dần :

def format_write(addr, number) : 

    payload = '' 
    old_c = 0 
    value = []
    for i in range(8) : 
        value.append((number >> (i * 8)) % 256)
        
    for i in range(len(value)) : 
        new_c = value[i]  
        if new_c > old_c : 
            res = new_c - old_c 
        else : 
            res = 256 + new_c - old_c
        old_c = new_c 
        payload += '%' + str(res) + 'c' + '%' + '{}$hhn'
        
    payload += '0' * (8 - len(payload) % 8)
    offset = len(payload) / 8 + 6
    payload = payload.format(*[offset + i for i in range(len(value))] )
    for i in range(8) : 
        payload += p64(addr + i)
    return payload 
    

Mình đã thử overwrite exit bằng one_gadget nhưng không thành công.Đành overwrite thành main xong chuyển printf thành hàm system gọi /bin/sh\x00 thôi :))) done

🎇🎇🎇 Đọc writeup : https://github.com/kam1tsur3/2020_CTF/blob/master/nullcon/pwn/KiDPwN/README.md thì thầy người ta dùng ROP.Cụ thể là dùng 3pop; ret thì cũng đạt hiệu quả tương tự. Cách suy nghĩ này hay hơn vì không phục thuộc vào hàm __libc_start_main mà hàm này lại thay đổi theo từng phiên bản libc nên khó để cân bằng trên server. Đồng thời, lúc đó lại dùng one_gadget được :v Đọc mới thấy cách của người ta tối ưu vl (っ °Д °;)っ


👊👆🤲

[PWN] Dark Honya

Link writeup : https://teamrocketist.github.io/2020/02/09/Pwn-Nullcon-2020-DarkHonya/
Mình đọc nhiều bài writeup của nhóm này viết rất hay, dễ hiểu. Bài này là một bài heap sử dụng kĩ thuật unlink + null-byte overflow.

  • null-byte overflow : ghi đè lên tạo fake free chunk -> unlink
  • unlink : ghi đè lên ptr[0] = ptr[0] - 0x18
    Thực ra đây là unsafe unlink được trình bày bởi shellfish : https://github.com/shellphish/how2heap/blob/master/glibc_2.26/unsafe_unlink.c
    Từ đó chúng ta có thể ghi đè lên GOT -> thực hiện leak libc bằng lỗi format string bằng cách ghi đè atoi thành printf. Sau khi leak, ghi đè atoi thành system -> get shell.


👊👆🤲

[PWN] Chocolate-chip

Link writeup : https://github.com/ironore15/ctf/tree/master/2020-HackIM/chocolate-chip
Phần đầu tiên của bài này là phải tìm được random number được đọc từ file thông qua một đoạn mã hóa ngẫu nhiên. Chúng ta có thể dễ dàng giải bằng Z3.

Tiếp đến, chúng ta có lỗi tràn và có thể kiểm soát được địa chỉ trở về, no canary found. Đây là một bài ROP cơ bản. Nhưng trong thời gian thi mình chưa có thời gian động tới bài này. Ngồi luyện lại tí ROP nhưng có vẻ mình cũng quên khá nhiều rồi :))))
Ta có các gadget cơ bản để thiết lập gọi một hàm như pop_rdi, pop_rsi, pop_rdx, ret, ….
Các bước tấn công như sau :

  • Leak libc bằng các gadget gọi hàm write
  • Overwrite GOT thay bằng hàm system
  • Ghi /bin/sh lên bss
  • Gọi hàm system với tham số /bin/sh
  • Get shell, cat flag