HGAME2020 Week3 WRITEUP

サイン成功は
、単に何もweek4を行っていません


暗号 - 為替

トピック:

Our admin hijacked a secret channel and it looks like there are two teams doing some unspeakable transactions.
nc 47.98.192.231 25258

まず、問題の暗号サインweek2悪いスタートを取得し、問題解決の最後に直接スクリプトを
改ざんすることができ、「I」、インターセプト通信アリスとボブ、および「I」の部分の後に話題
しかし双方が使用し、非対称暗号化は、作る「私は」直接暗号化を解く鍵を取得することはできません

通常の会話録音メッセージの期間は、次のように改ざんされていません。

root@tesla:~# nc 47.98.192.231 25258
sha256(XXXX+xAkaaFN1enC5UQm1) == a196d23933aaa95a960505f51b0bbb80e4d5e171c650ee77e5f690db0da49f9d
Give me XXXX: hhA9
Bob: Hi Alice, I got the second half of the flag.
Alice: Really? I happen to have the first half of the flag.
Bob: So let's exchange flags, :-)
Alice: Ok, 
Alice: Ah, wait, maybe this channel is not secure, 
Alice: Let's do Key Exchange first.

[INFO] : ********** STEP.1 **********
[INFO] : Alice and Bob publicly agree to use a modulus `p` and base `g`

Alice: p = 153556892283026381077940804008394861131515741989658821679175416849698517587575938981504454432773936568307359774473745489589317350169237690857181940569391633955685290014611082866737102235415668265604660796650340393980508711731525896209747614702453521502602117643570282460093254535065811953844942144919365256521
Alice: g = 12533226630211123267480634698107636517645717206048415151467364959257674379888339001890561804433849050919145849131053263972695583418788336181686631504927023

[INFO] : ********** STEP.2 **********
[INFO] : Alice generates her private key `a` which is a random number from the set {2, 3, ... p-2}.
[INFO] : Bob does exactly the same: he compute his private key `b` which is taken randomly from the same set of integers.
[INFO] : Now, Alice computes her public key `A` which is simply `g` raises to the `a`s power modulo `p`, a.k.a, `A = pow(g, a, p)`.
[INFO] : Bob does the same: Bob computes the `B = pow(g, b, p)`.

[INFO] : ********** STEP.3 **********
[INFO] : Alice and Bob exchange their public key.
[WARNING] : You intercepted Alice's message, which is 
[WARNING] : A = 70647511862974167605718126933019534199899553781360742526572958241129354838758980650269080031171386413383158364613484740512529293994231201867956459561904354997881561301016979250717640861826800500932231197782918763790608092952036935588386452098820212616532542944466948129452067049514243474150423655883359222625
[WARNING] : Do you want to modify this message? (yes/no)
> no

Alice: A = 70647511862974167605718126933019534199899553781360742526572958241129354838758980650269080031171386413383158364613484740512529293994231201867956459561904354997881561301016979250717640861826800500932231197782918763790608092952036935588386452098820212616532542944466948129452067049514243474150423655883359222625

[WARNING] : Again, you intercepted Bob's message, which is
[WARNING] : B = 55085249875112723856925071143685404855037357202693125267627947872717479150226973644582145373865554532006354683411571141265612889988476979355044790254554068600596002693605036052763915418121951582932809011925223738451952524155809034538713880059778382169632171663072947110450799562961709324788795954190769715233
[WARNING] : Do you want to modify this message? (yes/no)
> no

Bob: B = 55085249875112723856925071143685404855037357202693125267627947872717479150226973644582145373865554532006354683411571141265612889988476979355044790254554068600596002693605036052763915418121951582932809011925223738451952524155809034538713880059778382169632171663072947110450799562961709324788795954190769715233

