我们是由Eur3kA和flappypig组成的联合战队r3kapig。本周末,我们参与了趋势科技举办的TrendMicro CTF 2018 Qualifier 并以第十名的成绩成功晋级12月在日本东京举办的TrendMicro CTF 2018 Final。我们决定把我们做出来的题目的writeup发出来分享给大家。
另外我们战队目前正在招募队员,欢迎想与我们一起玩的同学加入我们,尤其是Misc/Crypto的大佬,有意向的同学请联系lgcpku@gmail.com。给大佬们递茶。
由于是国际比赛,所以我们的首发wp为英文版,中文版正在路上~

Analysis-Offense

200

I just modified my callgrind solver to solve this challenge.

$ cat oracle.py
#!/usr/bin/python -u
#-*- coding:utf-8 -*-

# Let's exploit easy and quick!
# 1) apt install valgrind
# 2) use callgrind to find instruction count

flag = 'TMCTF{'
n = 0

import os
import sys

# format given by admin
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}"
while True:
    n += 1
    total_call_count = {}
    for i in charset:
        cmd = "valgrind --tool=callgrind --dump-instr=yes --callgrind-out-file=temp/call_count ./oracle '" + flag + i + "A'  2>&1"
        # print(cmd)
        res =  os.popen(cmd).read()

        call_count = res.split("Collected : ")[1].split()[0]
        call_count = int(call_count)
        # total_call_count { 'call_count': [occured_count, occured_by], ... }
        if not total_call_count.get(call_count):
                total_call_count[call_count] = [1, [i]]
        else:
                total_call_count[call_count][0] += 1
                total_call_count[call_count][1].append(i)
        print(n, i, call_count)
    ## get lowest/highest idx,
    idx_call_count = total_call_count.keys()
    print(idx_call_count)
    idx_call_count.sort()
    highest_count_idx = idx_call_count[-1]
    lowest_count_idx = idx_call_count[0]
    # get highest idx
    flag_char = total_call_count[highest_count_idx][1][0]
    flag += flag_char
    print(n, total_call_count, highest_count_idx, flag)

300

We get 3 rsa public keys here, and there are no other attack method, just GCD them and found the GCD number to factor 3 n.

c1=18700320110367574655449823553009212724937318442101140581378358928204994827498139841897479168675123789374462637095265564472109735802305521045676412446455683615469865332270051569768255072111079626023422

e1=65537
n1=23795719145225386804055015945976331504878851440464956768596487167710701468817080174616923533397144140667518414516928416724767417895751634838329442802874972281385084714429143592029962130216053890866347



c2=27979368157170890767030069060194038526134599497456846620984054211906413024410400026053694007247773572972357106574636186987337336771777265971389911503143036021889778839064900818858188026318442675667707

e2=65537
n2=46914096084767238967814493997294740286838053572386502727910903794939283633197997427383196569296188299557978279732421725469482678512672280108542428152186999218210536447287087212703368704976239539968977



c3=24084879450015204136831744759734371350696278325227327049743434712309456808867398488915798176282769616955247276506807739249439515225213919008982824219656080794207250454008942016125074768497986930713993

e3=65537
n3=24543003393712692769038137223030855401835344295968717177380639898023646407807465197761211529143336105057325706788229129519925129413109571220297378014990693203802558792781281981621549760273376606206491


def int2text(message):
    result=""
    while message>0:
        result = chr(int(message)%int(256))+ result
        message=int(message)/int(256)
    return result

import primefac

p1=primefac.gcd(n1,n2)
q1=n1/p1
d=primefac.modinv(e1,(p1-1)*(q1-1))%((p1-1)*(q1-1))
m1=pow(c1,d,n1)
print int2text(m1)

p2=p1
q2=n2/p2
d=primefac.modinv(e2,(p2-1)*(q2-1))%((p2-1)*(q2-1))
m2=pow(c2,d,n2)
print int2text(m2)


p3=primefac.gcd(n2,n3)
q3=n3/p3
d=primefac.modinv(e3,(p3-1)*(q3-1))%((p3-1)*(q3-1))
m3=pow(c3,d,n3)
print int2text(m3)

400

This challenge is a white-box protocol analysis aimed to break the authentication system.

Following is the work flow of this authenticatoin system:

  1. the user send a login request with username to the server
  2. the server send Nonce and ChallengeCookie = Base64Encode(RandomIV | AES128-CBC(RandomIV,Nonce | U | Timestamp, KS)) back to the user
  3. the user send the challenge response(R = SHA256(Nonce | P), where P is the password for authentication) to the server
  4. the server verify whether the password and username is right or not. if right the server will issue a ticket to user, Ticket = Base64Encode(RandomIV | AES128-CBC(RandomIV,Identity | TicketTimestamp, KS)) where Identity = JSON string: { user: U, groups: [ G1, G2, ... ] }
    where G1, G2, ... are the names of the groups that U belongs to

  5. the user can use the ticket to run some command, if the username in the ticket is admin, we can run the command "getflag"

to break this authentication protocol, we can send a login request with username 'AAAAAAAA' + '{"user": "admin", "groups": ["admin"]}\x00' to the server.

