易霖博-2020-YCTF复现

前言

2020年3月27日,参加了易霖博“停课不停学”的CTF比赛,emmm,被师傅们按在地上摩擦了一顿,究其原因,已经很久没有刷题了,于是按照各位师傅们的WP把当时存下来的题复现一遍,以作备忘学习。

CRYPTO

EasyRSA

题目给了一个私钥文件和一个密文

直接用一条命令即可

openssl rsautl -decrypt -in flag.en -inkey rsa_private_key.pem -out flag.txt

拿到flag{We1c0meCtf3r_elab}

CRC32

这个很明显就是一个CRC32碰撞

c1.png

用了一个大佬的脚本跑出来了密码

64p2@sworD20

拿到flag{d12f101d06855e2cd686c1ad6ac4de85}

贴下大佬的脚本

import binascii
import string

dic=string.printable 
crc1=0x308E1D5B
crc2=0x5194C2D0
crc3=0x5C48F6CA
for i in dic:
    for j in dic:
        for n in dic:
            for m in dic:
                s=i+j+n+m
                #s = bytes(s, encoding = 'utf-8')
                if(crc1==(binascii.crc32(s) &     0xffffffff)):
                    text1=s
                if (crc2 == (binascii.crc32(s) &     0xffffffff)):
                    text2=s
                if (crc3 == (binascii.crc32(s) &     0xffffffff)):
                    text3=s
print (text1+text2+text3)

RSAbackdoor

据说是BCNSCTF的原题,没写出来,是我们百度手的锅。
先看看题目给的脚本

from Crypto.Util.number import getPrime, isPrime
flag = 'flag{a-z0-9}'
nbits = 2048
gbits = 1000
g = getPrime(int(gbits))
while True:
    a = getPrime(int(nbits * 0.5) - gbits)
    p = 2 * g * a + 1
    if isPrime(p):
        break

while True:
    b = getPrime(int(nbits * 0.5) - gbits)
    q = 2 * g * b + 1
    if p != q and isPrime(q):
        break
N = p * q
e = 65537


def str2int(s):
    return int(s.encode('hex'), 16)


with open('pubkey.txt', 'w') as f:
    f.write(str(e) + '\n')
    f.write(str(N) + '\n')

plain = str2int(flag)

c = pow(plain, e, N)
with open('cipher.txt', 'w') as f:
    f.write(hex(c))

观察发现P,Q有公因数2*g ,尝试Pollard‘s ρ method;
其实还是用的大佬的脚本分解n得到p,q

def gcd(a, b):
  while b:
    a, b = b, a%b
  return a

def mapx(x):
  x=(pow(x,n-1,n)+3)%n
  return x

n=33774167600199691072470424898842928168570559940362770786060699320989546851695106466924163816843729828399984649770900793014896037884774039660562546937090412844276185560384964983508291174867808082182386566813393157054259464108858158903739578119760394228341564696225513954400995543629624209942565369972555679980359992955514826589781286738100616149226885302403505062415492679633217275379153421830105021673417544608398249866398042786421630495968810854036782025120509999022773806069591080190166920079688217334968528641747739241234353918892029263544388161160427668518991666960251381106788899451912317001247537576428186291689

x1=x2=1

while True:
  x1=mapx(x1)
  x2=mapx(mapx(x2))
  p=gcd(x1-x2,n)
  if (p!=1):
    print(p)
    print(n/p)
    break

得到p,q

p=177993461816075408240866752227210319316825574291000376727523991315086097605063837563342286560819823849610146713383370383386260295565108973920944593141677024612114517119831676665456754235233172344362610684938542774386956894066675103840244633202469661725050948177995671009070311486253646420435061175078660441183

q=189749484366449861630736482622030204229600074936733397229668738586605895979811823994029500725448581332746860468289540041125768726148614579255062994177531727784605194094836998282676712435286273497842956368997116036170165393912022560935791934662695453870846024312915604049805219410140420469163797779129644454583

然后利用脚本求出d

# coding = utf-8

def computeD(fn, e):

    (x, y, r) = extendedGCD(fn, e)

    #y maybe < 0, so convert it

    if y < 0:

        return fn + y

    return y