[INFO] : ********** STEP.4 **********
[INFO] : Alice takes public key of Bob (`B`), raises to, again, to the `a`s power modulo `p`, the she gets the secret value `S_a = pow(B, a, p)`.
[INFO] : Bob also gets the secret value `S_b = pow(A, b, p)`.
[INFO] : Right now, they have done the key exchange.
[WARNING] : hint: does Alice and Bob share the same key?

Alice: Now, we have securely shared the secret value.
Bob: Right, let's exchange the encrypted flag!

[INFO] : For the encryption, Alice compute `C_a = (m * S_a) % p`
[INFO] : Bob does the same, `C_b = (m * S_b) % p`

[WARNING] : Bob is trying to send a message to Alice, 
[WARNING] : C_b = 110913341603720164796891815210574224350021153266903320843223068059001121967570733691796324525020947859066394223508548881918150742163684558186913833640618265871415287259294426888410901531102711227891803726165091368041974003571462338237395576033657204061415069107115364368082057002132107630185756527268217377247
[WARNING] : Do you want to modify this message? (yes/no)
> no
Alice: Great, I get the flag.
Alice: C_a = 124986611840107028357373332961427876017685009748795981788067670242988099919086562972017332366455079294211132131812413022628117952556356716858374892804876191509540189241840538243159537688361879032001676734836917946408430037028348731342744428672358594885114018261862941151688600653201876316592113600143479932888

Happy cooperation. :)

まず、Pによる探すために開始し、上記のStackOverflow見つけるために、暗号化アルゴリズムを関連するグラム2名クイズ、およびSSH2は、関連すると思われます。検索後に該当する暗号化アルゴリズムを発見しました。その後、彼は、CTFのWikiは、アイデアを見つけられませんでした、(現在はもうこれを知っている)の上にRSAの内容になっていった
全体week3何も行われず、暗号化でこの質問それらを最も多くを完了し、それを咀嚼に決定されますので、すべての後に

そこには同様の暗号化アルゴリズムではない、との乗算を使用した場合、最後に暗号文を見つけるので(現代の暗号化アルゴリズムの間であまり一般的のようです)ので、おそらく、分析のための暗号化プロセス自体から推測
会話中の両方を分析以下のようにして得られた情報は次のとおりです。

A:p,g
B:p,g
A:p,g,a,A
B:p,g,b,B
A:p,g,a,A,B
B:p,g,b,B,A
A:p,g,a,A,B,S_a
B:p,g,b,B,A,S_b
A:p,g,a,A,B,S_a,C_b
B:p,g,b,B,A,S_b,C_a

プロセスAを通して、bが(タイトルが不明なので、特定の復号化アルゴリズムを与えていない)秘密鍵は、Aは、BがA、Bが復号化に使用されなければならない相手側の公開鍵に渡されています

次のように暗号文を解析しようとすると、非常に厳密な分析プロセスは、(まだ数論を学ぶために開始されていません)です。

Ca=m%p*Sa%p
    =m%p*Sa
    =m%p*B^a%p
    =m*B^a%p
    =m*g^b%p^a%p
    =m*g^b^a%p
    =m*g^a^b%p
    =m*g^a%p^b%p
    =m*A^b%p
    =m%p*A^b%p
    =m%p*Sb

そして、偶然発見されたS_A S_Bが同じであるように思わ
彼らの導出は問題があると思われるが、見てチャットが持っている「ヒント:?んアリスとボブ共有し、同じキー」は、 そう、考慮に公共二つの異なる秘密鍵を取って彼はタイトルが同じSaとSbのでなければならないことを言った
と、後に数日間立ち往生

その後、冷静な分析の波は、暗号化のセキュリティはaとbに反映されている(傍受することができない、である)相互に送信する必要がありますが、他の情報とし、Bを起動する方法はありそうですません。^ Sを復号化するために必要なため、暗号化キーとBの複合効果により、S、及び-1それは未知の状態になっています。値またはSで他の情報と起動Sになるように考えは、暗号文は、問題を解決することができるされている
二つの量Sとするので、複数回のうちの逆数週間クリプト問題と合わせ、Bに関連します、 S、bは互いに打ち消し合うことを公共のように間に構造を考えるのが自然です。様々な試み(彼らは証明できないので)した後、以下の亀裂プロセス:

A = g^a%p(不变)
B = A^-1(篡改)
S_a = B^a%p = g

従ってSはGなり、Mを解決することができます

しかし、具体的な実施プロセスはとても滑らかされませんでした。特定の2つの通信シーケンスので、2つのケースがあった:
1. Bはさらに、M C_Aによって解決、S_A = G改竄することです。Bが改ざんされた場合、アリスは、フラグBで正しいエラーによって解決することができないので、C_Aを提供していない
ため2.切片を公開鍵は第1のA、Bの後に常にA = B ^ -1ように、Aは改ざんすることができない
クラック故障

強くABBAは、この方法を阻止するの疑いのある2間の通信シーケンスが使用されています。クラックが唯一C_B Aキーの内容の改ざんによってで来ることができます。しかし、それはまた、クラックする方向性を提供します

指数計算のための簡単な方法のことを考えた後、1にも優れたツールです。だから、A = 1、その後、S_B = 1、そしてC_Bが割れすることができます。
幸いA 1、次のような結果に。

[WARNING] : Select a decimal number
> 1
Invalid A
Rua!!!

このような簡単な方法は、禁止にも理にかなっていること
、およびその後、A = 2、少し見て何かからの仮数を作ってみます。しかし、メートル後S_B操作は何も見ることができません*

時間の逆数は、建設がgである前にあるので、別の角度からこの準備ので、Pからのアイデアを探し始め。展開+ 1項目でも、因数分解のpの前に項目が含まれており、^ A = 1 1への最後の1の後に簡単なパッチワークpが突然^(P + 1)、二項定理を思い出した後、 (P + 1)^ A =ある KP + 1、 そう((P + 1)^ A )%P = 1。Aをさせることにより= P + 1がS_B 1ように変更してもよいです。
喜んでのpのp + 1、次の結果によれば:

Invalid A
Rua!!!

その後、彼らは2P、(P ^ 2)+1と2P + 1、失敗した変更しようとする
人々がAの法的認証のために問題を把握することはできませんので、彼は数日間立ち往生ように、

その後、彼はまた、以前の設定で、演算処理は、このように、通常のAがpよりも小さくなければならない、剰余Pが関与思っ二項定理Aがこの条件を満たしていないとき。A <Pにするために、A = P-1 S_Bが1になる、または-1(bは偶数であるかに応じて)、およびSを満たす攻撃せように構成されてもよい所定値条件となります。

A = P-1、以下が直接C_B得られるように

[WARNING] : Bob is trying to send a message to Alice, 
[WARNING] : C_b = 4328638271619280595085272697247544492929485359891054205

この長さはC_Bが正常C_Bの長さよりも大幅に少ない取得見出すことができます。いくつかの試行後、C - Bが短い常に4328638271619280595085272697247544492929485359891054205ある(Bは偶数である)、および場合より長い時間C - B(Bは奇数である)、得られたC - bが乗じ-1 gmpy2.invertと逆元P((上)を探している)および係数pは、ちょうど考えを示すこと正確でなければならない、4328638271619280595085272697247544492929485359891054205を得ることができます

pythonで直接実行

print((4328638271619280595085272697247544492929485359891054205).to_bytes(50,'big'))

結果を見ます

b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-1n~ThE+miDd!3_4TtAck~}'

その後、後半のフラグであります

-1n~ThE+miDd!3_4TtAck~}

意味のあるコンテンツであるフラグは、その後暴力フラグの最初の半分を推測することができるので

