天天看點

DDCTF 2018線上賽writeup - 蟬時雨

DDCTF 2018線上賽writeup

2018-04-24 14:35 

蟬時雨 

閱讀(2763) 

評論(6) 

編輯 

收藏 

舉報

DDCTF2018 題目writeup,原創,misc類的題目解析流程,本人是第一次參加今年的ddctf,很不幸隻拿下了3道題。這裡一下wp,供以後自己或者其他人檢視,本文所有内容均為原創内容,觀點純屬個人觀點,如果讓閱讀者引起不适請見諒。那麼,以下是本人在解題中的流程思路:

 第一題:

DDCTF 2018線上賽writeup - 蟬時雨

d4e8e1f4a0f7e1f3a0e6e1f3f4a1a0d4e8e5a0e6ece1e7a0e9f3baa0c4c4c3d4c6fbb9b2b2e1e2b9b9b7b4e1b4b7e3e4b3b2b2e3e6b4b3e2b5b0b6b1b0e6e1e5e1b5fd

解題思路:

首先嘗試各種解密,無果。

開始研究,分析字元串,首先看看有哪些字元,然後準備分析頻率

import string

cipertext = "d4e8e1f4a0f7e1f3a0e6e1f3f4a1a0d4e8e5a0e6ece1e7a0e9f3baa0c4c4c3d4c6fbb9b2b2e1e2b9b9b7b4e1b4b7e3e4b3b2b2e3e6b4b3e2b5b0b6b1b0e6e1e5e1b5fd"
for i in string.lowercase:
    if i in cipertext:
        print i
for i in string.digits:
    if i in cipertext:
        print i      

列印出來發現字元串由a-f 0-9組成,瞬間想到16進制格式,開始向16進制進攻

len()檢視到字元長度為134,16進制一般是兩個字元組成一個位元組,是以兩個兩個拆解分開試試

cipertext = "d4e8e1f4a0f7e1f3a0e6e1f3f4a1a0d4e8e5a0e6ece1e7a0e9f3baa0c4c4c3d4c6fbb9b2b2e1e2b9b9b7b4e1b4b7e3e4b3b2b2e3e6b4b3e2b5b0b6b1b0e6e1e5e1b5fd"
i = 0
plaintext = ""
while i < 133:
    plaintext += str(int(cipertext[i:i + 2], 16)) + " "
    i += 2
print plaintext      

得到212 232 225 244 160 247 225 243 160 230 225 243 244 161 160 212 232 229 160 230 236 225 231 160 233 243 186 160 196 196 195 212 198 251 185 178 178 225 226 185 185 183 180 225 180 183 227 228 179 178 178 227 230 180 179 226 181 176 182 177 176 230 225 229 225 181 253 

明顯看到超出正常ascii範圍,考慮嘗試凱撒解密,由于ascii有128字元,嘗試先減去128

cipertext = "d4e8e1f4a0f7e1f3a0e6e1f3f4a1a0d4e8e5a0e6ece1e7a0e9f3baa0c4c4c3d4c6fbb9b2b2e1e2b9b9b7b4e1b4b7e3e4b3b2b2e3e6b4b3e2b5b0b6b1b0e6e1e5e1b5fd"
i = 0
plaintext = ""
while i < 133:
    asciinum = int(cipertext[i:i + 2], 16)-128
    plaintext += chr(asciinum)
    i += 2
print plaintext      

得到flag

第二題:

DDCTF 2018線上賽writeup - 蟬時雨

打開下載下傳的windows.jpg

DDCTF 2018線上賽writeup - 蟬時雨

非常普通的一張圖,看到圖檔,第一聯想到隐寫術,自行用binwalk看看圖檔有沒有藏東西

DDCTF 2018線上賽writeup - 蟬時雨

一大堆東西,嘗試提取分離,得到一個zip,打開一看需要密碼

DDCTF 2018線上賽writeup - 蟬時雨

 這裡可以用暴力破解,不過花費時間較長,期間可以做一些其他事情,比如去看看圖檔的詳細資訊(可能藏東西)

DDCTF 2018線上賽writeup - 蟬時雨

在備注找到Pactera,嘗試作為密碼輸入,解壓成功Orz...............

打開file.txt

DDCTF 2018線上賽writeup - 蟬時雨

進行一頓栅欄,編碼等解密,無果。

