Thứ Bảy, 10 tháng 12, 2016

[writeup] SECCON quals 2016

Giải SECCON  đầu tiên. Đội làm được 4 bài thôi mà 3 bài có dấu răng mình :3. Mặc dù chơi pwn mà chả pwn được bài nào :(. Quá kém.

Bài đầu tiên nhiều người giải nhất : Vignere 















Vigenre ? Nhìn qua thấy được là k có 12 kí tự.   Mà nhờ có 8 kí tự SECCON{} nên sẽ tính được 8 kí tự đầu của key là VIGENERE. Còn 4 kí tự sau thì brute force rồi kiểm tra với md5 thôi

Code : http://pastebin.com/UDZwC1Uv
Key : VIGENERECODE
flag : SECCON{ABABABCDEDEFGHIJJKLMNOPQRSTTUVWXYYZ}

Memory Analysis



















file : http://files.quals.seccon.jp/memoryanalysis.zip

Bài này làm khá ngáo =)). Không đổi domain thành IP làm không ra (Tks Khánh =)) )

Kiểm tra file trước 









Thêm cái hint là xem file hosts với thêm 1 cái nữa là file svchost fake







dump 2 file đó ra 





Kiểm tra 2 file thấy được ip bị chuyển tới và url của nó 







Curl và flag đây rồi :





flag : SECCON{_h3110_w3_h4ve_fun_w4rg4m3_}


Anti-Debugging








file : http://files.quals.seccon.jp/bin
Kiểm tra là file bin: PE32 executable (console) Intel 80386, for MS Windows
Bật ida lên xem qua : main http://pastebin.com/w5T5sHnU
Chú ý có đoạn này 
  1. printf("Input password >");
  2.   v3 = (FILE *)sub_40223D();
  3.   fgets(&v23, 64, v3);
  4.   strcpy(v21, "I have a pen.");
  5.   v22 = strncmp(&v23, v21, 0xDu);
  6.   if ( !v22 )
  7.   {
  8.     puts("Your password is correct.");
....

ủa vậy là flag là "I have a pen." à ? Tất nhiên là k phải (đã thử submit =)) ). Cái này chỉ để kiểm tra rồi nó chạy xuống thôi. 

Nhìn hết hàm main mà chả có gì đáng chú ý ngoài mấy cái check debug. Chuyển sang graph xem. 
Chú ý có cái này (Tks Khánh again =)) )










loc_401652:
mov     [ebp+var_78], 0
cmp     [ebp+var_78], 1
jnz     loc_40174D

Dòng trên làm nó luôn nhảy vào loc_40174D (nhánh bên phải). Vậy check xem nhánh bên trái xem sao. 
Đại khái là có một chuỗi khác rồi nó làm này nhọ gì nhức óc lắm vì vậy nên mình patch lại file bin này. Chuyển byte 1 ở trên thành cmp với 0 => vậy nó sẽ nhảy về nhánh bên trái 
Chuyển sang hex view xem (Bôi đen dòng đó rồi chuyển sang hex view sẽ thấy )









Rồi bật hex editor lên chuyển thành 83 7d 88 00 thôi 
file path : https://drive.google.com/file/d/0B-QPcxnExPUcamRLWGx6amRQVHc/view?usp=sharing
Run (Nhớ tắt mấy trình debug)





Flag : SECCON{check_Ascii85}

Thứ Ba, 8 tháng 11, 2016

[SVATTT2016][RE] mrc150


$ ./mrc flag.txt
ffc309e61f2ac3df48d3b9b64fd1720bfb95b460a1235f5d91c4f92ce90dfa516e1b8c49225b808560a9d853980662dc26984e
bin : https://goo.gl/EvnRLw

Bài này cũng khá dễ.

Đọc qua code thì hiểu được thuật toán:
1. Ban đầu đọc 1 file dữ liệu
2. encrypt dữ liệu từ file đó theo thuật toán trong hình :
     Chỉ chú ý ở dòng 21. Giá trị được xor với 1 mảng dword_804a044. Ta export dữ kiệu mảng này ra.















Giờ ta chỉ cần code lại thuật toán sau đó bruteforce các kí tự là xong.

Chú ý là ở dòng 20 : printf("%02x",v4) sẽ tương đương với v4%256
Vì 4 bytes cuối được in ra từ  dòng 23 nên ta biết chắc giá trị đó là "}" (Vì flag có format SVATTT{...})




Code : http://pastebin.com/qRmUu4xg