取得するにはC_Aの旗の最初の半分が処理され、C_Aに対処するためには、最初C_Aを取得する必要があります。テストの後、アリスは、フラグの半分はC_AはC_B Bを解く必要が手でアリスに発行され得るために成功する唯一の後に
メソッドが早く、変更Bは、このようなS_A C_Aを解決知られている場合フラグの半分を解決していない、アリスは右とB C_Bの間違って、それはC_Aを提供することはありません
、あなたが変更した場合、その後、善悪C_B通じBアリスは、フラグの半分を解決し、このことはできません工法の種類の助けを借りずに問題を解決するために、S_A、C_Aに影響を与えることができない
別の行き詰まり。

継続的分析は、変形A / Bのための直接の理由が成功するとBがC_B会合できないことができないことを示しました。このような修飾アリスCはながら、B、及び結合前アイデアは、B = P-1を作るべきである- -対象がちょうどタンパーCを許可Bフラグの半分の両方を解決することができ、その後、彼女はC_Aを提供する、前の実施形態によって解決することができます第1のフラグの半分
既知フラグの後半以来、及び場合アリス復号が逆元P上S_Aを乗算C_Bを使用し、S_A =(B ^)% p =±1、 そう直接偶数である場合4328638271619280595085272697247544492929485359891054205にC_B(半数フラグに対応する)です。会話の各時間の間にパリティ不確実なので、それほど時間はC_Aを取得することさえできているちょうどその時、何度か試みるが、今回C_Aは、デジタルを対応するフラグの前半であります

次のようにテスト結果は以下のとおりです。

[WARNING] : Bob is trying to send a message to Alice, 
[WARNING] : C_b = 40484057514218572415601529748988352447573488701051111978715974421109661614203811628553417900570734689394514518960126352459248262398663489038928626299439015099616683819906237575672079407115365648493033284422191391521849393401890002769018804186035186954501411955032326315075837266787650114023412030957491696992
[WARNING] : Do you want to modify this message? (yes/no)
> yes
[WARNING] : Select a decimal number
> 4328638271619280595085272697247544492929485359891054205
Alice: Great, I get the flag.
Alice: C_a = 9999900281003353773808009517307254317640165173345730638

[INFO] : Alice is offline

Bob: Damn it! She lied on me...

pythonで直接実行

print((9999900281003353773808009517307254317640165173345730638).to_bytes(50,'big'))

結果を見ます

