[Writeup] WhiteHat Grand Prix 2016

Thảo luận trong 'Writeup WhiteHat Grand Prix' bắt đầu bởi whf, 27/12/16, 11:12 PM.

  1. sunny

    sunny Điều hành viên Thành viên BQT

    Tham gia: 30/06/14, 10:06 PM
    Bài viết: 1,520
    Đã được thích: 637
    Writeup bài Bánh cuốn - by qt:

    Crypto 100

    [​IMG]


    This is basically a substitution cipher. You lookup the characters corresponding to your numbers using the table. For some numbers that are multiplication of 2 other numbers, use them as row/column indices.

    I solved this one by replacing the high-frequency numbers with characters and used SCBSolvr to do the rest.

    Writeup bài Bánh tráng cuốn thịt heo - by qt:

    Crypto 300

    The key is generated from a 8-byte seed so it has a very big weakness: it's repeating after every 72 bytes. Using known plain-text attack you can recover the key and decrypt the text.
     
  2. sunny

    sunny Điều hành viên Thành viên BQT

    Tham gia: 30/06/14, 10:06 PM
    Bài viết: 1,520
    Đã được thích: 637
    Writeup các bài: Bánh cống Sóc Trăng, Bánh chưng, Bánh canh Tràng Bảng by CLGTftMeePwn

    Web 100 - Bánh căn
    Challenge:

    I. Overview
    Sau khi xem qua một hồi, bài này tác giả filter các hàm như:
    • $blacklist = array("system", "passthru", "exec", "read", "open", "eval", "backtick", "`", "_");

    Để ý thấy không filter hàm assert :D. Quất thôi.
    More details: http://php.net/manual/en/function.assert.php

    [​IMG]


    Mục đích là read được file (flag có thể nằm trong source), tuy nhiên vấn đề là mặc dù run được hàm assert nhưng vẫn không thể read được file do bị filter các hàm read, dấu "_"....

    II. Bypass and build exploit:

    Bypass bằng cách chèn thêm dấu backslash vào hàm cần gọi và sử dụng hàm stripslashes ( không bị filter hàm này)

    Tuy nhiên vấn đề thứ hai là giá trị trả về sẽ vẫn là string, làm sao để excute nó như một function.

    => Tiếp tục sử dụng hàm assert.

    Như vậy final payload: Exploit()

    Và flag nằm trong file index.php


    [​IMG]



    Web 100 - Bánh canh Trảng Bàng


    Challenge:
    The Bug:
    Đây là một bài sql injection.
    Sau khi overview một hồi thì mình thấy có một file khá là khả nghi.
    được truyền hai tham số theo biến POST, lỗi blind SQLi rõ ràng
    • True case:
      [​IMG]
    • False case:

      [​IMG]
    Exploit:
    Sau khi extract hết DB thì không thấy flag đâu, tinh ý các bạn sẽ nhận thấy flag được nằm trong database khác.

    Payload:
    • data = "target=like-(3 and if(substr((select flag from flag.flag limit 1),%d,1)=binary('%s'),1,0))-area&status=3" % (i, j)
    Flag


    [​IMG]



    Web 200 - Bánh cống Sóc Trăng
    Challenge:
    Lại thêm một chall về sqli nữa. Mình đánh giá bài này không khó và chỉ mất thời gian.

    Bug: Blind Sql Injection tại:


    Có hai vấn đề:
    • Hàm limit bị filter.
    • Sau khi sử dump hết các tables và columns ra thì nhận ra flag nằm trong table backup và column image


    Raw data của file flags.png được lưu trong database với len xấp xỉ 16k ký tự, nếu blind bình thường với con dell ghẻ của mình thì tính toán sơ sơ hết 8 tiếng, tuy nhiên ta có thể optimize lại chương trình exploit, ở đây mình sử dụng multithread python

    My final payload:
    • url = '''http://web01.grandprix.whitehatvn.com/selectF00d.php?name=123"+or+if(binary(substr((select+hex(image)+from+backup),%d,1))=binary('%s'),1,0)--+-'''

    [​IMG]


    Mang lên vps (nếu có), cắm chạy và có flag.

    1/2 Web 500 - Bánh chưng
    Challenge:


    Part 1: Building a shell and upload

    Giao diện giống bài web 200. Challenge cho phép ta upload hình ảnh.


    [​IMG]


    Bài này tác giả lấy ý tưởng lại từ hai bài CodeGate General CTF 2015: Owlur và bài Web 300 MMA CTF 2015 mình cũng đã từng writeup.

    [​IMG]



    Bỏ qua công đoạn try hard nên mình đi thẳng vô exploit luôn

    How to exploit???
    • Tạo một file a.php send theo phương thức POST
    • Compress lại thành file b.zip và chuyển tên thành b.zip.jpg sau đó upload lên
    • Chạy shell

    [​IMG]


    Flag nằm ở thư mực: /home/tommy/


    [​IMG]


    Part 2: Pwn hello file and cat flag
    Tuy nhiên chúng ta không có quyền cat flag, phải pwn cái file hello (ELF file) và một thằng noob pwn như mình thì đến đây là dừng bước.

    [​IMG]



    Share tobe shared, teamwork is da best. Thanks for reading!!!
     
  3. sunny

    sunny Điều hành viên Thành viên BQT

    Tham gia: 30/06/14, 10:06 PM
    Bài viết: 1,520
    Đã được thích: 637
    Writeup các bài: Bún chả - Mỳ Quảng - ISITDTU Team

    Bun cha ( Cryptography) point 100

    Hướng dẫn giải:


    Đây là một dạng crypto dễ nên cách làm sẽ rất đơn giản.

    Chỉ cần biết g^a , b và ciphertext chúng ta đã có thể tìm được plaintext

    Vì m[g^(ab)][(gab)^(−1)] = m(1) = m theo lý thuyết .m ở đây chính là plaintext
    mg^(ab) là ciphertext. Để tìm plaintext chúng ta chỉ cần lấy ciphertext chia cho g^(ab) = g^(ba) = pow(pow(g,a),b)= pow(pow(g,b),a) .Với gb và a đã cho ở đề.Không cần phải bruteforce.

    Các dữ liệu đề còn lại chỉ nhằm mục đích đánh lạc hướng người chơi.Những ai có kiến thức cơ bản về Diffie Hellman đều có thể dễ dàng vượt qua thử thách này

    Flag là Bun_cha_ca

    Khó khăn và hướng giải quyết:

    Trong thuật toán trao đổi khóa Diffie Hellman a là số bí mật của Alice và b là số bí mật của Bob. Đoạn ciphertext được tạo ra bằng cách lấy plaintext nhân với gab. Bình thường khi nhìn vào người làm sẽ dễ lầm tưởng sẽ cần phải tìm được b để có thể tính toán g^(ab) với a và g nên sẽ làm theo cách bruteforce b, rất mất thời gian. Đơn giản ở đây ta có thể thấy g^(ab) = g^(ba) mà g^b và a đã cho trong đề nên chỉ cần tính toán ra số liệu sau đó lấy số cipher đã cho trong đề chia cho số đó ta sẽ tìm ra được kết quả. Những số liệu còn lại trong đề là không cần thiết.


    Mi Quang (Cryptography) point 100

    Hướng dẫn giải:

    Đầu tiên người chơi phải tìm được đúng chữ số tương ứng với đúng các ký tự và chữ cái trong bảng,

    Tạo thư viện sau đó viết code để có thể giải mã được ciphertext.

    Có thể chạy file decrypt.py trong mục decrypt để ra kết quả.

    Flag là you_should_try_miquang_danang_vietnam!!!

    Khó khăn và hướng giải quyết:

    Thực chất bảng có các ký tự và mặt cười được đưa ra trong đề là bẳng cửu chương của pytago

    [​IMG]








    [​IMG]




    Các ký tự được mã hóa dựa theo những số của bảng dưới.

    Bình thường khi nhìn vào một đoạn cipher text với rất nhiều số nhiều số và không theo quy luật hay không có nghĩa gì cả thì người làm sẽ rất khó có thể biết được nó thuộc dạng mã hóa nào thậm chí khi có bảng ký tự cho sẵn cũng rất khó có thể biết được nó là bảng cửu chương. Nhưng nếu nhìn kỹ ciphertext có thể thấy được những chữ số trong đó hầu hết là có 2 chữ số và là những số quen thuộc đều có thể phân tích thành thừa số. Từ đó có thể nhận biết được nó có liên quan đến phép nhân. Chỉ cần lên mạng tìm phép nhân hay bảng cửu chương sẽ dễ dàng thấy bảng cửu chương pytago, sau đó người làm có thể xây dựng lại bộ thư viện từ 2 bảng này (bảng đề cho và bảng cửu chương pytago). Sau đó ngường làm có thể viết code để giải mã cipher text.
     
    Last edited by a moderator: 19/01/17, 11:01 AM
  4. sunny

    sunny Điều hành viên Thành viên BQT

    Tham gia: 30/06/14, 10:06 PM
    Bài viết: 1,520
    Đã được thích: 637
    Writeup các bài Bành mì - Bánh Giầy - Bánh cuốn - ISITDTU team

    Banh Mi [Cryptography] 100 pts

    Từ tấm hình gợi ý ta Xor 3 đoạn lần lượt vớ 8bits, 16bits, 24 bits để tìm ra password giấu trong đoạn văn

    d = open('password.txt',"rb")

    g = open('decrypt.txt',"w")

    read1 = d.read()

    buff = read1.split('\n')

    tmpp =''

    for i in range(len(buff)):

    buf = buff

    for j in range(len(buf)):

    tmpp += chr(ord(buf[j])^(8+8*i))

    g.write(tmpp)

    g.close()

    [​IMG]

    Dùng mật khẩu giải nén ta có được hình chứa flag

    [​IMG]

    Banh Giay [Forensic] 100 pts

    [​IMG]

    File -> Export Object -> HTTP ta thấy có file secret

    [​IMG]

    Export tất cả, mở file secret bằng Hex

    [​IMG]

    Ta thấy đây là file đã bị nén dạng zip, giải nén và tìm cách mở

    [​IMG]

    Đúng như dự đoán có lẽ flag ở đây . Trở lại phân tích những file khác để tìm mật khẩu.

    [​IMG]

    Dựa vào hint nên mình quyết định bruteforce thử . Dùng fcrackzip để brute force. Mình test từ 2-4 và tìm được password là fuzu

    [​IMG]

    Sau khi giải nén nhận được 30 file flag.txt

    [​IMG]

    Nối các file lại và xóa các từ flag dư để decrypt các chuỗi md5

    [​IMG]

    Dùng Hashkiller.co.uk để decrypt

    [​IMG]

    SHA1 chuỗi vừa nhận được và submit flag

    Banh Cuon [Cryptography] 200pts

    Đây là một dạng bài RSA, nhìn thì có vẻ như đã có đủ các số hết rồi, nhưng mình không nghĩ như thế nên quyết định kiểm tra xem p & q có phải là số nguyên tố không

    e: 65537

    p: 1553762687409601943499178289783616523235812050573150316009646301542436391128879624646734300008782361965139513359

    q: 18393926378291118190346463738382882261613293132387833409

    c: 12682879488984861193795141642779903374526316499885184966492486107034525136565770064564244757954564431956497062324291051476829691654157833815737932841382692373398780347


    p1=346284627819235013

    p2=48108377392359593329

    p3=91836381613824658927

    p4=37252538404847211828439

    p5=27262151738933289423634232512139

    Đầu tiên ta thấy tại sao vừa có p rồi lại có p1,p2,p3,p4,p5 => ta biết được rằng là đề bài đang bẫy ta.

    Bây giờ ta check xem p va p1,p2,p3,p4,p5,q có số nào ko phải là số nguyên tố không => p không phải số nguyên tố ^^

    [​IMG]

    Thế bây giờ ta đã biết đề nó bẫy ở đâu ta trở lại làm 1 bài RSA multi number với tìm phi bằng cách:


    phi = (p1-1)(p2-1)(p3-1)(p4-1)(p5-1)(q-1)

    #!/usr/bin/env python2

    from numbthy import *


    p1= 346284627819235013

    p2= 48108377392359593329

    p3= 91836381613824658927

    p4= 37252538404847211828439

    p5= 27262151738933289423634232512139

    q = 18393926378291118190346463738382882261613293132387833409

    c = 12682879488984861193795141642779903374526316499885184966492486107034525136565770064564244757954564431956497062324291051476829691654157833815737932841382692373398780347

    e = 65537

    n = p1*p2*p3*p4*p5*q

    fi = (p1-1)*(p2-1)*(p3-1)*(p4-1)*(p5-1)*(q-1)

    d = invmod(e,fi)

    print 'd:',d

    m2 = powmod(c,d,n)

    print hex(m2)[2:-1].decode('hex')

    Yup! WhiteHat{ff94658cf7612e7f68de6d960caf6f9b92e8a4a4}!
     
    Last edited by a moderator: 21/01/17, 02:01 PM
  5. likehack

    likehack New Member

    Tham gia: 08/01/17, 09:01 PM
    Bài viết: 25
    Đã được thích: 2
    cho minh gợi ý bài banh beo bi binh duong đi
     
  6. sunny

    sunny Điều hành viên Thành viên BQT

    Tham gia: 30/06/14, 10:06 PM
    Bài viết: 1,520
    Đã được thích: 637
    Chào bạn likehack ,

    Hiện tại đã có 19/35 write up các bài thi được các đội đóng góp, những bài còn lại BTC sẽ bổ sung trong thời gian tới bạn nhé.
     
  7. firey522

    firey522 W-------

    Tham gia: 13/10/14, 11:10 AM
    Bài viết: 17
    Đã được thích: 8
    Writeup: Bánh tằm bì Bạc Liêu
    GrandPrix 2016 qua được gần 2 tháng rồi mà giờ mới có thời gian ngồi viết lại writeup :-"

    Đề bài cho chúng ta một trang HTML bao gồm 3 mảng số và 1 file python. Sau khi đọc thử file này có thể thấy đây là thuật toán thử tất cả các trường hợp để giải một loại câu đố tên là “Nonogram”.

    Ngoài ra khi view-source HTML cũng thấy một file ảnh “dirty.png” [​IMG]



    -> Chúng ta cần tìm được 3 QR code từ 3 mảng số đã cho
    -> ez game ez life

    Sẵn tính lười mình quyết định đưa vào một trang solve nonogram online luôn: “http://www.griddler.co.uk/Solve.aspx”
    Nhưng sau khi thử thì hình như có gì đó không đúng :-SS, chỉ có mảng số 3 là ra được một ảnh tương đối rõ ràng.

    Thử kiểm tra lại thì 2 mảng số 1 và 2 là các mảng 21x20 và tổng số pixel lệch nhau 1 đơn vị
    -> Đã có một hàng bị thiếu trong mảng, và hàng đó chỉ chứa 1 pixel
    -> Cần thêm một hàng chỉ chứa số 1 trước khi giải mã, số lượng tương đối nhỏ nên mình quyết định sẽ thử hết các trường hơp bằng đoạn code cùi bắp sau
    Mã:
    import time
    from selenium import webdriver
    
    def selenium_solver(cols, rows, result_img):
        driver = webdriver.Firefox()
        driver.get("http://www.griddler.co.uk/Solve.aspx")
        driver.find_element_by_id("TextboxNumberOfColumns").send_keys(21)
        driver.find_element_by_id("TextboxNumberOfRows").send_keys(21)
        driver.find_element_by_id("ButtonNext").click()
        time.sleep(1)
    
        count = 0
        for col in cols:
            flag = 0
            while flag == 0:
                try:
                    driver.find_element_by_id("TextboxColumnDefinition"+str(count)).send_keys(col.strip()[::-1])
                    flag = 1
                except:
                    time.sleep(1)
            count+=1
        driver.find_element_by_id("ButtonNext").click()
        time.sleep(2)
    
        count = 0
        for row in rows:
            flag = 0
            while flag == 0:
                try:
                    driver.find_element_by_id("TextboxRowDefinition"+str(count)).send_keys(row.strip()[::-1])
                    flag = 1
                except:
                    time.sleep(1)
            count+=1
        driver.find_element_by_id("ButtonNext").click()
        time.sleep(2)
        print result_img + 'done'
        driver.save_screenshot(result_img)
        driver.quit()
    
    #puzzle 3:
    puzzle ='7.1.1.1.7    ,     1.1.1.2.1.1    ,     1.3.1.2.1.1.3.1    ,     1.3.1.2.2.1.3.1    ,     1.3.1.2.1.1.3.1    ,     1.1.1.1.1    ,     7.1.1.1.7    ,     1.2    ,     5.7.2.1.1    ,     6.2.1.1.1.1    ,     1.4.1.4    ,     1.1.1.2.1.1.2.1    ,     5.2.3.1    ,     1.1.1.2.2    ,     3.8    ,     1.2.1.1.2.1.1    ,     3.3.1.3.1    ,     1.1.1.1.3.1.3.1    ,     5.3.1.3.1    ,     1.1.2.1.1.1    ,     1.7    ],    7.1.1.7    ,     1.1.1.1.1.1    ,     1.3.1.1.1.3.1    ,     1.3.1.1.1.1.3.1    ,     1.3.1.3.1.3.1    ,     1.1.1.3.1.1    ,     7.1.1.1.7    ,     2.2    ,     1.1.1.2.4.5    ,     1.1.1.2.1.1    ,     4.4.1.1.1.1    ,     2.2.3.4    ,     1.1.1.1.1.2.1.1    ,     1.4.2    ,     1.2.1.3.7    ,     1.1.6.1.1    ,     1.1.1.3.1.3.1    ,     1.1.1.3.1.3.1    ,     3.1.1.2.1.3.1    ,     1.2.1.1.1    ,     4.1.2.1.7'
    pos = puzzle.split('],')
    
    cols = pos[0].split(',')
    rows = pos[1].split(',')
    selenium_solver(cols,rows,'puzzle3.png')
    
    #puzzle 1,2
    puzzles = ['7.2.7    ,     1.1.1.1.1.1    ,     1.3.1.1.1.1.3.1    ,     1.3.1.3.1.1.3.1    ,     1.3.1.1.1.1.1.3.1    ,     1.1.2.1.1    ,     7.1.1.1.7    ,     2.1    ,     5.5.1.2.1.1    ,     3.1.1.1.2.1    ,     2.2.1.3.1.3    ,     1.2.1.1.2.1.1.1    ,     4.5.1.5    ,     1.2.1.1.2    ,     3.3.7    ,     1.1.1.2.1.1.1.1    ,     3.1.3.1    ,     1.1.1.1.1.1.3.1    ,     1.2.4.1.3.1    ,     1.2.1.2.1.1    ,     1.2.1.7    ],    7.3.7    ,     1.1.1.3.1.1    ,     1.3.1.3.1.3.1    ,     1.3.1.1.2.1.3.1    ,     1.3.1.1.1.1.3.1    ,     1.1.1.1.1.1    ,     7.1.1.1.7    ,     1.1.1.1.1.3.5    ,     3.5.1    ,     1.2.1.1.6    ,     1.2.5.2.1.3    ,     3.1.1.1.1.2    ,     1.1.1.2    ,     1.1.1.2.1.7    ,     3.2.1.1.1    ,     1.1.1.2.1.1.3.1    ,     1.5.1.1.3.1    ,     2.1.2.1.3.1    ,     1.7.1.1    ,     2.1.1.3.7    ','7.3.1.7    ,     1.1.2.1.1.1    ,     1.3.1.2.2.1.3.1    ,     1.3.1.5.1.3.1    ,     1.3.1.1.1.3.1    ,     1.1.1.1.1    ,     7.1.1.1.7    ,     1.1.1    ,     5.3.1.2.1.1    ,     4.4.1.2.1    ,     5.2.1.1.3    ,     1.2.1.1.2.1.1.1    ,     3.5.1.5    ,     1.2.1.1.2    ,     3.3.7    ,     1.1.1.2.1.1.1.1    ,     3.1.3.1    ,     1.1.5.1.3.1    ,     1.2.3.1.1.3.1    ,     1.2.3.1.1.1    ,     1.2.7    ],    7.3.7    ,     1.1.1.3.1.1    ,     1.3.1.3.1.3.1    ,     1.3.1.1.2.1.3.1    ,     1.3.1.1.1.1.3.1    ,     1.1.1.1.1.1    ,     7.1.1.1.7    ,     1.1.1.1.1.3.5    ,     2.5.2    ,     1.1.2.1.2.1.1    ,     4.4.1.4    ,     4.1.1.6.4    ,     1.1.1.3    ,     1.1.1.1.2.7    ,     3.2.1.1.1    ,     1.1.1.2.1.1.3.1    ,     1.7.1.3.1    ,     2.1.3.1.3.1    ,     1.7.1.1    ,     2.1.2.7    ']
    puzzle_name = 0
    for puzzle in puzzles:
        in_post = 0
        puzzle_name+=1
        pos = puzzle.split('],')
        cols = pos[0].split(',')
        rows = pos[1].split(',')
        while (in_post < 21):
            tmp_rows = rows[:]
            tmp_rows.insert(in_post,'1')
            result_img ='puzzle'+str(puzzle_name)+'-'+str(in_post)+'.png'
            selenium_solver(cols,tmp_rows,result_img)
            in_post += 1
    
    Sau khi xem lại đống hình hỗn loạn này, chọn ra các kết quả khả thi nhất =D> [​IMG]
    [​IMG]
    [​IMG]

    Kết hợp với file “dirty.png” trước đó và vẽ lại cho đẹp , Kết quả là
    [​IMG]

    Submit flag thôi :x: WhiteHat{SHA1(N0NOGRAM)}
    dirty.jpg

    puzzle1-7.jpg

    puzzle2-7.jpg

    puzzle3.jpg

    tmp.jpg
     
  8. tmnt53

    tmnt53 Guest

  9. SoWhat

    SoWhat Moderator Thành viên BQT

    Tham gia: 07/02/17, 10:02 AM
    Bài viết: 14
    Đã được thích: 7
    Mình bổ sung WriteUp cho những bài Bánh bột chiên, Bánh khọt Bà Rịa – Vũng Tàu, Bánh phu thê Đình Bảng, Bánh Tẻ, Bún bò Huế, Cốm làng vòng, Chả cá lã vọng, Cháo lươn Nghệ An, Cơm tấm Sài Gòn, Gỏi cuốn, Lẩu mắm U Minh, Phở Hà Nội, Phở khô Gia Lai, Xôi ngũ sắc Tây Bắc. Các bạn có thể tham khảo tại đây nhé:
    https://github.com/hoalx/WHGP-2016/tree/master/Write-Up
     
    Last edited by a moderator: 01/03/17, 08:03 AM
  10. tapchiattt

    tapchiattt WhiteH--

    Tham gia: 01/03/17, 10:03 AM
    Bài viết: 13
    Đã được thích: 0
    Cảm ơn mod đã tổng hợp.
     

Chia sẻ trang này