Write-up

[UIUCTF 2018] xoracle (250)

2018. 4. 18. 19:35

이번 UIUCTF에서 못다푼 xoracle을 이번에 다시 한번 풀어보기로 했다.


이미 서버가 닫혀버렸으므로 가상서버에서 구축하여서 다시 풀어보기로 하였다.

(서버구축에 관한 내용은 이쪽 참고)


참고로 파이썬은 이렇게 추가해줘야한다.


service xoracle
{
          disable         = no
          flags           = REUSE
          socket_type     = stream
          protocol        = tcp
          wait            = no
          user            = sherlock
          server          = /usr/bin/python3
          server_args     = /home/sherlock/workstation/2018_CTF/UIUCTF/xoracle/xoracle.py
}
 
cs

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에 차이가 나는 이유를 알았다.


writeup1에서는 주어진 암호문의 해독한 길이를 1536으로 보았다. (실제로 서버에서 1536의 길이만 받은것같다.)[각주:1]


writeup2에서는 주어진 암호문을 해독하여 나온 길이를 2039로 본다.(나도 복호화한 결과 길이가 2039였다.)


그래서 결과적으로 w1과 w2에서 서로 조금씩 다른 파일들을 해독하였고... w2에 있는 분이 더 정확한 파일을 얻게된것이다.


나는 w1의 것을 w2의 2039를 받는것으로 해서 writeup을 재구성해보겠다.


먼저 이론을 다시 한번 정리하면 아래와 같다.


Solution

  1.  먼저 키를 모르고 암호문인 C만 알고 있을 때, 여기서 키만 남기고 이 키의 길이를 어떻게 정의하느냐를 알아야한다.

nc를 통해서 받게 되는 암호문 C를 base64로 복호화해보면 길이가 2039인것을 알 수 있다. 그리고 중요한 키 K의 길이는 128~255의 범위에 있고 만약 우리가 같은 길이를 가진 키 k1k2가 반복되어 얻어진 OTP인 K1K2로 암호화된 C1, C2를 가지고 있다면 키 길이를 유추할 수 가 있다.(키값은 서로 다르다, 같은것은 길이 뿐)



K1 XOR K2 은 2039길이를 가지고 있고, 이 안에는 128-255 의 길이를 가지는 k1 XOR k2가 반복되어지고 있을 것이다.

그러므로 우리는 다음 파이썬 코드를 가지고 키길이가 각각 128-255인 암호문을 128개 얻을 수 있다.


from base64 import b64decode
from socket import socket
 
ADDR = 'localhost'7777
KEY_LEN = 128
 
def get_msg():
    while True:
        with socket() as s:
            s.connect(ADDR)
            msg = b64decode(s.recv(3000))
        if len(msg) == 2039:
            return msg
 
def xor_bytetrings(a, b):
    return bytes((x^y for x,y in zip(a,b)))
 
def find_msgs():
    msgs ={get_msg()}
    needed = set(range(128))
 
    while needed:
        print(len(msgs), needed)
        new_msg = get_msg()
        for msg in list(msgs):
            xor_key = xor_bytetrings(new_msg, msg)
            good_part, last_part = xor_key[:KEY_LEN], xor_key[KEY_LEN:]
 
            if good_part in last_part:
                i = last_part.index(good_part)
                print('\t', i)
                if i in needed:
                    yield (i+KEY_LEN, new_msg)
                    needed -= {i}
                    msgs -= {msg}
                    continue
        msgs.add(new_msg)
 
if __name__ == "__main__":
### STEP 1. find key_length and Save
    for i, text in find_msgs():
        with open('key_{0:0>3}_c'.format(i), 'wb') as f:
            f.write(text)
 
# yeild : http://kkamikoon.tistory.com/90  , https://dojang.io/mod/page/view.php?id=1119
 
 
cs



  1. 자 이제 우리는 암호문 C와 그 암호화에 쓰인 키 K의 길이를 알고 있다. 키 길이를 len이라고 할 때 암호문 Clen길이씩 짤라서 n개의 블록과 Mlen으로 나눈 n개의 블록 다음과 같이 표시 할 수 있다.