b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00hgame{Wow!+U_d0_tH3_m@N'

そして、前半のフラグがあります

hgame{Wow!+U_d0_tH3_m@N

最終フラグ:hgame {うわ+ U_d0_tH3_m @ N-1N〜+ miDd 3_4TtAck〜!}

追伸:
ちょうどA = B = P-1聞かせているようだ 、C_B = 4328638271619280595085272697247544492929485359891054205 そして、bが両方とも偶数であるとき、ボブを作ることができると私は旗の最初の半分を持って
みてくださいするのが面倒ではなく、
悩んでボブAを秒
先週は、スクリプトを書いてからは、半自動なので、アイデアを検証するたびに困っています。次のようにヘルプ人がtelnetlibとソケットの組み合わせ方法を使用してトピックを知って、スクリプトを記述し、コードは次のとおりです。

import string, sys, re
from socket import socket
from telnetlib import Telnet
from hashlib import sha256
from multiprocessing import Pool, Pipe
from time import sleep

table = (string.ascii_letters + string.digits).encode()
prefix = [string.ascii_lowercase.encode()[0:13],string.ascii_lowercase.encode()[13:26],string.ascii_uppercase.encode()[0:13],   string.ascii_uppercase.encode()[13:26],string.digits.encode()]

def task(pipe,index, c, part):
    print('task',index,"is running")
    for i in prefix[index]:
        for j in table:
            for k in table:
                for l in table:
                    raw = i.to_bytes(1, 'big')
                    raw += j.to_bytes(1, 'big')
                    raw += k.to_bytes(1, 'big')
                    raw += l.to_bytes(1, 'big')
                    raw += part
                    if sha256(raw).hexdigest().encode() == c:
                        pipe.send(raw.decode()[:4].encode())

if __name__ == '__main__':
    sock = socket()
    sock.connect(("47.98.192.231", 25258))
    text = sock.recv(1024).decode()
    sleep(0.02)
    sock.recv(1024)
    print(text)
    part = re.search(r'(?<=\+).{16,}(?=\))', text,).group(0).encode()
    c = re.search(r'(?<=\=\= ).+', text,).group(0).encode()
    (root,sub)=Pipe()
    pool = Pool(processes=5)
    for i in range(5):
        pool.apply_async(func=task, args=(sub, i, c, part))
    print("all process started")
    pool.close()
    pool.join()
    print("all process stopped")
    res = root.recv()
    print(res)
    sock.send(res)
    sleep(0.02)
    tel = Telnet()
    tel.sock = sock
    tel.interact()

暗号 - フィードバック

トピック:

听说上周Classic_CrackMe的CBC很简单? 来耍个CFB试试 XD
nc 47.98.192.231 25147

そして、サーバーサイドスクリプト:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os, random
import string, binascii
import signal
import socketserver
from hashlib import sha256
from Crypto.Cipher import AES

from secret import MESSAGE
assert len(MESSAGE) == 48

class Task(socketserver.BaseRequestHandler):
    def __init__(self, *args, **kargs):
        self.KEY = b""
        self.IV = b""
        super().__init__(*args, **kargs)

    def _recvall(self):
        BUFF_SIZE = 2048
        data = b''
        while True:
            part = self.request.recv(BUFF_SIZE)
            data += part
            if len(part) < BUFF_SIZE:
                break
        return data.strip()

    def send(self, msg, newline=True):
        try:
            if newline: msg += b'\n'
            self.request.sendall(msg)
        except:
            pass

    def recv(self, prompt=b'> '):
        self.send(prompt, newline=False)
        return self._recvall()

    def encrypt(self, data):
        assert len(data) % 16 == 0
        aes = AES.new(self.KEY, AES.MODE_CFB, self.IV, segment_size=128)
        return aes.encrypt(data)

    def decrypt(self, data):
        assert len(data) % 16 == 0
        aes = AES.new(self.KEY, AES.MODE_CFB, self.IV, segment_size=128)
        return aes.decrypt(data)

    def handle(self):
        signal.alarm(60)
        self.KEY = os.urandom(32)
        self.IV = os.urandom(16)

        self.send(b"You have only 3 times to decrypt sth, then I'll give u the FLAG.")
        try:
            for _ in range(3):
                self.send(b"Give me sth(hex) to decrypt")
                hex_input = self.recv()
                if not hex_input:
                    break
                ciphertext = binascii.unhexlify(hex_input)
                plaintext = self.decrypt(ciphertext)
                self.send( binascii.hexlify(plaintext) )
        except:
            self.send(b"Rua!!!")
            self.request.close()

        enc_msg = self.encrypt(MESSAGE)
        self.send(b"Here is your encrypted FLAG(hex): ", newline=False)
        self.send( binascii.hexlify(enc_msg) )
        self.request.close()

class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
    pass

if __name__ == "__main__":
    HOST, PORT = '0.0.0.0', 1234
    server = ForkedServer((HOST, PORT), Task)
    server.allow_reuse_address = True
    server.serve_forever()

指定されたアドレスを接続した後、サーバは、三回の任意のテキストを復号する機会、および表示結果を提供すると、暗号化フラグを復号
サーバによって使用されるたびに暗号化接続パラメータが同じではないので、)(スクリプトos.urandomにの

CFBを明示的に参照するタイトルは、Baiduの後に、これはAES暗号化モード(ピット)であることがわかりました。次のように図です。

チャートのそれぞれの検索、その数字は⊕排他表しOR、IVが使用初期パラメータ(初期化ベクトル)の最初のラウンドで暗号化されている、しかし、中央のブロック暗号の暗号化は、それが何を意味するかわからない
の後を見つけるために静止画でマークされたが、中国では把握できなかったKの暗号化を生成する方法であります

直接BaiduのAES暗号化の後に、これは対称暗号化方式であり、その原理は非常に(私にとっては)複雑な、と以前にいくつかの暗号化モード(CBC、ECB、CTR、CFBおよびOCF)が発見されていることと、だけでなく、AESへの具体的な、しかし、すべてのパケット暗号化(ブロック暗号)を使用することができる
。このようになっているはずの図全体

而之前图片中的block cipher encryption以及“加密器”就是所选用的具体加密算法,在这里是AES
后来查到服务端脚本中的segment_size=128表明每处理128位调用一次加密器,而因为len(MESSAGE) == 48,所以整个加密器只被调用了一次(坑)。结合之前的CFB原理图,我只需要提供一串长度为48的文本C,将其提供给服务器解密得到m,之后计算K=C^m,然后将加密后的flag与K异或即可获得明文。题目给的3次机会明显多余(坑)
然而题目很明显不会这么简单。实际操作结果如下:

C(编码前,自定义)=b'123456789012345678901234567890123456789012345678'
C(编码后)=313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738
m(16进制编码)=f8a940949cbce4fa99c87070055517fd926d8107c69aa64675d188fc9461400352cac50ad9af1660e9def81c1bbccd70
m(解码后)=b'\xf8\xa9@\x94\x9c\xbc\xe4\xfa\x99\xc8pp\x05U\x17\xfd\x92m\x81\x07\xc6\x9a\xa6Fu\xd1\x88\xfc\x94a@\x03R\xca\xc5\n\xd9\xaf\x16`\xe9\xde\xf8\x1c\x1b\xbc\xcdp'
K=b'\xc9\x9bs\xa0\xa9\x8a\xd3\xc2\xa0\xf8AB6a"\xcb\xa5U\xb87\xf7\xa8\x95r@\xe7\xbf\xc4\xadQq1a\xfe\xf0<\xee\x97/P\xd8\xec\xcb(.\x8a\xfaH'
flag(16进制编码,解密前)=8fd732e789e3a0e2c89f202f531a17facd049273a075ec70f393376473f833a7486269c7076d3341cad2c40412009150
flag(解密前)=b'\x8f\xd72\xe7\x89\xe3\xa0\xe2\xc8\x9f /S\x1a\x17\xfa\xcd\x04\x92s\xa0u\xecp\xf3\x937ds\xf83\xa7Hbi\xc7\x07m3A\xca\xd2\xc4\x04\x12\x00\x91P'
flag(解密后)=b'FLAG is hgame{51hQ*DW\xddy\x02\xb3t\x88\xa0\xde\xa9B\x96)\x9c\x99\xfb\xe9\xfa\x1c\x11\x12>\x0f,<\x8ak\x18'

发现flag的后半段是无法打印的字符,并且最后也没有出现}
怀疑要对flag后半段进行异或。因为0x7d( '}' 对应编码) ^ 0x18=0x65=101,所以将刚才的flag整体与101异或,得到以下结果

b'#)$"E\x0c\x16E\r\x02\x04\x08\x00\x1ePT\r4O!2\xb8\x1cg\xd6\x11\xed\xc5\xbb\xcc\'\xf3L\xf9\xfc\x9e\x8c\x9fytw[jIY\xef\x0e}'

叒叒叒陷入了僵局。。。
后来才发现segment_size=128指的是128位(16个字节),而len(MESSAGE) == 48是指48个字节,因此整个加密器被使用了3次。上面的操作只能解出MESSAGE的前16个字节
(回想一下也觉得自己挺傻的,既然考点是CFB,那么一次简单的异或肯定不能解决问题)

之后进一步分析CFB,发现在这种模式下,某个块的加密结果和前一个块的加密结果有关。举个例子,在segment_size=8(1个字节)的情况下,使用相同的key和初始向量IV加密b'12345'和b'02345',即使明文只有第1个字节不同,之后相同的'2345'加密之后的结果也不一样。通过这种方式加密,即使明文中出现了多个完全相同的块,攻击者也无法从密文当中直接看出来
(与其形成鲜明对比的是ECB模式,块与块的加密过程完全独立(类似于week1的仿射密码,在指定A、B的情况下单个明文字符和密文字符的对应关系是唯一的),虽然方便并行计算,但是在攻击者拥有大量明文和对应密文的情况下更容易受攻击)

而从本题的角度来分析,如果我提交的待解密密文是任意的,那么刚才的方法只能确保加密器第一次生成的K(K用于与明文/密文异或,图中有说明)与加密flag的第一个K相同(因为都是用IV和Key生成的),而之后加密器生成的K就与加密flag的K不一样了(因为参数中只有Key相同,而上一个块的密文不同),因此前者的K不能用于解密后者。这也就是刚才的解密过程只能获得MESSAGE前16个字节(128位)的原因

不过目前已知第一个块的明文m1,在获取了第一个块的K1之后可以算出第一个块的密文c1=m1 ^ K1,将第一个块的密文与任意字符串S2+X拼接得到密文C'=c1+S2+X(仍然需要确保len(C')==48,且S2=16),将其提交给服务器解密得到M'=m1+s2+X,此时计算K2=S2 ^ s2即可得到正确的K2,并且用K2可以解出flag的第二部分m2
同理,K3,m3也可以求出来,最后flag=m1+m2+m3