the server will response with Base64Encode(RandomIV | AES128-CBC(RandomIV, Nonce | 'AAAAAAAA{"user": "admin", "groups": ["admin"]}\x00 | Timestamp, KS)).

since the AES128-CBC is a block cipher with CBC mode, we can use the AES128-CBC(RandomIV, Nonce | 'AAAAAAAA) as the newIV, and the remain part will be AES128-CBC(newIV,{"user": "admin", "groups": ["admin"]}\x00 | Timestamp), which is a valid admin ticket.

then we can use the ticket to run getflag command and get the flag.

from pwn import *
import base64
from Crypto.Cipher import AES


io=remote("localhost",9999)

def toNullTerminatedUtf8(s):
    return unicode(s).encode("utf-8") + "\x00"
payload="\x01"+"A"*8+'{"user": "admin", "groups": ["admin"]}\x00'
io.send(payload)
data=io.recv(1000)
nounce=data[1:9]
cookie_b64=data[9:]
cookie = base64.b64decode(cookie_b64)
iv=cookie[:16]


fake_ticket=cookie[16:]
fake_ticket_b64=base64.b64encode(fake_ticket)

cmd="\x06"+fake_ticket_b64+"\x00"+"getflag\x00"
io.send(cmd)
io.interactive()

Reverse-Binary

100

We first find base64-encoded data from the pcap file.

Then, reverse the pyinstaller binary and modify the script to solve the challenge.

import struct, os, time, threading, urllib, requests, ctypes, base64
from Cryptodome.Cipher import AES, ARC4
from Cryptodome.Hash import SHA

infile = 'flag'
encfile = 'orig.CRYPTED'
keyfile = 'keyfile'
sz = 1024
bs = 16

def decrypt_request():
    pcap_req = "35998fdb7fe3b7940b9375a68a654ff949c58dcb9b1aebb048d6aa74d905b7b0c6e04b404eb61129f92ad912703850201582ce39e77bfe739fec528741b202f8923a9f8d6303617d8e6e35a0d644115e238522c6d0cacd1afdae23050452c998e39a"
    _hash_chksum = pcap_req[:40]
    _hash_content = pcap_req[40:]
    dec = ARC4.new(_hash_chksum.decode('hex'))
    return dec.decrypt(_hash_content.decode('hex'))
    # 'id=d1&key=2f87011fadc6c2f7376117867621b606&iv=95bc0ed56ab0e730b64cce91c9fe9390'

def generate_keyfile():
    # n = hex(ord(id) + bs)
    n = hex(ord('d1'.decode('hex')) + 16)
    iv = "95bc0ed56ab0e730b64cce91c9fe9390".decode('hex')
    key = "2f87011fadc6c2f7376117867621b606".decode('hex')

    key = ''.join((chr(ord(x) ^ int(n, 16)) for x in key))
    iv = ''.join((chr(ord(y) ^ int(n, 16)) for y in iv))
    keyfile = open("keyfile", "wb")
    keyfile.write(key + iv)
    keyfile.close()
    print(n, iv, key)
    return True

def decrypt():
    global keyfile
    key = ''
    iv = ''
    if not os.path.exists(encfile):
        exit(0)
    while True:
        time.sleep(10)
        if os.path.exists(keyfile):
            keyin = open(keyfile, 'rb')
            key = keyin.read(bs)
            iv = keyin.read(bs)
            if len(key) != 0 and len(iv) != 0:
                aes = AES.new(key, AES.MODE_CBC, iv)
                fin = open(encfile, 'r')
                fsz = struct.unpack('<H', fin.read(struct.calcsize('<H')))[0]
                fout = open(infile, 'w')
                fin.seek(2, 0)
                while True:
                    data = fin.read(sz)
                    n = len(data)
                    if n == 0:
                        break
                    decrypted = aes.decrypt(data)
                    n = len(decrypted)
                    if fsz > n:
                        fout.write(decrypted)
                    else:
                        fout.write(decrypted[:fsz])
                    fsz -= n

                fin.close()
                os.remove(encfile)
                break

print(decrypt_request())
generate_keyfile()
decrypt()

# ----Trend Microt CTF 2018. Flag for this challenge is: TMCTF{MJB1200}

200

A 32-bit shellcode injector using IAT hook. DragQueryFileW in notepad.exe is hooked. The shellcode is written into .text section of shell32.dll .

from ida_bytes import get_bytes, patch_bytes
buf = bytearray(get_bytes(0x4031A0, 376))
for i in xrange(len(buf)):
    buf[i] ^= [0xDE, 0xAD, 0xF0, 0x0D][i % 4]
patch_bytes(0x4031A0, str(buf))

Run 32-bit notepad.exe and drop a file named "zdi_ftw", the rot13-enctypted flag is shown.

TMCTF{want_sum_iat_hooking}

300

The PE file is packed but it's easy to unpack. It detects debugger by IsDebuggerPresent, and Virtual Machine by checking the presense of specific .sys file. Checks whether the hour field of current time is 5.

TMCTF{F14g1s::____1G}

400

A river crossing puzzle with a servant(7), a dog(4), a father(6), a mother(5), two sons(2,3) and two daughters(0,1).

sidev = 1
def side():
    global sidev
    t = sidev
    sidev = 0 if sidev else 1
    return t

def a(x, y = None):
    if(y == None):
        return "\xD0" + chr(side()) + chr(1 << x)
    else:
        return "\xD1" + chr(side()) + chr(1 << x) + chr(1 << y)

s = a(7, 4) + a(7)
s += a(7, 0) + a(7, 4)
s += a(5, 1) + a(5)
s += a(6, 5) + a(6)
s += a(7, 4) + a(5)
s += a(6, 5) + a(6)
s += a(6, 2) + a(7, 4)
s += a(7, 3) + a(7)
s += a(7, 4)
print(s.encode("hex").lower())

Reverse-Other

100

Run the binary directly, it ouput "flag is here", but run the binary under debugger, it output "nice try, punk".

so it seems like there are anti-dbg techniques deployed on this binary.

No worry, there are various ways to patch the binary and bypass the anti-debugging. once we find the function that output "flag is here", we found the flag. since the flag is reside in that function.

200

Simply unpack upx, some weird strings appear in main function.
I noticed this program will self-open and read all data in memory by using API monitor.
After some reversing , I found that it will compare the section name in memory.
Simply modify the code , let program compare the encrypted flag string with section name, you got flag in debugger instantly.

400

This Challenge is a python bytecode reversing challenge.

import sys


def verify_flag(flag): pass
verify_flag.__code__ = verify_flag.__code__.__class__( 1 , 20 , 9 , 67 , 'y\x0c\x00|\x00\x00d\x01\x00\x17\x01Wn%\x00\x01\x01\x01x9\x00|\x00\x00D]\x10\x00}\x01\x00|\x01\x00|\x01\x007}\x01\x00q\x19\x00W~\x01\x00n\x1b\x00Xx\x17\x00t\x00\x00rJ\x00|\x00\x00|\x00\x007}\x00\x00q7\x00W~\x00\x00y\x08\x00t\x01\x00\x01Wn\x07\x00\x01\x01\x01n\x01\x00Xt\x02\x00|\x00\x00\x83\x01\x00d\x01\x00k\x02\x00sx\x00t\x03\x00r|\x00t\x03\x00S|\x00\x00j\x04\x00d\x02\x00\x83\x01\x00s\x8f\x00t\x03\x00S|\x00\x00j\x05\x00d\x03\x00\x83\x01\x00s\xb4\x00t\x03\x00S|\x00\x00j\x06\x00d\x02\x00\x83\x01\x00}\x00\x00na\x00t\x02\x00|\x00\x00\x83\x01\x00}\x02\x00|\x00\x00j\x07\x00d\x02\x00d\x04\x00\x83\x02\x00d\x05\x00\x19j\x08\x00d\x03\x00d\x04\x00\x83\x02\x00d\x01\x00\x19}\x00\x00y \x00t\x02\x00|\x00\x00\x83\x01\x00d\x06\x00\x17|\x02\x00k\x02\x00s\x05\x01t\t\x00\x82\x01\x00Wn\x08\x00\x01\x01\x01t\x03\x00SXd&\x00\x01|\x00\x00d\x08\x00j\x06\x00d\t\x00d\n\x00\x83\x02\x00k\x02\x00r1\x01t\x03\x00St\n\x00t\x0b\x00|\x00\x00\x83\x02\x00}\x00\x00t\x02\x00|\x00\x00\x83\x01\x00}\x02\x00|\x02\x00d\x0b\x00k\x03\x00r\\\x01t\x03\x00St\x0c\x00|\x00\x00\x83\x01\x00}\x03\x00|\x03\x00|\x02\x00\x16d\x0c\x00k\x03\x00r|\x01t\x03\x00S|\x03\x00|\x02\x00\x15}\x04\x00t\r\x00|\x04\x00\x83\x01\x00d\r\x00k\x03\x00r\x9c\x01t\x03\x00Sg\x00\x00|\x00\x00D]\x10\x00}\x05\x00|\x05\x00|\x04\x00A^\x02\x00q\xa3\x01}\x00\x00t\x0e\x00t\x0f\x00|\x00\x00\x83\x01\x00\x83\x01\x00}\x06\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x07\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x08\x00d\x01\x00g\x01\x00d\x07\x00\x14}\t\x00d\x01\x00g\x01\x00d\x07\x00\x14}\n\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x0b\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x0c\x00d\x01\x00g\x01\x00d\x07\x00\x14}\r\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x0e\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x0f\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x10\x00xS\x02t\x10\x00t\x02\x00|\x07\x00\x83\x01\x00\x83\x01\x00D]?\x02}\x11\x00x\xc6\x01t\x10\x00t\x02\x00|\x08\x00\x83\x01\x00d\x04\x00\x18\x83\x01\x00D]\xae\x01}\x12\x00|\x07\x00|\x11\x00c\x02\x00\x19|\x00\x00|\x11\x00|\x12\x00\x17\x19N\x03<|\x08\x00|\x11\x00\x19|\x00\x00|\x11\x00|\x12\x00\x17\x19\x17d\x0e\x00k\x04\x00r\xbb\x02t\x03\x00S|\x08\x00|\x11\x00c\x02\x00\x19|\x00\x00|\x11\x00|\x12\x00\x17\x197\x03<|\t\x00|\x11\x00c\x02\x00\x19|\x00\x00|\x11\x00|\x12\x00\x14\x19N\x03<|\n\x00|\x11\x00\x19|\x00\x00|\x11\x00|\x12\x00\x14\x19\x17d\x0e\x00k\x04\x00r\x0b\x03t\x03\x00S|\n\x00|\x11\x00c\x02\x00\x19|\x00\x00|\x11\x00|\x12\x00\x14\x197\x03<|\x0b\x00|\x11\x00c\x02\x00\x19|\x00\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x19N\x03<|\x0c\x00|\x11\x00\x19|\x00\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x19\x17d\x0e\x00k\x04\x00rc\x03t\x03\x00S|\x0c\x00|\x11\x00c\x02\x00\x19|\x00\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x197\x03<|\r\x00|\x11\x00c\x02\x00\x19|\x06\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x19N\x03<|\x0e\x00|\x11\x00\x19|\x06\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x19\x17d\x0e\x00k\x04\x00r\xbf\x03t\x03\x00S|\x0e\x00|\x11\x00c\x02\x00\x19|\x06\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x197\x03<|\x0f\x00|\x11\x00c\x02\x00\x19|\x06\x00|\x11\x00|\x12\x00\x17\x19N\x03<|\x10\x00|\x11\x00\x19|\x06\x00|\x11\x00|\x12\x00\x17\x19\x17d\x0e\x00k\x04\x00r\x13\x04t\x03\x00S|\x10\x00|\x11\x00c\x02\x00\x19|\x06\x00|\x11\x00|\x12\x00\x17\x197\x03<q}\x02W|\x07\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\t\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\x0b\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\r\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\x0f\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\x0c\x00|\x11\x00c\x02\x00\x19d\x0f\x007\x03<|\x10\x00|\x11\x00c\x02\x00\x19d\x04\x007\x03<q`\x02WxJ\x00|\x07\x00|\t\x00|\x0b\x00|\r\x00|\x0f\x00|\n\x00|\x0c\x00|\x0e\x00|\x10\x00g\t\x00D]\'\x00}\x13\x00x\x1e\x00|\x13\x00D]\x16\x00}\x05\x00|\x05\x00d\x0e\x00k\x04\x00r\xd2\x04t\x03\x00Sq\xd2\x04Wq\xc5\x04Wd\x11\x00j\x11\x00t\n\x00t\r\x00|\x07\x00\x83\x02\x00\x83\x01\x00d\x12\x00k\x03\x00r\x12\x05t\x03\x00Sy&\x00d\x11\x00j\x11\x00t\n\x00t\r\x00|\x08\x00\x83\x02\x00\x83\x01\x00d\x13\x00k\x03\x00r7\x05t\x03\x00SWn\x12\x00\x04t\x12\x00k\n\x00rL\x05\x01\x01\x01t\x03\x00SXd\x11\x00j\x11\x00t\n\x00t\r\x00|\t\x00\x83\x02\x00\x83\x01\x00d\x14\x00k\x03\x00ro\x05t\x03\x00St\x13\x00|\n\x00\x83\x01\x00d\'\x00k\x03\x00r\x85\x05t\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x0b\x00\x83\x02\x00\x83\x01\x00d\x1a\x00k\x03\x00r\xac\x05d\x1b\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x0c\x00\x83\x02\x00\x83\x01\x00d\x1c\x00k\x03\x00r\xd3\x05d\x1d\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\r\x00\x83\x02\x00\x83\x01\x00d\x1e\x00k\x03\x00r\xfa\x05d\x1f\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x0e\x00\x83\x02\x00\x83\x01\x00d \x00k\x03\x00r!\x06d!\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x0f\x00\x83\x02\x00\x83\x01\x00d"\x00k\x03\x00rH\x06d#\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x10\x00\x83\x02\x00\x83\x01\x00d$\x00k\x03\x00ro\x06d%\x00GHt\x03\x00St\x00\x00S' , (None, 0, 'TMCTF{', '}', 1, -1, 7, 5, 'ReadEaring', 'adEa', 'dHer', 24, 9, 'h', 255, 8, 32, '', 'R) +6', 'l1:C(', ' RP%A', 236, 108, 102, 169, 93, ' L30Z', 'X2', ' j36~', 's2', ' M2S+', 'X3', '4e\x9c{E', 'S3', '6!2$D', 'X4', ']PaSs', 'S4', 10, (236, 108, 102, 169, 93)) , ('True', '\xe0\xa1\xb5\xe0\xa1\xb5HA', 'len', 'False', 'startswith', 'endswith', 'replace', 'split', 'rsplit', 'AssertionError', 'map', 'ord', 'sum', 'chr', 'list', 'reversed', 'xrange', 'join', 'ValueError', 'tuple') , ('inval', 'c', 'l', 's', 'sdl', 'x', 'ROFL', 'KYRYK', 'QQRTQ', 'KYRYJ', 'QQRTW', 'KYRYH', 'QQRTE', 'KYRYG', 'QQRTR', 'KYRYF', 'QQRTY', 'i', 'j', 'ary') , 'flag.py' , 'verify_flag' , 1337 , '\x00\x01\x03\x01\x0c\x01\x03\x01\r\x01\x0e\x02\x07\x02\t\x01\x0e\x02\x03\x02\x03\x01\x08\x01\x03\x01\x04\x02\x12\x01\x06\x01\x04\x01\x0f\x01\x04\x02\x0f\x01\x04\x01\x12\x03\x0c\x01&\x01\x03\x01 \x01\x03\x01\x05\x02\x04\x02\x18\x01\x04\x01\x0f\x01\x0c\x01\x0c\x01\x04\x01\x0c\x01\x10\x01\x04\x01\n\x01\x12\x01\x04\x01\x1d\x01\x12\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\x19\x01\x1d\x01\x18\x01\x1c\x01\x04\x01\x18\x01\x18\x01\x1c\x01\x04\x01\x18\x01\x1c\x01 \x01\x04\x01\x1c\x01\x1c\x01 \x01\x04\x01\x1c\x01\x18\x01\x1c\x01\x04\x01\x1c\x01\x10\x01\x10\x01\x10\x01\x10\x01\x10\x01\x10\x01\x14\x01(\x01\r\x01\x0c\x01\x0c\x01\x1e\x01\x04\x01\x03\x01\x1e\x01\x08\x01\r\x01\x05\x07\x1e\x01\x04\x01\x12\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01' )

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print "Usage:"
        print "    %s flag" % sys.argv[0]
    else:
        if verify_flag(sys.argv[1]):
            print "%s is the correct flag!" % sys.argv[1]
        else:
            print "Better luck next time"

Seems like we have to reverse the python bytecode verify_flag.code.

We try to decompile the bytecode by crafting a pyc file and use uncompyle6 to decompile, but it doesn't work since the code contains non-ascii characters.

Finally, We sucessfully decompiled the bytecode by craft a Code2 object and call uncompyle6.main.decompile() directly

import xdis
import sys
from xdis.code import Code2
from xdis.bytecode import get_instructions_bytes
import uncompyle6


argcount = 1
nlocals = 20
stacksize = 9
flags = 67
code = b'y\x0c\x00|\x00\x00d\x01\x00\x17\x01Wn%\x00\x01\x01\x01x9\x00|\x00\x00D]\x10\x00}\x01\x00|\x01\x00|\x01\x007}\x01\x00q\x19\x00W~\x01\x00n\x1b\x00Xx\x17\x00t\x00\x00rJ\x00|\x00\x00|\x00\x007}\x00\x00q7\x00W~\x00\x00y\x08\x00t\x01\x00\x01Wn\x07\x00\x01\x01\x01n\x01\x00Xt\x02\x00|\x00\x00\x83\x01\x00d\x01\x00k\x02\x00sx\x00t\x03\x00r|\x00t\x03\x00S|\x00\x00j\x04\x00d\x02\x00\x83\x01\x00s\x8f\x00t\x03\x00S|\x00\x00j\x05\x00d\x03\x00\x83\x01\x00s\xb4\x00t\x03\x00S|\x00\x00j\x06\x00d\x02\x00\x83\x01\x00}\x00\x00na\x00t\x02\x00|\x00\x00\x83\x01\x00}\x02\x00|\x00\x00j\x07\x00d\x02\x00d\x04\x00\x83\x02\x00d\x05\x00\x19j\x08\x00d\x03\x00d\x04\x00\x83\x02\x00d\x01\x00\x19}\x00\x00y \x00t\x02\x00|\x00\x00\x83\x01\x00d\x06\x00\x17|\x02\x00k\x02\x00s\x05\x01t\t\x00\x82\x01\x00Wn\x08\x00\x01\x01\x01t\x03\x00SXd&\x00\x01|\x00\x00d\x08\x00j\x06\x00d\t\x00d\n\x00\x83\x02\x00k\x02\x00r1\x01t\x03\x00St\n\x00t\x0b\x00|\x00\x00\x83\x02\x00}\x00\x00t\x02\x00|\x00\x00\x83\x01\x00}\x02\x00|\x02\x00d\x0b\x00k\x03\x00r\\\x01t\x03\x00St\x0c\x00|\x00\x00\x83\x01\x00}\x03\x00|\x03\x00|\x02\x00\x16d\x0c\x00k\x03\x00r|\x01t\x03\x00S|\x03\x00|\x02\x00\x15}\x04\x00t\r\x00|\x04\x00\x83\x01\x00d\r\x00k\x03\x00r\x9c\x01t\x03\x00Sg\x00\x00|\x00\x00D]\x10\x00}\x05\x00|\x05\x00|\x04\x00A^\x02\x00q\xa3\x01}\x00\x00t\x0e\x00t\x0f\x00|\x00\x00\x83\x01\x00\x83\x01\x00}\x06\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x07\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x08\x00d\x01\x00g\x01\x00d\x07\x00\x14}\t\x00d\x01\x00g\x01\x00d\x07\x00\x14}\n\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x0b\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x0c\x00d\x01\x00g\x01\x00d\x07\x00\x14}\r\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x0e\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x0f\x00d\x01\x00g\x01\x00d\x07\x00\x14}\x10\x00xS\x02t\x10\x00t\x02\x00|\x07\x00\x83\x01\x00\x83\x01\x00D]?\x02}\x11\x00x\xc6\x01t\x10\x00t\x02\x00|\x08\x00\x83\x01\x00d\x04\x00\x18\x83\x01\x00D]\xae\x01}\x12\x00|\x07\x00|\x11\x00c\x02\x00\x19|\x00\x00|\x11\x00|\x12\x00\x17\x19N\x03<|\x08\x00|\x11\x00\x19|\x00\x00|\x11\x00|\x12\x00\x17\x19\x17d\x0e\x00k\x04\x00r\xbb\x02t\x03\x00S|\x08\x00|\x11\x00c\x02\x00\x19|\x00\x00|\x11\x00|\x12\x00\x17\x197\x03<|\t\x00|\x11\x00c\x02\x00\x19|\x00\x00|\x11\x00|\x12\x00\x14\x19N\x03<|\n\x00|\x11\x00\x19|\x00\x00|\x11\x00|\x12\x00\x14\x19\x17d\x0e\x00k\x04\x00r\x0b\x03t\x03\x00S|\n\x00|\x11\x00c\x02\x00\x19|\x00\x00|\x11\x00|\x12\x00\x14\x197\x03<|\x0b\x00|\x11\x00c\x02\x00\x19|\x00\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x19N\x03<|\x0c\x00|\x11\x00\x19|\x00\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x19\x17d\x0e\x00k\x04\x00rc\x03t\x03\x00S|\x0c\x00|\x11\x00c\x02\x00\x19|\x00\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x197\x03<|\r\x00|\x11\x00c\x02\x00\x19|\x06\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x19N\x03<|\x0e\x00|\x11\x00\x19|\x06\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x19\x17d\x0e\x00k\x04\x00r\xbf\x03t\x03\x00S|\x0e\x00|\x11\x00c\x02\x00\x19|\x06\x00d\x0f\x00|\x11\x00|\x12\x00\x14\x17\x197\x03<|\x0f\x00|\x11\x00c\x02\x00\x19|\x06\x00|\x11\x00|\x12\x00\x17\x19N\x03<|\x10\x00|\x11\x00\x19|\x06\x00|\x11\x00|\x12\x00\x17\x19\x17d\x0e\x00k\x04\x00r\x13\x04t\x03\x00S|\x10\x00|\x11\x00c\x02\x00\x19|\x06\x00|\x11\x00|\x12\x00\x17\x197\x03<q}\x02W|\x07\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\t\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\x0b\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\r\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\x0f\x00|\x11\x00c\x02\x00\x19d\x10\x007\x03<|\x0c\x00|\x11\x00c\x02\x00\x19d\x0f\x007\x03<|\x10\x00|\x11\x00c\x02\x00\x19d\x04\x007\x03<q`\x02WxJ\x00|\x07\x00|\t\x00|\x0b\x00|\r\x00|\x0f\x00|\n\x00|\x0c\x00|\x0e\x00|\x10\x00g\t\x00D]\'\x00}\x13\x00x\x1e\x00|\x13\x00D]\x16\x00}\x05\x00|\x05\x00d\x0e\x00k\x04\x00r\xd2\x04t\x03\x00Sq\xd2\x04Wq\xc5\x04Wd\x11\x00j\x11\x00t\n\x00t\r\x00|\x07\x00\x83\x02\x00\x83\x01\x00d\x12\x00k\x03\x00r\x12\x05t\x03\x00Sy&\x00d\x11\x00j\x11\x00t\n\x00t\r\x00|\x08\x00\x83\x02\x00\x83\x01\x00d\x13\x00k\x03\x00r7\x05t\x03\x00SWn\x12\x00\x04t\x12\x00k\n\x00rL\x05\x01\x01\x01t\x03\x00SXd\x11\x00j\x11\x00t\n\x00t\r\x00|\t\x00\x83\x02\x00\x83\x01\x00d\x14\x00k\x03\x00ro\x05t\x03\x00St\x13\x00|\n\x00\x83\x01\x00d\'\x00k\x03\x00r\x85\x05t\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x0b\x00\x83\x02\x00\x83\x01\x00d\x1a\x00k\x03\x00r\xac\x05d\x1b\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x0c\x00\x83\x02\x00\x83\x01\x00d\x1c\x00k\x03\x00r\xd3\x05d\x1d\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\r\x00\x83\x02\x00\x83\x01\x00d\x1e\x00k\x03\x00r\xfa\x05d\x1f\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x0e\x00\x83\x02\x00\x83\x01\x00d \x00k\x03\x00r!\x06d!\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x0f\x00\x83\x02\x00\x83\x01\x00d"\x00k\x03\x00rH\x06d#\x00GHt\x03\x00Sd\x11\x00j\x11\x00t\n\x00t\r\x00|\x10\x00\x83\x02\x00\x83\x01\x00d$\x00k\x03\x00ro\x06d%\x00GHt\x03\x00St\x00\x00S'
consts = (None, 0, 'TMCTF{', '}', 1, -1, 7, 5, 'ReadEaring', 'adEa', 'dHer', 24, 9, 'h', 255, 8, 32, '', 'R) +6', 'l1:C(', ' RP%A', 236, 108, 102, 169, 93, ' L30Z', 'X2', ' j36~', 's2', ' M2S+', 'X3', '4e\x9c{E', 'S3', '6!2$D', 'X4', ']PaSs', 'S4', 10, (236, 108, 102, 169, 93))
names = ('True', '\xe0\xa1\xb5\xe0\xa1\xb5HA', 'len', 'False', 'startswith', 'endswith', 'replace', 'split', 'rsplit', 'AssertionError', 'map', 'ord', 'sum', 'chr', 'list', 'reversed', 'xrange', 'join', 'ValueError', 'tuple')
varnames = ('inval', 'c', 'l', 's', 'sdl', 'x', 'ROFL', 'KYRYK', 'QQRTQ', 'KYRYJ', 'QQRTW', 'KYRYH', 'QQRTE', 'KYRYG', 'QQRTR', 'KYRYF', 'QQRTY', 'i', 'j', 'ary')
filename = 'flag.py'
name = 'verify_flag'
firstlineno = 1337
lnotab = '\x00\x01\x03\x01\x0c\x01\x03\x01\r\x01\x0e\x02\x07\x02\t\x01\x0e\x02\x03\x02\x03\x01\x08\x01\x03\x01\x04\x02\x12\x01\x06\x01\x04\x01\x0f\x01\x04\x02\x0f\x01\x04\x01\x12\x03\x0c\x01&\x01\x03\x01 \x01\x03\x01\x05\x02\x04\x02\x18\x01\x04\x01\x0f\x01\x0c\x01\x0c\x01\x04\x01\x0c\x01\x10\x01\x04\x01\n\x01\x12\x01\x04\x01\x1d\x01\x12\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\r\x01\x19\x01\x1d\x01\x18\x01\x1c\x01\x04\x01\x18\x01\x18\x01\x1c\x01\x04\x01\x18\x01\x1c\x01 \x01\x04\x01\x1c\x01\x1c\x01 \x01\x04\x01\x1c\x01\x18\x01\x1c\x01\x04\x01\x1c\x01\x10\x01\x10\x01\x10\x01\x10\x01\x10\x01\x10\x01\x14\x01(\x01\r\x01\x0c\x01\x0c\x01\x1e\x01\x04\x01\x03\x01\x1e\x01\x08\x01\r\x01\x05\x07\x1e\x01\x04\x01\x12\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01\x1e\x01\x05\x01\x04\x01'

co = Code2(argcount, 0, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab, (), ())
version = 2.7
timestamp = 1536287532
code_objects = {co: co}
source_size = None
is_pypy = False
magic_int = 62211
uncompyle6.main.decompile(version, co, sys.stdout, None, False, timestamp, False, code_objects=code_objects, source_size=source_size, is_pypy=is_pypy, magic_int=magic_int, mapstream=None, do_fragments=None)

following is the decompiled code

# uncompyle6 version 3.2.3
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.7.0 (default, Jul 15 2018, 10:44:58) 
# [GCC 8.1.1 20180531]
# Embedded file name: flag.py
# Compiled at: 2018-09-07 10:32:12
try:
    inval + 0
except:
    for c in inval:
        c += c
    else:
        del c

else:
    while 1:
        if True:
            inval += inval
    else:
        del inval

try:
    ࡵࡵHA
except:
    pass

if len(inval) == 0 or False:
    return False
if not inval.startswith('TMCTF{'):
    return False
if not inval.endswith('}'):
    return False
    inval = inval.replace('TMCTF{')
else:
    l = len(inval)
    inval = inval.split('TMCTF{', 1)[-1].rsplit('}', 1)[0]
    try:
        assert len(inval) + 7 == l
    except:
        return False

    10
if inval == ('ReadEaring').replace('adEa', 'dHer'):
    return False
inval = map(ord, inval)
l = len(inval)
if l != 24:
    return False
s = sum(inval)
if s % l != 9:
    return False
sdl = s / l
if chr(sdl) != 'h':
    return False
inval = [ x ^ sdl for x in inval ]
ROFL = list(reversed(inval))
KYRYK = [0] * 5
QQRTQ = [0] * 5
KYRYJ = [0] * 5
QQRTW = [0] * 5
KYRYH = [0] * 5
QQRTE = [0] * 5
KYRYG = [0] * 5
QQRTR = [0] * 5
KYRYF = [0] * 5
QQRTY = [0] * 5
for i in xrange(len(KYRYK)):
    for j in xrange(len(QQRTQ) - 1):
        KYRYK[i] ^= inval[i + j]
        if QQRTQ[i] + inval[i + j] > 255:
            return False
        QQRTQ[i] += inval[i + j]
        KYRYJ[i] ^= inval[i * j]
        if QQRTW[i] + inval[i * j] > 255:
            return False
        QQRTW[i] += inval[i * j]
        KYRYH[i] ^= inval[8 + i * j]
        if QQRTE[i] + inval[8 + i * j] > 255:
            return False
        QQRTE[i] += inval[8 + i * j]
        KYRYG[i] ^= ROFL[8 + i * j]
        if QQRTR[i] + ROFL[8 + i * j] > 255:
            return False
        QQRTR[i] += ROFL[8 + i * j]
        KYRYF[i] ^= ROFL[i + j]
        if QQRTY[i] + ROFL[i + j] > 255:
            return False
        QQRTY[i] += ROFL[i + j]

    KYRYK[i] += 32
    KYRYJ[i] += 32
    KYRYH[i] += 32
    KYRYG[i] += 32
    KYRYF[i] += 32
    QQRTE[i] += 8
    QQRTY[i] += 1

for ary in [KYRYK, KYRYJ, KYRYH, KYRYG, KYRYF, QQRTW, QQRTE, QQRTR, QQRTY]:
    for x in ary:
        if x > 255:
            return False

if ('').join(map(chr, KYRYK)) != 'R) +6':
    return False
try:
    if ('').join(map(chr, QQRTQ)) != 'l1:C(':
        return False
except ValueError:
    return False

if ('').join(map(chr, KYRYJ)) != ' RP%A':
    return False
if tuple(QQRTW) != (236, 108, 102, 169, 93):
    return False
if ('').join(map(chr, KYRYH)) != ' L30Z':
    print 'X2'
    return False
if ('').join(map(chr, QQRTE)) != ' j36~':
    print 's2'
    return False
if ('').join(map(chr, KYRYG)) != ' M2S+':
    print 'X3'
    return False
if ('').join(map(chr, QQRTR)) != '4e\x9c{E':
    print 'S3'
    return False
if ('').join(map(chr, KYRYF)) != '6!2$D':
    print 'X4'
    return False
if ('').join(map(chr, QQRTY)) != ']PaSs':
    print 'S4'
    return False
return True

By reversing the decompiled code, we realized that it is very easy to get the flag by z3 solver.

from z3 import *

flag = []
constraints = []
sum_flag=2505
for i in range(24):
   flag.append(BitVec('x%d' % i, 16))
   constraints.append(flag[i]<0x7f)
   constraints.append(flag[i]>0x20)

   sum_flag-=flag[i]
constraints.append(sum_flag==0)

flag_enc = [x ^ 104 for x in flag]
flag_enc_rev = list(reversed(flag_enc))

aa = [0] * 5
bb = [0] * 5
cc = [0] * 5
dd = [0] * 5
ee = [0] * 5
ff = [0] * 5
gg = [0] * 5
hh = [0] * 5
ii = [0] * 5
jj = [0] * 5
for i in range(len(aa)):
   for j in range(len(bb) - 1):
       aa[i] ^= flag_enc[i + j]
       #if bb[i] + flag_enc[i + j] > 255:
       #    return False
       bb[i] += flag_enc[i + j]
       cc[i] ^= flag_enc[i * j]
       #if dd[i] + flag_enc[i * j] > 255:
       #    return False
       dd[i] += flag_enc[i * j]
       ee[i] ^= flag_enc[8 + i * j]
       #if ff[i] + flag_enc[8 + i * j] > 255:
       #    return False
       ff[i] += flag_enc[8 + i * j]
       gg[i] ^= flag_enc_rev[8 + i * j]
       #if hh[i] + flag_enc_rev[8 + i * j] > 255:
       #    return False
       hh[i] += flag_enc_rev[8 + i * j]
       ii[i] ^= flag_enc_rev[i + j]
       #if jj[i] + flag_enc_rev[i + j] > 255:
       #    return False
       jj[i] += flag_enc_rev[i + j]

   aa[i] += 32
   cc[i] += 32
   ee[i] += 32
   gg[i] += 32
   ii[i] += 32
   ff[i] += 8
   jj[i] += 1

#for ary in [aa, cc, ee, gg, ii, dd, ff, hh, jj]:
#    for x in ary:
#        if x > 255:
#            return False

compare = list(map(ord, 'R) +6'))
for i in range(5):
   constraints.append(aa[i] == compare[i])

compare = list(map(ord, 'l1:C('))
for i in range(5):
   constraints.append(bb[i] == compare[i])

compare = list(map(ord, ' RP%A'))
for i in range(5):
   constraints.append(cc[i] == compare[i])

compare = (236, 108, 102, 169, 93)
for i in range(5):
   constraints.append(dd[i] == compare[i])

compare = list(map(ord, ' L30Z'))
for i in range(5):
   constraints.append(ee[i] == compare[i])

compare = list(map(ord, ' j36~'))
for i in range(5):
   constraints.append(ff[i] == compare[i])

compare = list(map(ord, ' M2S+'))
for i in range(5):
   constraints.append(gg[i] == compare[i])

compare = list(map(ord, '4e\x9c{E'))
for i in range(5):
   constraints.append(hh[i] == compare[i])

compare = list(map(ord, '6!2$D'))
for i in range(5):
   constraints.append(ii[i] == compare[i])

compare = list(map(ord, ']PaSs'))
for i in range(5):
   constraints.append(jj[i] == compare[i])

#print(constraints)
print(solve(constraints))

Forensics-crypto1

100

25 x 25 qr-code version 2

type infomation bits: 010101111x101101, ECC level: Q, mask: 7

( ((row + column) mod 2) + ((row * column) mod 3) ) mod 2 == 0

Error corrections available but data is removed (right side)

This is readed as follows
1001110110001001110110001001010001101110010001101110010001101011110101000010111101011000100111010011001100101101010011100011000101110110011010100011010001111101000011101100110110101001110100101101011111110100010101100001100011100101110010101000111111011001110011111111011011001010101110110100101110100101100110111100001001100001100100100001111010000000000

QR CODE has many modes, we try to use byte mode to deocode it.(4 bit mode, 8 bit length, the size of per data block is 8)

By trying to decode the QR CODE manually, we can find that the flag is ended with <font color="red">N1nj4}</font>. So the length of this string is 0b00010100.

The Data and ECC block can be read under the rule as follows. <font color="blue">But we need to read it from offset 4 + 8</font>.

Due to the fact that the ecc level of this QR CODE is %25, we just need to patch some known letters as “TWCTF”,etc.

But we need to know how to patch it.
XORed

we need to patch the header of the QR CODE, mode and lemgth and then we need to XOR them with mask.
After patching known bytes, we can scan the QR CODE.

flag is here
<font color="red">TMCTF{QRc0d3-N1nj4}</font>

200

Decompiling pyinstaller shows the sourcecode.

$ cat OceanOfSockets.py

...
def request():
    try:
        connection = httplib.HTTPConnection(sys.argv[1], sys.argv[2])
        connection.request('GET', '/tmctf.html')
        resTMCF = connection.getresponse()
        readData = resTMCF.read()
        if 'OceanOfSockets' in readData:
            headers = {'User-Agent': 'Mozilla Firefox, Edge/12',
             'Content-type': 'text/html',
             'Cookie': '%|r%uL5bbA0F?5bC0E9b0_4b2?N'}
            connection.request('GET', '/index.html', '', headers)
        else:
            sys.exit(0)
    except:
        pass
...

There doesn't seem to be much information except the suspicious cookie.

While thinking about the flag format (which is TMCTF{}), I realized it should be a simple addition algorithm used on Cookie.

>>> [chr((ord(i) + 47)) for i in '%|r%uL5bbA0F?5bC0E9b0_4b2?N']
['T', '\xab', '\xa1', 'T', '\xa4', '{', 'd', '\x91', '\x91', 'p', '_', 'u', 'n', 'd', '\x91', 'r', '_', 't', 'h', '\x91', '_', '\x8e', 'c', '\x91', 'a', 'n', '}']

Now it sounds like some of characters are not displayed properly. I decided to mod a byte to leak remaining ambiguous bytes.

>>> [chr((ord(i) + 47) % 0x5e) for i in '%|r%uL5bbA0F?5bC0E9b0_4b2?N']
['T', 'M', 'C', 'T', 'F', '\x1d', '\x06', '3', '3', '\x12', '\x01', '\x17', '\x10', '\x06', '3', '\x14', '\x01', '\x16', '\n', '3', '\x01', '0', '\x05', '3', '\x03', '\x10', '\x1f']

Merging above results will print the flag

flag: TMCTF{d33p_und3r_th3_0c3an}

400

We got these informations from challenge:

n = 144 and l = 288
fi (x) = x XOR ki
unknown h

We known a couple of plaintext/cipher, so it's known plaintext attack.

Here the F function of feistel is XOR, all differences are transmitted by probability 1. So we can decrypt all cipher over these conditions.

Fistly, we do some pre-works:

we don't know h, so we need to try alot of time, and finally I found:

true_l=xor(lm,xor(rc,r))

We guess the h=5 or like 5 round's result, so we can solve it:

m1="010000010110111000100000011000010111000001110000011011000110010100100000011000010110111001100100001000000110000101101110001000000110111101110010011000010110111001100111011001010010000001110111011001010110111001110100001000000111010001101111001000000101010001110010011001010110111001100100"

c1="000100100011000101110101001101100110001100110001001110100011110101100000011110010010111000110011001110000000110100100101011111000011000000100001010000100110011100100001011000000111001101110100011011100110000000100000011011010110001001100100001011010110111001100110001010110110110101110001"


c="000000110000111001011100001000000001100100101100000100100111111000001001000001100000001100001001000100100010011101001010011000010111100100100010010101110100010001000010010101010100010101111111010001000110000001101001011111110111100001100101011000010010001001001011011000100111001001101011"


def xor(bin1,bin2):
    assert len(bin1)==len(bin2)
    s=""
    for i in range(len(bin1)):
        s+=str(int(bin1[i])^int(bin2[i]))
    return s
from Crypto.Util.number import long_to_bytes
def show(x):
    print long_to_bytes(int(x,2))

lm=m1[0:144]
rm=m1[144:]
lc=c1[0:144]
rc=c1[144:]

l=c[0:144]
r=c[144:]



true_l=xor(lm,xor(rc,r))
true_r=xor(xor(xor(xor(lc,l),true_l),lm),rm)

show(true_l+true_r)

Forensics-crypto2

200

Dump HTTP upload requests and you will get mausoleum.exe.

From there, decompile the exe file (omg so many pyinstaller binary)

I was somehow unable to decrypt the python file (I changed some of bits in headers, still it didn't work)

so I decided to remove useless letters from the notepad and get the flag. Guess what? I successfully submitted it on the first guess.

TMCTF{the_s3cr3t_i$_unE@rth3d}

Misc

100

Foremost extract a zip file and unzip it to get flag:

200

The challenges provides a pcap file and a python script. The python script reads a txt file into an array and uses it as training data for DBSCAN. So I guess the purpose of this challenge is to extract the data from the pcap.

I use strings to observe that the data of icmp packet looks like the data we want ,so I extract them with the following command
tshark -r ./traffic.pcap -Y "icmp and ip.src_host==192.168.0.17" -T fields -e data

Decode them and apply them to the python script. But the model outputs nothing. So I decide to plot it directly.

And the flag is FLAG:1

点击收藏 | 0 关注 | 1 打赏
  • 动动手指,沙发就是你的了!
登录 后跟帖