Code có đoạn bỏ "\" và "`" do có vài Trường hợp trùng với các kí tự đó.


Flag : SVATTT{Whats_differenc3_between_my_mrc_@nd_crc}

Thứ Hai, 7 tháng 11, 2016

[SVATTT2016][ACM] betacaro150

5-in-a-row and get the flag!
nc betacaro.svattt.org 19132


Bài này này gọi là acm chứ mình chả code gì cả =)). Ngồi chơi tay từ đầu đến cuối thôi.
















Ban đầu chưa biêt sẽ đi như thế nào nên sẽ chọn no . Sau đó nó sẽ trả về một dãy hex cho mình. 









Ban đầu mình cũng tính toán xem mấy cái hex này quy luật thế nào với vị trí. Nhưng sau đó thấy nghĩ thuật toán tốn thgian quá nên quyết định chơi tay luôn =)). 
Sau lần đầu chọn no thì nó sẽ cho 1 đoạn hex. Sau đó nc lại với server và đi lại nước đó, nó sẽ đánh nước tiếp theo. Xong mình lại copy nước đó để lại cho lần sau, ...(bật 2 terminal lên chơi song song sẽ nhanh hơn ) Cứ thế xây dựng được 5 vị trí liên tiếp là bắt đầu chơi đc rồi. 
Thường thì mình cứ đánh liên tục 1 hàng như vậy :v. Nếu nó chặn thì cancel và chơi lại. Nhưng mà ít khi nó chặn mình lắm =)), toàn đánh xung quanh nên win khá dễ (Không biết là lỗi hay tính năng :v )









Hôm đi thi mình dùng gg sheets tạo cái bảng này :v (~20p)
Mới chơi lại thì tốn thgian hơn một chút 











và Flag : 













SVATTT{W3lc0m3_t0_MITM!} 

Thứ Hai, 10 tháng 10, 2016

[writeup][PPC] HITCON2016

Vì pwn heap khó nên mình chỉ làm 2 bài PPC

FLAME






Đề cho một file elf sử dụng cấu trúc powerpc. Vì IDA của mình không có pseudo-code C được powerpc. Ban đầu mình nhin asm code rồi xem instruction để tự dịch sang code C nhưng vì khó với nếu dịch thiếu thì sẽ rất mất công nên quyết định kiếm tool. Sau một hồi mò thì kiếm đuọc một web decompile khá tốt https://retdec.com .
http://bugs.vn/5120

Đọc sơ qua code (có vẻ hơi khác với asm nhưng vẫn đúng).
Ban đầu sẽ kiểm tra flag nhập vào có độ dài là 35. Nếu sai thì thoát khỏi chương trình.
Vòng lặp đầu tiên, sẽ lấy từng kí tự trong chuỗi nhập vào xor với một số random (Chuối các số random này là cố định, các số trong chuỗi khác nhau nhưng mọi lần là như nhau ).
Vòng lặp thứ hai là kiểm tra từng số đã xor với một chuỗi các số đã có sẵn trong stack.

Việc đầu tiên là leak hết chuỗi số random.
thêm một dòng printf("%d",v7) và compile code lại. Sau khi chạy thử ta có chuỗi số.

Sau khi xem thì để ý trong IDA có đoạn này. Xem xét các giá trị trong đó thì hơi vô nghĩa

























Vì biết chắc flag có format hitcon{...27char....}
nên sẽ thử kiểm tra
3222^ord('h') = 3326 số này thì vô nghĩa nên thử div cho 256 sau do chuyen ve hex xem sao thì ra được như hình


export data này ra... Sau đó code kiếm flag thôi.
Code :


a=[254, 89, 93, 113, 13, 6, 222, 168, 97, 218, 120, 130, 
169, 95, 94, 176, 191, 198, 56, 93, 9, 237, 7, 192, 153, 
86, 69, 146, 138, 47, 74, 100, 148, 218, 31]
x=[3222,2096,2345,2066,1122,104,2725,4088,1361,2445,
2123,1776,4089,3900,513,3537,3981,3060,3339,2320,3377,
1953,894,415,936,2404,2586,737,3258,2416,121,2384,417,2467,354]
flag=''
for i in range(35):
    k=x[i]/256
    flag+=chr((k*256+a[i])^x[i])
print flag 
http://bugs.vn/5121
FLAG : hitcon{P0W3rPc_a223M8Ly_12_s0_345y}





BEELZEMON

Đề đại khác cho cho 2 số n và k trong khoảng 0 -> 20. Sau đó sinh ra bộ S {a | -2^n <= a <= 2^n-1}
Rồi tự bộ trên sinh ra 2 bộ A và B sao cho số phần tử của 2 bộ là như nhau và bộ thỏa mãn điều kiện sum(a^k | a in A) = sum(b^k | b in B)

nc thử thì thấy trả về các cặp số như 1 1, 4 1, 2 2,4 3... Theo như xem xét thì các cặp số này thỏa mãn sum(S) chia hết cho 2.
Mình thử với các cặp số nhỏ như 1 1, 2 2, 3 1 trước. Và sau đó mình nhận ra một điều là thứ tự lấy các số trong S vào bộ A luôn theo một thứ tự nhất định 0,3,5,6,9,... Thử tìm thử dãy số này trên google thì biết rằng đây là dãy các số Evil number.
Evil number là các số thỏa mãn điều kiện là số các số một trong mã nhị phân của số đó = 2a (ngoại trừ số 0). Vì n<=20 nên mình sẽ sinh ra khoảng 2^20 số.
Đến đây thì xong  rồi. Code :
from pwn import *

indexA=[]
print '[+] Evil Numbers...'

def evil(n):
    if n==1:
        return 0
    if n%2==0:
        return 3*n-3-evil(n/2)
    elif n%2==1:
        return evil((n+1)/2)+n-1
        
for i in xrange(1,2**20-1):
    indexA.append(evil(i))
    
print '[*] Done'

def genSet(n):
    s=[]
    for i in range(-2**n,2**n):
        s.append(i)
    return s

def genSetA(s):
    A=[]
    for i in indexA:
        if i>len(s):
            break
        A.append(s[i])
    return A
    

def solve():
    r =remote('52.198.217.117',6666)

    while(1):
        c=r.recvline()
        c=c[:c.find('\n'):]
        data=c.split(' ')
        if c[:6]=='hitcon':
            print 'FLAG:',c
            break
        n=int(data[0],10)
        k=int(data[1],10)
        pl=''
        for i in genSetA(genSet(n)):
            pl+=str(i)
            pl+=' '
        r.send(pl+'\n')
solve()
FLAG : hitcon{8Ee121m0n kNow3 ev1l Num8e2}

Thứ Hai, 3 tháng 10, 2016

[showup][H4ck1t] Blabla

Giải xài platform của facebook ctf nên rất lag. Pwn cũng chả mấy bài nên toàn làm for, misc này nọ thôi.
1 vài bài mình làm
https://drive.google.com/drive/folders/0B-QPcxnExPUcbDNmUC1OdTJDa0E?usp=sharing
Bài nào có có code thì show code thôi chứ cũng k khó lắm. Mấy bài pcap thì khá dễ nên không bàn...

100 PPC
Bài này thì giải nén mấy file đó ra. Trong đó có khoảng 100 file nén lại với nhau thì phải (?). File cuối cùng là flag.
code :
import os
filename=98
#thay duong dan 
path = "/home/z22/ctf/h4ck1t/100_00edb54bed7e46bd5cdb7c06059881c2.1/work_folder/99.1/work_folder/"
while (1):
 try:
  os.system('dtrx -f --no-directory *')
  path = path + "work_folder/"
  os.chdir(path)
 except:
  os.system("cat flag")
  break
#flag 0W_MY_G0D_Y0U_M4D3_1T


CryptoPixels:
Đọc code, hiểu, sau đó code decrypt.
code :
from PIL import Image
img1=Image.open('encrypted.png')
flag=''
l_flag=img1.getpixel((0,0))[0]
x=img1.getpixel((0,0))[1]
y=img1.getpixel((0,0))[2]
for i in range(l_flag):
  x1=img1.getpixel((x,y))[1]
  y1=img1.getpixel((x,y))[2]
  flag+=chr(img1.getpixel((x,y))[0])
  x=x1
  y=y1
print 'h4ck1t{'+flag+'}'
Planet :
Nhìn kĩ có mấy pixels khác màu. Get từng pixel ra xong ghép lại ra flag
code:
from PIL import Image

data=[]
im=Image.open('planet.png')
im1=Image.open('flag.png')
pix=im.load()
it=0
for i in range(0,1512,24):
 for j in range(0,1512,24):
  data.append(pix[i,j]);
 it=it+1
print it

t=0

for i in range(63):
 for j in range(63):
  im1.putpixel((i,j),data[t])
  t=t+1

im1.save('flag.png')
Test :
đọc đoạn đầu " \'00\'89\'50\'4e\'47\ "
là đoán đây là mã hex file signature của file png (code dễ lắm nên tự code nha ).
Sau khi lấy được hình. dùng binwalk xem thì thấy có file zip.
Trong file zip có chưa flag.txt.
Lấy đoạn đó ra. unzip ra được flag.

Thứ Ba, 20 tháng 9, 2016

[writeup][CSAW16][pwn200] Tutorial


Lần đầu làm giải CSAW này. Chỉ solve được vài bài, pwn thì chỉ làm đc warmup với tutorial. Bài warmup dễ nên nên lười viết. Bài này khó (so với noob như mình) nên viết, để năm sau có khá hơn đọc lại còn có cái mà tự cười vào mặt ...

File :https://drive.google.com/drive/folders/0B-QPcxnExPUcbmZ2cXBKcFVVQjQ?usp=sharing

Kiểm tra file









Hàm main thì chủ yếu là phần kết nối với socket này nọ, không liên quan đến ctrinh chính và được setup ở trên server sẵn nên mình không tập trung vào đây.
Sau khi kết nối xong này nọ, nó sẽ gọi hàm menu

















Hàm này sẽ cho ta truyền vào một số. Nếu số 1 thì gọi func1, số 2 gọi func2, số 3 thì exit. Trong đây không có lỗi gì nên sẽ xem tiếp func1...













Hàm func1 cũng không có lỗi gì. Tuy nhiên, ta có thể chú ý đến hàm dlsym. Sau khi lấy địa chỉ của hàm puts trong, nó sẽ trừ đi 1280 sau đó in ra. Qua cái này ta có thể leak được địa chỉ của puts. sau đó thông qua libc đề cho tính đc base libc.


Xem tiếp hàm func2...











Nhìn qua cũng thấy chỗ này là có lỗi rồi . Stack của hàm có 0x144=324bytes tuy nhiên hàm read lại cho phép đọc 460 bytes. Ngoài ra hàm write còn in ra 324 bytes từ s. Mà từ s đến v3 khoảng cách là 0x140-0x8 = 312. Vậy nó sẽ in ra cả v3, nhưng thiếu 2 bytes cuối. Sau quá trình debug thì ta thấy 2 bytes cuối là 0 nên ta sẽ thêm vào sau. Như vậy là ta sẽ leak đc v3 và bypass stack cookies.

Như vậy có thể hình dung được stack của func2 như sau :

rbp + 0x8:  ret (3)
...
rbp - 0x8: v3 (2)
...
...
rbp - 0x140: s (1)

Vậy cách làm là sẽ overflow buffer(s) sau đó ghi cookie (v3) vào đúng vị trí và ghi đè ret để chạy system("/bin/sh")
(1)  ---> (2) Ta overflow s
Tại (2) ta sẽ đè giá trị ban đầu của v3 mà đã leak đc
(3) ---> ghi đè system và /bin/sh.
Từ cái leak puts của func1. Ta tính toán các offset của system và /bin/sh trong libc đã cho :
base = puts - 0x06fd60 +1280
system=0x046590+base
binsh=0x17c8c3+base
Bên cạnh đúng cũng tìm ropgadget để có thể truyền arg cho system

$ ROPgadget --binary tutorial | grep "pop rdi"
0x00000000004012e3 : pop rdi ; ret

payload sẽ là

pl+='A'*312
pl+=p64(cookie)
pl+='\x90'*8
pl+=p64(pop_rdi)
pl+=p64(binsh)
pl+=p64(system)

Tuy nhiên cái này chạy trên server thì được, nhưng chạy trên client thì k đc. Thế nên mình dùng dup2 (Cái này nhờ anh phieulang mới biết). Ta sẽ dùng 2 hàm dup2(4,0) + dup2(4,1). Và cũng tính toán offset lấy hàm dup2 từ libc.
Tìm thêm 1 ropgadget nữa để truyền arg cho 2 hàm

$ ROPgadget --binary tutorial | grep "pop rsi"
0x00000000004012e1 : pop rsi ; pop r15 ; ret

code exploit : http://bugs.vn/4995

















Lần đầu thì bao giờ cũng sung sướng nhất :)). Cảm ơn anh phieulang và lacloi đã giúp em bài này :D.
GLHF!







Thứ Hai, 5 tháng 9, 2016

[writeup][TWCTF][pwn50] Judgement


Ban đầu sẽ kiểm tra file 


Bật IDA xem qua pseudo code xem sao :
printf(&format); Để ý dòng này thì chắc chắn đây là lỗi format string. 


NX được bật nên k thể chèn shellcode vào được.

Thử debug bằng peda thì thấy địa chỉ của Flag là ở 0x0804a0a0. Nhưng so với đầu stack thì khá xa nên không thể quét. Vậy còn cách Direct parameter access. 
Sau một hồi tính toán, thử nghiệm thì đã tìm đc thứ tự của flag là 45th. Rồi, h thì lấy flag rồi submit thôi.