当前思路用符号表述如下(括号内为字符长度):
其中S是提交的密文,s是服务器返回的明文,K用于与明文/密文异或(CFB中的K),C是flag的密文,m是flag的明文,X为任意字符串
整个过程中m全程不变,其余参数在单次连接内不变

第一次连接:
任意构造S=S1(16)+X(32),提交一次得到s=s1(16)+X(16),计算K1(16)=S1 ^ s1
之后服务器提供C=C1(16)+X(32),计算m1(16)=C1 ^ K1

第二次连接:
任意构造S=S1(16)+X(32),提交一次得到s=s1(16)+X(16),计算K1(16)=S1 ^ s1,C1(16)=m1 ^ K1
之后构造S'=C1(16)+S2(16)+X(16),再提交一次得到s'=m1+s2(16)+X,计算K2(16)=S2 ^ s2
之后服务器提供C'=C1(16)+C2(16)+X(16),计算m2(16)=C2 ^ K2

第三次连接:
任意构造S=S1(16)+X(32),提交一次得到s=s1(16)+X(16),计算K1(16)=S1 ^ s1,C1(16)=m1 ^ K1
之后构造S'=C1(16)+S2(16)+X(16),再提交一次得到s'=m1+s2(16)+X,计算K2(16)=S2 ^ s2,C2(16)=m2 ^ K2
之后构造S''=C1(16)+C2(16)+S3(16),再提交一次得到s''=m1+m2+s2(16),计算K3(16)=S3 ^ s3
之后服务器提供C''=C1(16)+C2(16)+C3(16),计算m3(16)=C3 ^ K3

