HGAME2020 Week3 Writeup

Sign success
just not done nothing week4


Crypto - Exchange

topic:

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

First, get a bad start week2 Crypto sign of problems, problem-solving script directly to the last
topic after the "I" intercepted communication Alice and Bob, and the "I" part of which can be tampered with
, however the two sides use asymmetric encryption, making the "I" can not obtain a key for decryption directly

Period of normal conversation recorded message has not been tampered with as follows:

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. :)

First, start to look for according to p, g two names associated encryption algorithm to find the StackOverflow above a quiz , and SSH2 seems relevant. After the search found no relevant encryption algorithm. . . Later he went CTF Wiki turned RSA content above (currently only know this anymore), did not find the idea
after all because the entire week3 nothing will be done, and completed the largest number in Crypto This question them, decided to chew on it

Because there is no similar encryption algorithm, and finally find ciphertext when using a multiplication (seems to be less common among modern encryption algorithms), and therefore probably guess from the encryption process itself for analysis
analyze both during a conversation the information obtained as follows:

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

Throughout the process a, b is the private key, A, B is passed to the other side's public key, A, B should be used for decryption (the title did not give specific decryption algorithm so unknown)

Try to analyze the ciphertext, a very rigorous analysis process is as follows (not yet started to learn number theory):

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

And accidentally discovered S_a S_b seems to be the same
suspect that their derivation is a problem, but seeing chats have "hint:? Does Alice and Bob share the same key", taking into account the public two different private keys, so He said that the title should be in the same Sa and Sb
and later stuck for a few days

Later, a wave of calm analysis, security of the encryption is reflected in a and b do not need to send to each other (that is, can not be intercepted), but there seems no way to launch a and b with other information. Encryption key S by the combined effect of a and b, and therefore required to decrypt S ^ -1 it has become unknown state. An idea is to become S value or S launched with other information, the ciphertext can be solved the problem
because the two quantities S and a, b related, combined with inverse few weeks Crypto problem among multiple occurrences, it is natural to think of the structure among the public so that S a, b cancel each other out. After various attempts (because they can not prove), the following crack processes:

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

Thus S becomes g, can be solved the m

However, the specific implementation process was not so smooth. Since the two specific communication sequence, there were two cases:
1. B is to make tampering S_a = g, further solved by m C_a. If B is tampered with, Alice can not be solved by correct errors In Flag B, and therefore does not provide C_a
order 2. intercepts the public key is always after the first A B, A can not be tampered with so that A = B ^ -1
cracks failure

Communication sequence between two strongly suspected of ABBA blocking this method is used. But it also provides direction to crack: the crack can only come in by tampering with the contents of C_b A key

After the thought of a simpler method for index calculation, 1 is also a good tool. So that A = 1, then S_b = 1, then C_b can be cracked.
Happily to the A 1, the following results:

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

Such a simple way be ban also makes sense
, and then try to make A = 2, a little seen something from which the mantissa. However, after m * S_b operation can not see anything

Because the inverse of the time before the construction is from the g, so this preparation from another angle, starting to look for ideas from p. After a simple patchwork p suddenly recalled the binomial theorem, (p + 1) ^ after a Expand a + 1 item contains items before a factorization p, and the last one to 1 ^ a = 1, also there is a (p + 1) ^ a = kp + 1, so ((p + 1) ^ a )% p = 1. By letting A = p + 1 may be changed such that S_b 1.
A happily according to the p p + 1, the following results:

Invalid A
Rua!!!

Then they try to change A 2p, (p ^ 2) +1 and 2p + 1, have failed
because people can not figure out the problem for legal authentication of A, so he stuck a few days

Later, he also thought A calculation operation involves modulo p, thus a normal A must be smaller than p, with the previous configuration binomial theorem when A does not satisfy this condition. In order to make A <p, may be configured so that A = p-1 S_b becomes 1 or -1 (depending on whether b is an even number), and let S satisfies attack becomes a predetermined value condition.

So that A = p-1, the following is directly obtained C_b

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

This length can be found C_b obtained significantly less than the length of the normal C_b. And after several attempts, C - b is short is always 4328638271619280595085272697247544492929485359891054205 (b is an even number), and when longer time C - b (b is an odd number), the resulting C - b multiplied by -1 on the inverse element p (with gmpy2.invert ( ) seeking) and modulus p, can be obtained 4328638271619280595085272697247544492929485359891054205, indicating just thinking should be correct

Run directly in python

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

got the answer

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~}'

Then the second half is the flag of

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

Since the flag which is meaningful content, then violence can guess the first half of the flag

To get the first half of the flag of C_a will be processed, and to deal with C_a must first obtain C_a. After testing, Alice only after half of the flag will be successful to get C_a issued to Alice by hand which requires solving C_b B
if the methods earlier, modification B is known and thus solve such S_a C_a , Alice through the right and wrong of B C_b not solved half of the flag, it will not provide a C_a
If you modify a, then B Alice through the right and wrong C_b can not be solved half of the flag, and this kinds of construction methods can not affect S_a, C_a, to solve problems without the help of
another impasse. . . .

Continued analysis showed that the direct reason for modification A / B can not be successful and that B can not C_b association. Subject allowed just tamper C - b, and ideas before binding, should make B = p-1, while such modifications Alice C - b can be solved both by half of the flag, then she will provide C_a, can be solved by the previous embodiment first half of the flag
since the second half of the known flag, and when Alice decryption will use C_b multiplying S_a on inverse element p, and S_a = (B ^ a)% p = ± 1, so when a is an even number directly the C_b to 4328638271619280595085272697247544492929485359891054205 (corresponding to half the number flag) to. Because parity uncertainty during a conversation each time, so try several times, just when a time is even able to get C_a, but this time C_a is the first half of the flag corresponding digital

Test results are as follows:

[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...

Run directly in python

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

got the answer

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'

Then the flag of the first half is

hgame{Wow!+U_d0_tH3_m@N

Final flag: hgame {Wow + U_d0_tH3_m @ N-1n ~ ThE + miDd 3_4TtAck ~!!}

Postscript:
it seems just let A = B = p-1, C_b = 4328638271619280595085272697247544492929485359891054205, then when a, b are both even number can make Bob and I have got the first half of the flag
, but not too lazy to try
distressed Bob a seconds
since last week wrote the script is semi-automatic, so every time to verify ideas are in trouble. Help people know the topic through the use of telnetlib and socket combination method, write a script, the code is as follows:

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()

Crypto - Feedback

topic:

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

Then the server-side script:

#!/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()

After connecting the specified address, the server will provide three chances to decrypt any text, and displays the results and decrypt the encrypted flag
in the script os.urandom (), so each time encryption connection parameters used by the server is not the same of

Title which refers explicitly to CFB, after Baidu, found that this is an AES encryption mode (the pit). Diagram is as follows:

Searching each of the charts, that figure ⊕ represents exclusive OR, IV is encrypted in a first round of initial parameter (initialization vector) used, however, the middle block cipher encryption does not know what it means
to find after the Chinese marked with a picture, but still could not figure out is how to generate the encryption of K

Directly after Baidu AES encryption, that this is a symmetric encryption method, and its principle is very complicated (for me), and previously found several encryption modes (CBC, ECB, CTR, CFB and OCF) and not just specific to AES, but all packet encryption (block encryption) can be used
throughout the diagram should look something like this

而之前图片中的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

Guess you like

Origin www.cnblogs.com/wh201906/p/12275367.html