破了很久,最後回頭看題目看了的提示

DDCTF 2018線上賽writeup - 蟬時雨

嘗試分析字元頻率,然後進行排序

file1 = open("file.txt", "r")
cipertext = file1.read()
dic1 = {}
for i in cipertext:
    if i not in dic1:
        dic1[i] = 1
    else:
        dic1[i] += 1
z = zip(dic1.values(), dic1.keys())
plaintext = ""
for i in sorted(z):
    plaintext = i[1] + plaintext
print plaintext      

直接得到flag

第三題:

DDCTF 2018線上賽writeup - 蟬時雨

本題差評!!!幹擾項太多,不親切,這裡不再贅述踩的坑

下載下傳得到附件,是一個pcap檔案,果斷丢入wireshark,把解析的到的檔案一次導出

隻有IMF的能導出,分析檢視,大概在一個檔案比較大的地方,看到

DDCTF 2018線上賽writeup - 蟬時雨

複制出來,看到是base64,解碼,得到一串字元

DDCTF 2018線上賽writeup - 蟬時雨

這個看到應該是一張圖檔,是以這裡儲存成圖檔看一看。。

#!/usr/bin/env python
# coding=utf-8
import base64

file1 = open("test", "r")
cipertext = file1.read()
file1.close()

plaintext = base64.b64decode(cipertext)  # 讀取file1進行base64解碼
file2 = open("testpng.png", "wb")  # 以.png寫入儲存
file2.write(plaintext)
file2.close()      

打開我們剛才儲存的圖檔

DDCTF 2018線上賽writeup - 蟬時雨

這裡就要使用圖像識别了,ocr了解一下

#!/usr/bin/env python
# coding=utf-8

import base64
import pytesseract
from PIL import Image


def getcode(imgurl):
    """識别圖檔"""
    image = Image.open(imgurl)
    vcode = pytesseract.image_to_string(image)
    code = base64.b64decode(vcode.encode("utf-8"))
    return code


temp_imgurl = \'testpng.png\'
code = getcode(temp_imgurl)
print code      

這裡無敵坑,ocr識别準确率不是很高,code得到後還要和圖檔進行比對檢查。

根據提示,補全RSA

-----BEGIN RSA PRIVATE KEY-----

MIICXAIBAAKBgQDCm6vZmclJrVH1AAyGuCuSSZ8O+mIQiOUQCvN0HYbj8153JfSQ

LsJIhbRYS7+zZ1oXvPemWQDv/u/tzegt58q4ciNmcVnq1uKiygc6QOtvT7oiSTyO

vMX/q5iE2iClYUIHZEKX3BjjNDxrYvLQzPyGD1EY2DZIO6T45FNKYC2VDwIDAQAB

AoGAbtWUKUkx37lLfRq7B5sqjZVKdpBZe4tL0jg6cX5Djd3Uhk1inR9UXVNw4/y4

QGfzYqOn8+Cq7QSoBysHOeXSiPztW2cL09ktPgSlfTQyN6ELNGuiUOYnaTWYZpp/

QbRcZ/eHBulVQLlk5M6RVs9BLI9X08RAl7EcwumiRfWas6kCQQDvqC0dxl2wIjwN

czILcoWLig2c2u71Nev9DrWjWHU8eHDuzCJWvOUAHIrkexddWEK2VHd+F13GBCOQ

ZCM4prBjAkEAz+ENahsEjBE4+7H1HdIaw0+goe/45d6A2ewO/lYH6dDZTAzTW9z9

kzV8uz+Mmo5163/JtvwYQcKF39DJGGtqZQJBAKa18XR16fQ9TFL64EQwTQ+tYBzN

+04eTWQCmH3haeQ/0Cd9XyHBUveJ42Be8/jeDcIx7dGLxZKajHbEAfBFnAsCQGq1

AnbJ4Z6opJCGu+UP2c8SC8m0bhZJDelPRC8IKE28eB6SotgP61ZqaVmQ+HLJ1/wH

/5pfc3AmEyRdfyx6zwUCQCAH4SLJv/kprRz1a1gx8FR5tj4NeHEFFNEgq1gmiwmH

2STT5qZWzQFz8NRe+/otNOHBR2Xk4e8IS+ehIJ3TvyE=

-----END RSA PRIVATE KEY-----

看到這個rsa秘鑰,自然聯想到ssl,搜尋一下(ssl了解一下)