def extendedGCD(a, b):

    #a*xi + b*yi = ri

    if b == 0:

        return (1, 0, a)

    #a*x1 + b*y1 = a

    x1 = 1

    y1 = 0

    #a*x2 + b*y2 = b

    x2 = 0

    y2 = 1

    while b != 0:

        q = a / b

        #ri = r(i-2) % r(i-1)

        r = a % b

        a = b

        b = r

        #xi = x(i-2) - q*x(i-1)

        x = x1 - q*x2

        x1 = x2

        x2 = x

        #yi = y(i-2) - q*y(i-1)

        y = y1 - q*y2

        y1 = y2

        y2 = y

    return(x1, y1, a)



p = 177993461816075408240866752227210319316825574291000376727523991315086097605063837563342286560819823849610146713383370383386260295565108973920944593141677024612114517119831676665456754235233172344362610684938542774386956894066675103840244633202469661725050948177995671009070311486253646420435061175078660441183

q = 189749484366449861630736482622030204229600074936733397229668738586605895979811823994029500725448581332746860468289540041125768726148614579255062994177531727784605194094836998282676712435286273497842956368997116036170165393912022560935791934662695453870846024312915604049805219410140420469163797779129644454583
e = 65537


n = p * q

fn = (p - 1) * (q - 1)



d = computeD(fn, e)

print d

得到d

d=11264411788839355592444856301614488363956471904061056255881635805090094375457400203763192894221130759558216953395674955120307575813439598378024263407707436165069943146297428393266768825247731038349979486052262807679509336199267919454932934045527300563698215071335234814155316242621058729891886931914187742084664702392602429806835617468209844338711315548455315452692700616464465563108767921693721150452939650725153874644898636543732854250641129411206109642819488878782249575130672657182665780011560050159281212359222980210472602178746411982328739935093883590670811966243661382699777078747677158108250557964576989602089

然后用脚本算出明文

n = 33774167600199691072470424898842928168570559940362770786060699320989546851695106466924163816843729828399984649770900793014896037884774039660562546937090412844276185560384964983508291174867808082182386566813393157054259464108858158903739578119760394228341564696225513954400995543629624209942565369972555679980359992955514826589781286738100616149226885302403505062415492679633217275379153421830105021673417544608398249866398042786421630495968810854036782025120509999022773806069591080190166920079688217334968528641747739241234353918892029263544388161160427668518991666960251381106788899451912317001247537576428186291689
c = eval('0x64c49797b12803ab0556926bf82296850e10949f7ce422d775dc4713ddd6eb7f807cafc80c3fbe3b6da93550beaa302801a162b132b165f1e4e4b5db43f891f33bbca948a5084cadf6ff733470e1f6a7a760c981a89440f56bbcef1b2b2cbd0f4062df04fcd98213d819fce92854a00bb6b2f6ecc327bc4c9d988705dd51c6d55e4f38cdce2aca8112bff6932fd93367d5411afc0d5dcebf93129e60afb717860e9afc0f1c6d98486d3abb34c183473fc015d0bacdfce92d3b55a9bc163b5e8dc3f0983980853d95b332b4954e22cec9ec684d008d2724e2d2a989471932a0b3d2e583a521745b0d4d8ccce13124f26bf96e25f02e713249aabadebf6ead4cf0L')
d = 11264411788839355592444856301614488363956471904061056255881635805090094375457400203763192894221130759558216953395674955120307575813439598378024263407707436165069943146297428393266768825247731038349979486052262807679509336199267919454932934045527300563698215071335234814155316242621058729891886931914187742084664702392602429806835617468209844338711315548455315452692700616464465563108767921693721150452939650725153874644898636543732854250641129411206109642819488878782249575130672657182665780011560050159281212359222980210472602178746411982328739935093883590670811966243661382699777078747677158108250557964576989602089
m = pow(c, d, n)
print hex(m)

得到一串16进制字符串,掐头去尾扔进HXD得到对应文本

c3.png

MISC

Disk

首先用7z提取文件,得到readme,secr3t2.zip等文件

然后secr3t2.zip里有一个加密的压缩包

c4.png

readme里说密码被删了

c5.png

尝试恢复一下

extundelete disk2 --restore-all

嘿嘿,得到一个文件

c6.png

打开是一个密码