最后得到flag=m1+m2+m3

由于每一次连接服务器时的Key、IV都不同,因此每一次连接服务器时取得的Kx都不一样,所以每次连接的关键在于获得一部分flag(明文块)mx,这样才可以进行下一步

具体实现过程中还有个问题,因为服务端脚本中有signal.alarm(60),所以每次连接之后的所有操作要在60秒内完成,否则连接会自动断开。只能写脚本了
最后编写的半自动脚本如下:

from socket import socket
from telnetlib import Telnet
from time import sleep
from binascii import hexlify,unhexlify
import re

XOR = lambda s1, s2: bytes([x ^ y for x, y in zip(s1, s2)])

base = '123456789012345678901234567890123456789012345678'.encode()
flag = 'FLAG is hgame{51b72d4cd23b2fe672a874cb44020868}.'.encode()

sock = socket()
sock.connect(("47.98.192.231", 25147))
tel = Telnet()
tel.sock = sock
sleep(0.1)

text = tel.read_until(b'>').decode()
print(text, end='\n---------------------\n')

tel.write(hexlify(base))
sleep(0.1)
text = tel.read_until(b'>').decode()
print(text, end='\n---------------------\n')

c = unhexlify(re.search(r'(?<= ).+(?=\n)', text).group(0))
tmp1 = c[:16]
tmp2 = base[:16]
key = XOR(tmp1, tmp2)
print(key)