DDCTF 2018線上賽writeup - 蟬時雨

看到了ssl的通信

把秘鑰導入

DDCTF 2018線上賽writeup - 蟬時雨

重新開機wireshark,驚奇地發現在最後多了http

DDCTF 2018線上賽writeup - 蟬時雨

追蹤http流

DDCTF 2018線上賽writeup - 蟬時雨

第四題

DDCTF 2018線上賽writeup - 蟬時雨
#!/usr/bin/env python
import sys
import json
from Crypto.Cipher import AES
from Crypto import Random


def get_padding(rawstr):
    remainder = len(rawstr) % 16
    if remainder != 0:
        return \'\x00\' * (16 - remainder)
    return \'\'


def aes_encrypt(key, plaintext):
    plaintext += get_padding(plaintext)
    aes = AES.new(key, AES.MODE_ECB)
    cipher_text = aes.encrypt(plaintext).encode(\'hex\')
    return cipher_text


def generate_hello(key, name, flag):
    message = "Connection for mission: {}, your mission\'s flag is: {}".format(name, flag)
    return aes_encrypt(key, message)


def get_input():
    return raw_input()


def print_output(message):
    print(message)
    sys.stdout.flush()


def handle():
    print_output("Please enter mission key:")
    mission_key = get_input().rstrip()

    print_output("Please enter your Agent ID to secure communications:")
    agentid = get_input().rstrip()
    rnd = Random.new()
    session_key = rnd.read(16)

    flag = \'<secret>\'
    print_output(generate_hello(session_key, agentid, flag))
    while True:
        print_output("Please send some messages to be encrypted, \'quit\' to exit:")
        msg = get_input().rstrip()
        if msg == \'quit\':
            print_output("Bye!")
            break
        enc = aes_encrypt(session_key, msg)
        print_output(enc)


if __name__ == "__main__":
    handle()      

這題算是純crypto,采用的是MODE_ECB的AES加密。

題目大概的意思就是明文由agentid和flag組成,随意輸入 agentid後明文會被随機産生的key進行AES加密,由于每一次遠端到116.85.48.103時key都是随機産生的,是以我們隻能通過後面的加密嘗試來猜測出明文

首先AES了解一下

ECB加密是分組進行加密的,解密也是分組解密。分組與分組之間的明文産生的密文互相獨立,且由于算法的緣故,相同的明文分組在相同的密鑰加密下會産生相同的密文

加解密流程如下圖所示

而我們要做的事是通過這些個分組且明文加密固定密文的特性猜出flag的每一位來

題中以16位元組為一組,我們舉例也拿16位元組為一組舉例

首先我們假設

xxxx

是我們可控的輸入,一般情況下的加密會是這樣的

但是如果我們控制

xxx

為十五個固定的字元如十五個

A

則加密過程會變成這樣:

現在我們記錄下此時的

HEX_1,在與密文進行比較,如果一樣就記下此時F的值,如此一個一個循環推測

以下是解題代碼

#!/usr/bin/env python
# coding=utf-8
import time
import socket
import string

agentid = ""
message = ""
flag = ""

for i in range(45):
    agentid += "1"


def returnmsg(data):
    """發送與接收"""
    s.send(data)
    time.sleep(0.3)
    msg = s.recv(1024)
    return msg


while True:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("116.85.48.103", 5002))

    print returnmsg("2acba569d223cf7d6e48dee88378288a\n")  # 發送題目的mission key
    cipertext = returnmsg(agentid + "\n")  # 得到密文
    print cipertext

    for i in string.lowercase + string.digits + string.uppercase + "{}":
        message = "Connection for mission: {}, your mission\'s flag is: {}".format(agentid, flag + i)
        info = returnmsg(message + "\n")
        if info.split("\n")[0] in cipertext: # 如果嘗試加密的内容和第一次密文相同,則記下i
            print info
            flag += i
            print "find key code: " + i
            break

    print message
    s.shutdown(2)
    s.close()
    if agentid == "": # 每一次猜到keycode後,agentid都要減一位
        break
    else:
        agentid = agentid[:-1]
    if i == "}":
        break      
  • 分類 CTF writeup
  • 标簽 DDCTF2018

    , CTF比賽

    , DDCTFwriteup

DDCTF 2018線上賽writeup - 蟬時雨