그리고 이 연산 c1 xor c2를 통해 키 K를 암호문에서 제거하여 평문 m블록의 연산으로만 바꿀수 있다. 이것이 키 길이를 알 때, 바로 암호문의 자신들끼리 곱하여 암호문에서 키를 소거하는 방법이다.


  1. 이제 키 길이가 서로 1차이가 나는 암호문 C1 과 C2 를 가져오자. 이 들의 키를 각각 K1,K2  [|K1-K2|=1이다.  여기서 기억할 것은 우리가 XOR할 것은 M의 블록이란 것이다.
키 길이가 3인 C1과 키 길이가 4인 C2가 있다. 
c11 xor c12 = m11 xor m12 
c21 xor c22 = m21 xor m22 인것을 잊지말자.


위와 같이 계산되는 것이다! 키 길이가 1다른 것을 이용하여

M[1]^M[4]인 부분을 키길이가 3인 H1에서 가져오고, M[0]^M[4]인 부분을 키길이가 4인 H2에서 가져와

그 둘의 XOR결과로 M[0]^M[1]을 구할 수 있는 것이다. 

이 계산을 키 길이 128인 C1을 base로 두고 키길이가 각각 1,2,3,4,5씩 차이나는 C들을 가져와 위와 같은 계산을 하면 우리는 결국   M[0] XOR M[i] for all i in [1,128] 을 계산할 수 있다. (M[1]~M[127])


  1. 이제 첫 평문 바이트 M[0]를 BruteForce를 통해 나머지 M[1]~M[127]을 구할 수 있고, 이 값을 이용해 키 길이가 128인 암호문과 XOR을 통해 128길이 키 K를 복구하여 평문메세지를 복호화할 수 있다.

import os
 
KEY_LEN = 128
FILE_LEN = 2039
 
def xor_bytetrings(a, b):
    return bytes((x^y for x,y in zip(a,b)))
 
def key2039_gen(key):
    key = key*(FILE_LEN // KEY_LEN)
    key += key[:FILE_LEN % KEY_LEN]
    return key
    
if __name__ == "__main__":
### STEP 2. Xor M1, M2 AND Genearte M[0]^M[i] (i=range(1,128)
    res = [0]
    with open('key_128_c''rb') as f: 
        original = f.read()
    
    for i in range(1,128):
        idx=i+KEY_LEN
        with open('key_{0:0>3}_c'.format(idx), 'rb') as f: 
            shifted = f.read()
        
        or_blocks = [original[KEY_LEN*x:KEY_LEN*(x+1)] for x in range(0,2)]
        sh_blocks = [shifted[(KEY_LEN+i)*x:(KEY_LEN+i)*(x+1)] for x in range(0,2)]
 
        H1 = xor_bytetrings(*or_blocks)
        H2 = xor_bytetrings(*sh_blocks)
 
        res.append(H1[i] ^ H2[0])
 
### STEP 3. Bruteforce M[0]
    for m0 in range(256):
        msg_first = [m0^x for x in res]
        key = xor_bytetrings(msg_first, original)
        key = key2039_gen(key);
        
        flag = xor_bytetrings(key, original)
        with open('flag_{0:0>3}'.format(m0), 'wb') as f:
            f.write(flag)
 
### STEP 4. file operation AND Find Real FLAG!
    for m0 in range(256):
        os.system('file flag_{0:0>3} | grep -v ": data"'.format(m0))
 
 
 
 
cs

위 코드를 실행하면 아래와 같이 나온다.


flag_number에서 number은 M[0], 즉 첫바이트를 저값으로 하였을 때 나온 키값으로 복호화했을 때

파일 시그니처로 이렇다는 것이다.


만일 flag가 텍스트 파일이라면 아래와 같이 나온다.


sherlock@ubuntu:~/workstation/2018_CTF/UIUCTF/xoracle/my_writeup$ echo "hello world" > test
sherlock@ubuntu:~/workstation/2018_CTF/UIUCTF/xoracle/my_writeup$ file test
test: ASCII text
cs

여기서 file 명령어를 통해 분석해본 결과로서 flag는 텍스트 파일이 아닌것같다.
가장 가능성있어보이는 것으로는 Zip archive data이나, 일단 한번 헥스값으로 비교해보겠다.


다른 파일들은 다 쓰레기값인것 같지만 flag_080은 뭔가 제대로된 파일헤더가 보인다. PK가 보이니 압축파일이겠고 또 f.bmp라는 문구도 보인다.


한번 unzip해보겠다.



CRC값이 다르다고 오류가 뜨긴하지만 성공적으로 f.bmp가 추출된것을 볼 수 있다.




성공~~ 굿... 굉장히 좋은 문제였다고 생각한다. 물론 CTF 당일에 풀었다면 정말 좋았겠지만..ㅠ


flag.zip



  1. writeup1에서 풀이해주신분이 실수하신게 있다. 소스를 확인해보니 서버로 부터 recv(2<<10)를 하는데, 서버가 주는 문자열은 2800자 정도된다. 물론 그 문자열이 base64인코딩되어있어 이를 디코딩하게 되면 2039자가 나온다. 아마 여기서 헷갈리셔서 2<<10=2048자만 받으신거같다. 그래서 서버가 주는 문자열 2800자중에 2048만 받아가게 되어 파일크기가 1536이 된것같다. [본문으로]

'Write-up > Crypto' 카테고리의 다른 글

[0ctf 2017] integrity - 75p  (0) 2018.05.02
[Byte Bandits CTF 2018] R u Ronald Rivest? 70p  (0) 2018.04.27
[TyokoWesterns] My Simple Cipher[75]  (0) 2017.09.02
[anstromCTF 2017] Knock Knock  (0) 2017.04.25
[anstromCTF 2017] Descriptions  (2) 2017.04.25

[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

My Simple Cipher

Problem

This my first cipher system. Can you break it?

my-simple-cipher.7z 


cipher.py

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/python2
import sys
import random
key = sys.argv[1]
flag = '**CENSORED**'
assert len(key) == 13
assert max([ord(char) for char in key]) < 128
assert max([ord(char) for char in flag]) < 128
message = flag + "|" + key
encrypted = chr(random.randint(0128))
for i in range(0len(message)):
  encrypted += chr((ord(message[i]) + ord(key[i % len(key)]) + ord(encrypted[i])) % 128)
print(encrypted.encode('hex'))
cs

encrypted.txt 내용 7c153a474b6a2d3f7d3f7328703e6c2d243a083e2e773c45547748667c1511333f4f745e



message | key

랜덤한 0~128 사이의 아스키문자 하나를 뽑아내고 그것을 이용해 (message | key)의 첫글자를 암호화한다. 이제 암호화한걸 encrypted 문자 뒤에 덧붙이면서 간다. random.randint = encrypted[0]이고, 실제 encrypted.txt에서 가져와서 보면 "|"로 int값은 124이다.

이걸... 와... 너무 설명이 귀찮고 어려워;

대충 말하자면 Message = FLAG | KEY 로 구성되어 암호화에 KEY가 두번 더해지고 있음, 그걸 이용해서 풀면됨

먼저 Message에 항상 "|"가 들어가므로 이걸 이용해서 Key[8]을 구하고 나머지를 순차적으로 구하면됨. 아래는 답을 구하는 소스

코드를 실행하면 플래그가 나온다. key : ENJ0YHOLIDAY! TWCTF{Crypto-is-fun!}|ENJ0YHOLIDAY! 플래그 획득

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
#!/usr/bin/python2
 
import sys
import random
 
key = [0,0,0,0,0,0,0,0,0,0,0,0,0]
encrypted_flag = '7c153a474b6a2d3f7d3f7328703e6c2d243a083e2e773c45547748667c1511333f4f745e'
 
enc = encrypted_flag.decode('hex')
 
key[8]=(ord(enc[22])-ord(enc[21])-ord(enc[0]))%128
 
for j in range(0,13):
  for i in range(013):
    if(key[(i+9)%13]!=0 and key[i]==0):
      key[i]=(ord(enc[i+23])-ord(enc[i+22])-key[(i+9)%13])%128
    
skey=''
for i in range(0,13):
  skey+=chr(key[i])
 
print("key : "+skey)
 
#decipher
 
message = ''
 
for i in range(1len(enc)):
  message += chr((ord(enc[i])-ord(enc[i-1])-ord(skey[(i-1)%13])) % 128)
  #encrypted += chr((ord(message[i]) + ord(key[i % len(key)]) + ord(encrypted[i])) % 128)
 
print(message)
 





'Write-up > Crypto' 카테고리의 다른 글

[Byte Bandits CTF 2018] R u Ronald Rivest? 70p  (0) 2018.04.27
[UIUCTF 2018] xoracle (250)  (0) 2018.04.18
[anstromCTF 2017] Knock Knock  (0) 2017.04.25
[anstromCTF 2017] Descriptions  (2) 2017.04.25
[anstromCTF 2017] Substitution Cipher  (0) 2017.04.25
난해한 프로그래밍 언어2017.08.01 12:19 신고

나무위키에 나온 난해한 프로그래밍 언어... 
https://namu.wiki/w/%EB%82%9C%ED%95%B4%ED%95%9C%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%20%EC%96%B8%EC%96%B4


Bugs_BunnyCTF에서 나온 문제 중 하나

 Crypto-20

Decode the message !


++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>----. >+++++++++++++++++. --------------. ++++++++++++. --------------------. <. >++++++++++++++++++++++. -------. . +++++++++++. ++. <. >---------. <--------------. ---. +++++++++++++++++++++++++++++. +++++++++++++++++. -------------------------. >+++. <<++++++++++++. . >>++++++++.





브레인퍽이란 언어...
https://namu.wiki/w/BrainFuck?from=%EB%B8%8C%EB%A0%88%EC%9D%B8%ED%8D%BD


브레인퍽 인터프리터

https://sange.fi/esoteric/brainfuck/impl/interp/i.html





답 : Bugs_Bunny{Br41N_Fu**}


 

USB ENCRYPTION

FORENSICS, 30

We've made a copy of defund's flash drive, which seems to be protected by a usb encryption software. Retrieve the flag.



Not really a hint, but this is an actual software.



위 문제에서 DEFUND.dmg라는 파일을 제공해준다.


AccessData FTK Imager 을 이용하여 dmg 파일을 열어보았다.

뭔가 많다.


그 USB encryption software라는건 USBSecurity.exe 라는 걸로.. 진짜 있는 프로그램이다...(!???)


뭐;; 알바없고


열어서 [root]/Thumbs.us/com1.{~~~}/~~/~~/flag.txt를 발견



actf{not_quite_usb_encryption}


와~ 끝;;

[anstromCTF 2017] Document

2017. 4. 26. 22:13


DOCUMENT

FORENSICS, 60

Defund wrecked his essay in a text editor to pretend that his file got corrupted.


No hint. 




docx 파일 복구!


자세한건 귀찮으니 생략;


뭐 대충 hxd로 열어서 헤더파일 만들어 넣고


어짜피 여기서 해서 뭐 얼마나 더 괜찮게 되겠으...


zip파일로 열어서 document.xml로 걍 찾아봄 ㅇㅇ.. 결과는 굿.. 있었음


actf{too_bad_for_zip_recovery}

 

IMAGE TRICKERY

FORENSICS, 50

What do Twitch emotes have to do with a CTF? No idea, but there's a flag in here somewhere. *kappa*



The colours in this image are just stunning.



IMAGE TRICKERY
문제

이미지가 하얀색으로만 덮여있는것처럼 보이지만 픽셀값을 살펴보면 아님 ㅇㅇ...
귀찮아서... 툴도 없고 해서 그냥 일단 그림판으로 대충 칠함

그러니까 QR코드가 나옴

https://webqr.com/index.html
여기서 QR코드 올려서 어떤거 나오는지 봄

=> 결과
http://pastebin.com/S9De6WYA
라는 값이 나옴.. QR코드 해석한 결과임

안에 들어가봄

base64값으로 보이는 RAW값이 있음
base64 디코딩해봄

RAW => 디코딩
data:image/svg+xml;base64, (base64값)
뭔가 또 나옴...

또 디코딩해보니까 svg+xml이 나옴 ㅇㅇ

xml로 저장해서 열어서 보면
왠 북극봄이 꼬깔콘같은 그거 뒤집어쓰고 PARTY HARD하면서
actf{fa1L_F15H} 라고 그림판으로 글씨쓴거처럼 되있음

[anstromCTF 2017] Knock Knock

2017. 4. 25. 23:39

KNOCK KNOCK

CRYPTO, 30

You have come across a strange audio recording. Can you recover the flag? Note: The flag is not in the actf{} format.



Google is your friend. 



... 망할 힌트있는줄 몰랐는데 방금 알음;;


Tap code 라 불리는 암호임...


참조 : https://en.wikipedia.org/wiki/Tap_code


GoldWave나 등등의 툴로 열어보든 아니면 직접 들어보든해서 들어보면

한번당 Knock 소리를 기록할수 있음


Roman alphabet tap code
012345
1ABC/KDE
2FGHIJ
3LMNOP
4QRSTU
5VWXYZ
The tap code table


2 3 1 5 3 1 3 5 3 2 1 5 3 5 3 1 1 5 1 1 4 3 1 5 임...


이걸 2개씩 묶음 그리고 옆 표대로 하면 됨


(2, 3) h

(1, 5) e

(3, 1) l

(3, 5) p

(3, 2) m

(1, 5) e

(3, 5) p

(3, 1) l

(1, 5) e

(1, 1) a

(4, 3) s

(1, 5) e



flag : helpmeplease

'Write-up > Crypto' 카테고리의 다른 글

[UIUCTF 2018] xoracle (250)  (0) 2018.04.18
[TyokoWesterns] My Simple Cipher[75]  (0) 2017.09.02
[anstromCTF 2017] Descriptions  (2) 2017.04.25
[anstromCTF 2017] Substitution Cipher  (0) 2017.04.25
[ch4n3] How are you? I'm XOR XOR.. (Crypto)  (0) 2017.03.08

[anstromCTF 2017] Descriptions

2017. 4. 25. 23:28


DESCRIPTIONS

CRYPTO, 50

We have found what appear to be nonsensical phrases. However, we believe that the author likes to hide secret messages using nonsensical phrases about animals. Please help us find what the secret message is.


The writer seems obsessed with categorizing words.




The horse was a small falcon runner.

The horse was a huge goat pitcher.

The pig is a quick falcon singer.

The goat was a quick sheep speaker.

The sheep is the big goat pitcher.

The sheep was a slow sheep hitter.

The horse is a tiny goat dancer.

A cow is the huge bluejay dancer.

The falcon is the fast sheep pitcher.

The pig was a speedy falcon pitcher.

The pig was the speedy goat singer.

The goat was a huge sheep hitter.

The horse was the speedy sheep runner.

The cow was a speedy bluejay singer.

A sheep is a small falcon catcher.

The cow was the fast cow singer.

The goat was a sluggish sheep catcher.

The goat is the slow robin catcher.


단어가 반복되고 같은 종류의 말들이 사용되는 것으로 보아 아마 같은 단어(종류)들은 같은 정보(비트)를 가질것이다.

또 한 문장이 7개의 단어들로 나누어져있음을 알 수 있다.


분류 시작


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

The : 1 

A : 0

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

네발 동물(육지) : 1

horse, pig, goat, sheep, cow

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

두발 동물(공중) : 0

falcon, bluejay, robin

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

is : 1

was : 0

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

크기 : 0

big, huge, small, tiny

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

속도 : 1

speedy, fast. slow, sluggish

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

야구 : 1

runner, catcher, pitcher, hitter

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

노래 : 0

singer, dancer, speaker

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


The horse was a small falcon runner.

 1      1     0   0   0      0       1


....

....

....


1100001 a

1100011 c

1110100 t

1100110 f

1111011 {

1100111 g

1110010 r

0111000 8

1011111 _

1100101 e

1101110 n

1100011 c

1101111 o

1100100 d

0110001 1

1101110 n

1100111 g

1111101 }


actf{gr8_encod1ng}



'Write-up > Crypto' 카테고리의 다른 글

[TyokoWesterns] My Simple Cipher[75]  (0) 2017.09.02
[anstromCTF 2017] Knock Knock  (0) 2017.04.25
[anstromCTF 2017] Substitution Cipher  (0) 2017.04.25
[ch4n3] How are you? I'm XOR XOR.. (Crypto)  (0) 2017.03.08
[ch4n3] King Sejong (Crypto)  (0) 2017.03.08

+ Recent posts