base = XOR(key, flag[:16]) + base[16:]
tel.write(hexlify(base))
sleep(0.1)
text = tel.read_until(b'>').decode()
print(text, end='\n---------------------\n')

c = unhexlify(re.search(r'(?<= ).+(?=\n)', text).group(0))
tmp1 = c[16:32]
tmp2 = base[16:32]
key = XOR(tmp1, tmp2)
print(key)

base = base[:16]+ XOR(key, flag[16:32]) + base[32:]
tel.write(hexlify(base))
sleep(0.1)
text = tel.read_until(b'>').decode()
print(text, end='\n---------------------\n')

c = unhexlify(re.search(r'(?<= ).+(?=\n)', text).group(0))
tmp1 = c[32:]
tmp2 = base[32:]
key = XOR(tmp1, tmp2)
print(key)

tel.interact()

最终flag:hgame{51b72d4cd23b2fe672a874cb44020868}

后记:
刚看到初始化向量(IV)的时候不知道其用途,以为解密方不需要IV只通过Key就能解密,于是猜测IV可以增强破解难度
后来看资料和服务端代码发现解密时也需要提供IV
经过后续分析,IV只是CFB加密的递归过程中的一个初始条件
***

Misc - 美 人 鲸

题目:

我们受过严格的训练,无论在什么环境里,都不会乱放东西,
除非忍不住。

后面是Docker镜像的地址

https://hub.docker.com/r/zhouweitong/hgame2020-misc

先是在Kali上安装Docker并下载镜像,然后百度到docker有个export命令可以将容器的文件系统提取为一个压缩包,提取并解压后直接搜索hgame无果,搜flag发现/usr/share/nginx/html/index.html里面有以下内容

You want flag? See $FLAG.

之后在Docker镜像中以交互模式运行sh,输入env
查看环境变量,发现以下内容

FLAG=Find flag.tar.gz!

而刚刚的搜索结果当中就有flag.tar.gz!
用压缩包管理器打开,里面含有flag.zip和README文件。flag.zip是被加密的压缩包,而README当中有以下内容

See sh history.

之后在镜像的sh中输入sh history,出现以下错误

sh: can't open 'history': No such file or directory

于是百度如何查看sh的历史记录,得知直接运行history命令即可。运行后发现一条记录

/ # history
   0 echo -e "Zip password is somewhere else in /etc.\nFind it!" 

到头来还是要从文件搜索入手。直接搜password,发现在/etc/issue文件中有以下内容

Welcome to Alpine Linux 3.10
Kernel \r on an \m (\l)

Zip Password: cfuzQ3Gd6gqKG@$N

用该密码解压flag.zip,得到flag.db。Kali系统中可以直接打开这个数据库文件,得到flag
最终flag:hgame{v3RWI3qSpcKZhp^xv$kaBhNjVqxk##3e}

后记:
该题时间分配:5%搜相关命令 5%解题 90%安装Docker(雾
(写了篇安装Docker的博文不到3天访问破千(指隔壁CSDN上的访问量破千,博客园上面还是没人看))
(网上有现成的安装方法,因为想修改一点点所以装了很久)


看完week4的题,感觉自己要凉

2020.02.08

おすすめ

転載: www.cnblogs.com/wh201906/p/12275367.html