don0tgu355p@sswd

打开level1.zip得到一个图片

c7.png

修改高度得到flag

c8.png

c9.png

Keyboard

这道题,复现时出了点问题,死活读不出真实内容
按照大佬的思路,打开发现一个USB流量包,一个加密的压缩包

于是乎,用tshark解析
tshark -r u.pcapng -T fields -e usb.capdata > usbdata.txt

然后用脚本,就能出来

ormalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
output = []
keys = open('usbdata.txt')
for line in keys:
    try:
        if line[0]!='0' or (line[1]!='0' and line[1]!='2') or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0' or line[6:8]=="00":
             continue
        if line[6:8] in normalKeys.keys():
            output += [[normalKeys[line[6:8]]],    [shiftKeys[line[6:8]]]][line[1=='2']
        else:
            output += ['[unknown]']
    except:
        pass
keys.close()

flag=0
print("".join(output))
for i in range(len(output)):
    try:
        a=output.index('<DEL>')
        del output[a]
        del output[a-1]
    except:
        pass
for i in range(len(output)):
    try:
        if output[i]=="<CAP>":
            flag+=1
            output.pop(i)
            if flag==2:
                flag=0
        if flag!=0:
            output[i]=output[i].upper()
    except:
        pass
print ('output :' + "".join(output))

读出文本
honkover1esOfNanle

解压得到flag{e4ef925dd60dc38d16f7d7901b3f4a8ba0aa8828}

可能是我人品问题,没复现出来

XOR

打开是一个压缩包,一个mtpxor.txt文件
我特么就是个弟弟,这是个原题,百度搜了一手CTF mtpxor就出来了

https://blog.csdn.net/valecalida/article/details/102717762

用脚本跑出来密码
打开第一个压缩包

# -*- coding: utf-8 -*-
import binascii
c1 = '24161a1d1c0317100c240f1818001e06120c03170e'
c2 = '380e04533e4f050b1529040154121a0e120100071c'
c3 = '25115312150004015b390916030a000302581c1d15'
c4 = '3c081816570e5200122c0c1c1a011b01460c07175d'
c5 = '24161a1d1c0317100c240f1818001e06120c03170e'
c6 = '380e04533e4f050b1529040154121a0e120100071c'
c7 = '2709161d571b1a01192100091d0b151c131606011a'
c8 = '2709161d5707170a1439091a1a0201070f160a0108'
c9 = '2409161d0e0007171322160a1b1000030f0c1b1e18'
c10 = '24161a1d1c0317100c240f18180013030a0c071713'
c11 = '2409161d03071710092c17161809171d0f161b1a18'
c12 = '2409121d1c1c0b0b0e2b0e010d0a071d1211010b0e'
c13 = '330e061f134f1a015b3e041654121a060510181304'
ciphers = [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11,c12,c13]
cipher_text = "Thenyoushowyourlittlelight"


def sxor(s1,s2):
    return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1, s2))


for cipher in ciphers:
    k = sxor(cipher.decode('hex'),cipher_text)
    print(binascii.a2b_hex(k.encode('hex')))

c11.png

得到第二个压缩包,里面还有个压缩包,但是三个个压缩包里readme的CRC一样,考虑ARCHPR明文攻击
x

将readme文件压缩作为明文,然后攻击

c13.png

第二,第三个压缩包都被破解
得到图片

c14.png

RE

re1

64为IDA打开,shift+f12,然后alt+t搜索字符串,发现

c15.png

进去跟随函数

c16.png

c17.png

在ascii码上按R就能变字符

c18.png

RE_Babyangr

发现complex_function对字符串做了变换,找到字符串,写出逆脚本即可

c19.png

c20.png

贴脚本

a = 'ZCPTMWEHULCABSBD'
flag = ''  
for i in range(len(a)):
    for j in range(64,91):
        if (j - 65 + (18-i)*29)%26 + 65 == ord(a[i]):  
            flag += chr(j)  

print(flag)

得到flag{XDTAWJUAQKEFJDPU}

写在最后

以上是对手里现有的wp进行的复现,如果以后出完整官方版了,再更新。

参考资料

公安一队

师大

  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2020 丰年de博客

请我喝杯咖啡吧~

支付宝
微信