HGAME 2024 WEEK 1 (crypto/re复现)
CRYPTO
ezRSA
解题分析:
leak1=p
leak2=q
(自己一顿复杂的推理得出来的,可能写的比较啰嗦)
考察的是费马小定理:如果p是一个质数,而整数a不是p的倍数,则有a^(p-1)≡1(mod p)
代码:
from Crypto.Util.number import *
from gmpy2 import *
leak1=149127170073611271968182576751290331559018441805725310426095412837589227670757540743929865853650399839102838431507200744724939659463200158012469676979987696419050900842798225665861812331113632892438742724202916416060266581590169063867688299288985734104127632232175657352697898383441323477450658179727728908669
leak2=116122992714670915381309916967490436489020001172880644167179915467021794892927977272080596641785569119134259037522388335198043152206150259103485574558816424740204736215551933482583941959994625356581201054534529395781744338631021423703171146456663432955843598548122593308782245220792018716508538497402576709461
c=10529481867532520034258056773864074017027019578041866245400647840230251661652999709715919620810933437191661180003295923273655675729588558899592524235622728816065501918076120812236580344991140980991532347991252705288633014913479970610056845543523591324177567061948922552275235486615514913932125436543991642607028689762693617305246716492783116813070355512606971626645594961850567586340389705821314842096465631886812281289843132258131809773797777049358789182212570606252509790830994263132020094153646296793522975632191912463919898988349282284972919932761952603379733234575351624039162440021940592552768579639977713099971
n=leak1*leak2
phi=(leak1-1)*(leak2-1)
e=0x10001
d=invert(e,phi)
m=powmod(c,d,n)
print(long_to_bytes(m))
答案:hgame{F3rmat_l1tt1e_the0rem_is_th3_bas1s}
ezMath
题目:
from Crypto.Util.number import *
from Crypto.Cipher import AES
import random,string
from secret import flag,y,x
def pad(x):
return x+b'\x00'*(16-len(x)%16)#ZeroPadding填充
def encrypt(KEY):
cipher= AES.new(KEY,AES.MODE_ECB)# AES的ECB模式 加密,创建了一个 cipher对象
encrypted =cipher.encrypt(flag)#加密flag
return encrypted
D = 114514
assert x**2 - D * y**2 == 1
flag=pad(flag)#flag进行填充,不足16位填充至16位
key=pad(long_to_bytes(y))[:16]#密钥取y的前16位,bytes型,同样不足16位进行填充
enc=encrypt(key)#AES加密
print(f'enc={enc}')
#enc=b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a"
AES加密:对称加密(加密与解密使用的秘钥是一个)
考察的主要是求解pell方程,可以用连分数法求解
这里用sagemath进行求解(它里面有相关的集成运算很方便),注意num的取值,小了的话得不到答案
sagemath在线环境: https://sagecell.sagemath.org/
#sage
def solve_pell(d, num = 10000000):
cf = continued_fraction(sqrt(d))
for i in range(num):
x = cf.numerator(i)#分子
y = cf.denominator(i)#分母
if x^2 - d * y^2 == 1:
return x, y
return None, None
D = 114514
solve_pell(D)
#(3058389164815894335086675882217709431950420307140756009821362546111334285928768064662409120517323199,9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680)
有了x,y直接根据AES加密代码解密即可
def pad(x):
return x+b'\x00'*(16-len(x)%16)#ZeroPadding填充
def decrypt(KEY):
cipher= AES.new(KEY,AES.MODE_ECB)# AES的ECB模式 加密,创建了一个 cipher对象
decrypted =cipher.decrypt(enc)#解密flag
return decrypted
D = 114514
x=3058389164815894335086675882217709431950420307140756009821362546111334285928768064662409120517323199
y=9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680
enc=b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a"
key=pad(long_to_bytes(y))[:16]#密钥取y的前16位,bytes型,同样不足16位进行填充
flag=decrypt(key)#AES解密
print(f'flag={flag}')
解密代码:(下面是直接通过连分数来求解x,y的,但是说实话还是不太理解)
from Crypto.Util.number import *
from Crypto.Cipher import AES
from gmpy2 import *
from math import *
import random,string
def solve_pell(d):#使用连分数求出最小整数解
m=floor(sqrt(d))#a0
r=sqrt(d)
list_a = []
list_a.append(m)#a的数组
n0 = n1 = d - m * m
m1 = m
while 1:
q, m2 = divmod(m1 + m, n1)
list_a.append(q)
m1 = -m2 + m
n1 = (d - m1 * m1) // n1
if m1 == m and n1 == n0:
break
# print(list_a)
b = 1
c = 0
for i in range(len(list_a) - 2, -1, -1):
b1 = c + b * list_a[i]
c = b
b = b1
# print(b*b-d*c*c)
# print(b,c)
return b,c
def pad(x):
return x+b'\x00'*(16-len(x)%16)#ZeroPadding填充
def decrypt(KEY):
cipher= AES.new(KEY,AES.MODE_ECB)# AES的ECB模式 加密,创建了一个 cipher对象
decrypted =cipher.decrypt(enc)#解密flag
return decrypted
D = 114514
x,y=solve_pell(D)
# x=3058389164815894335086675882217709431950420307140756009821362546111334285928768064662409120517323199
# y=9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680
enc=b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a"
key=pad(long_to_bytes(y))[:16]#密钥取y的前16位,bytes型,同样不足16位进行填充
flag=decrypt(key)#AES加密
print(f'flag={flag}')
代码来源:https://www.bilibili.com/read/cv24153490/
答案:hgame{G0od!_Yo3_k1ow_C0ntinued_Fra3ti0ns!!!}
参考文章:
AES加密原理: https://blog.csdn.net/chouzhou9701/article/details/122019967
pell方程: https://zhuanlan.zhihu.com/p/365860557
https://blog.csdn.net/TheWayForDream/article/details/113772229
连分数法解pell方程,非常具体: https://blog.csdn.net/wh2124335/article/details/8871535
ezPRNG
位运算:>>和 <<都是位运算,对二进制数进行移位操作。
<< 是左移,末位补0,类比十进制数在末尾添0相当于原数乘以10,x<<1是将x的二进制表示左移一位,相当于原数x乘2。比如整数4在二进制下是100,4<<1左移1位变成1000(二进制),结果是8。
是右移,右移1位相当于除以2。
而>>=和<<=,就是对变量进行位运算移位之后的结果再赋值给原来的变量,可以类比赋值运算符+=和-=可以理解。
比如x>>=2, 就是把变量x右移2位,再保留x操作后的值。
异或相同为0,不同为1(a ^ 0 = a)
参考的wp,写的真的好详细: https://blog.csdn.net/jayq1/article/details/136063602
题目:
from Crypto.Util.number import *
import uuid
def PRNG(R,mask):
nextR = (R << 1) & 0xffffffff#左移一位,即去掉了高一位,并补上一个0
i=(R&mask)&0xffffffff#只有mask中为1的位置有效(表示R中相应位置是1或者0),其他位置为0
nextbit=0
while i!=0:
nextbit^=(i%2)#nextbit与i的最低位异或
i=i//2#i舍弃最后一位,即nextbit与i的每一位进行了异或
nextR^=nextbit #nextR的最后一位为nextbit
return (nextR,nextbit)
R=str(uuid.uuid4())#生成的随机数,然后转字符串
flag='hgame{'+R+'}'
print(flag)
R=R.replace('-','')#把-删除了
Rlist=[int(R[i*8:i*8+8],16) for i in range(4)]#将R切片,8个为一组转为十进制放入列表中,共32个,列表有4个元素
mask=0b10001001000010000100010010001001
output=[]
for i in range(4):
R=Rlist[i]
out=''
for _ in range(1000):#加密操作
(R,nextbit)=PRNG(R,mask)
out+=str(nextbit)
output.append(out)
print(f'output={output}')
#output=['1111110110111011110000101011010001000111111001111110100101000011110111111100010000111110110111100001001000101101011110111100010010100000011111101101110101011010111000000011110000100011101111011011000100101100110100101110001010001101101110000010001000111100101010010110110111101110011011001011111011010101011000011011000111011011111001101010111100101100110001011010010101110011101001100111000011110111000001101110000001111100000100000101111100010110111001110011010000011011110110011000001101011111111010110011010111010101001000010011110110011110110101011110111010011010010110111111010011101000110101111101111000110011111110010110000100100100101101010101110010101001101010101011110111010011101110000100101111010110101111110001111111110010000000001110011100100001011111110100111011000101001101001110010010001100011000001101000111010010000101101111101011000000101000001110001011001010010001000011000000100010010010010111010011111111011100100100100101111111001110000111110110001111001111100101001001100010', '0010000000001010111100001100011101111101111000100100111010101110010110011001011110101100011101010000001100000110000000011000000110101111111011100100110111011010000100011111000111001000101001110010110010001000110010101011110011101000011111101101011000011110001101011111000110111000011000110011100100101100111100000100100101111001011101110001011011111111011010100010111011000010010101110110100000110100000100010101000010111101001000011000000000111010010101010111101101011111011001000101000100011001100101010110110001010010001010110111011011111101011100111001101111111111010011101111010010011110011111110100110011111110110001000111100010111000101111000011011011111101110101110100111000011100001010110111100011001011010011010111000110101100110100011101101011101000111011000100110110001100110101010110010011011110000111110100111101110000100010000111100010111000010000010001111110110100001000110110100100110110010110111010011111101011110000011101010100110101011110000110101110111011010110110000010000110001', '1110110110010001011100111110111110111001111101010011001111100100001000111001101011010100010111110101110101111010111100101100010011001001011101000101011000110111000010000101001000100111010110001010000111110110111000011001100010001101000010001111111100000101111000100101000000001001001001101110000100111001110001001011010111111010111101101101001110111010111110110011001000010001010100010010110110101011100000101111100100110011110001001001111100101111001111011011010111001001111010001100110001100001100000110000011111010100101111000000101011111010000111110000101111100010000010010111010110100101010101001111100101011100011001001011000101010101001101100010110000010001110011110011100111000110101010111010011010000001100001011000011101101000000011111000101111101011110011000011011000100100110111010011001111101100101100011000101001110101111001000010110010111101110110010101101000000101001011000000001110001110000100000001001111100011010011000000011011101111101001111110001011101100000010001001010011000001', '0001101010101010100001001001100010000101010100001010001000100011101100110001001100001001110000110100010101111010110111001101011011101110000011001000100100101000011011101000111001001010011100010001010110111011100100111110111001010010111010100000100111110101110010010110100001000010010001101111001110100010001011101100111011101011101100100101011010101000101001000101110011011111110110011111111100000000011100000010011000110001000110101010001011000010101000110000101001110101010111011010010111011001010011100010101001100110000110101100010000100110101110100001101001011011110011100110011001010110100101010111110110111100000111010001111101110000000000111011011101000011001010010111001110111000100111011110100101000100011011101100011111000101110110110111111001111000000011100011000010000101001011001101110101000010101001000100110010000101001111100101000001011011010011110001101000001101111010100101001100010100000111000011110101010100011011001110001011110111010111011010101101100000110000001010010101111011']
解题过程:(靠我自己根本写不出来,看了wp之后真的懂了)
首先R是由uuid4生成的随机数,然后把R进行了切片,最后也是最重要的就是加密过程了
def PRNG(R,mask):
nextR = (R << 1) & 0xffffffff#左移一位,即去掉了高一位,并补上一个0
i=(R&mask)&0xffffffff#只有mask中为1的位置有效(表示R中相应位置是1或者0),其他位置为0
nextbit=0
while i!=0:
nextbit^=(i%2)#nextbit与i的最低位异或
i=i//2#i舍弃最后一位,即nextbit与i的每一位进行了异或
nextR^=nextbit #nextR的最后一位为nextbit
return (nextR,nextbit)
R左移一位(即丢弃了最高位,最低位补0),& 0xffffffff作用是限制位数,保证位数一直是32位(可以自己编写代码简单测试一下)
R&mark那么结果中只有mark为1的位置是根据R的值来确定的(即有效位),而mark为0的位置一定为0
而nextbit的值是i的每一位进行异或的结果,即i上的mark有效位的值的异或(a^0=a,异或不分顺序,所以0的异或可以忽略不计)
最后nextR=nextR^nextbit即把nextR的最后一位变为nextbit的值
根据上面的分析可以知道
我们对R的第32位进行猜测(总共就两种可能,不是0就是1),然后根据R’的有效位的值异或结果与检验位(即nextbit的后一位)进行比较,相等则说明猜测正确,否则为另一个值
根据分析写出代码即可,其中得到答案fbbbee823f434f919337907880e4191a,但这不是最后的答案,题目中对于原始的R还进行了一个替换‘_’被删除了
这就要提到uuid4所生成的随机数有一定的格式,这里我尝试生成了10次
import uuid
for i in range(10):
print(uuid.uuid4())
#e0b6e3e8-000a-44b1-a3d4-7612fe75760c
#20c3b641-eaa4-4bfb-9360-a2ecd2be7835
#a3486b4a-995d-436a-b1f1-c3130c10f818
#c011a1f4-3565-4c0b-ac30-5c1fe81fa595
#40413971-bcc1-4d5c-94dc-249eb2fe67c6
#fc5fa159-cecf-4f08-a79c-2801f5ac349e
#41b0adc6-599c-478b-b7d8-eaf154915ff4
#001989d8-0222-480f-88a6-8aaeaaca80b5
#2806efef-26c4-477d-bb55-8be19f8d5cb3
#c06b061b-8a8e-4dbf-8ad8-75717cd9be88
可以看出是有固定格式的,所以根据格式可以直接解出flag
python的一些函数
join()函数
语法: ‘sep’.join(seq)
参数说明
sep:分隔符。可以为空
seq:要连接的元素序列、字符串、元组、字典
上面的语法即:以sep作为分隔符,将seq所有的元素合并成一个新的字符串返回值:返回一个以分隔符sep连接各个元素后生成的字符串
insert()函数用于将指定对象插入列表的指定位置
list.insert(index, obj)
- index:对象obj需要插入的索引位置
- obj:要插入列表中的对象
解密代码:
from Crypto.Util.number import *
# 首先针对mask提取出相与有效位1
# mask=0b10001001000010000100010010001001
mask='10001001000010000100010010001001'
for i in range(len(mask)):
if mask[i]=='1':
print(i,end=',')
# 0,4,7,12,17,21,24,28,31,有效位
#然后对R进行恢复
output=['1111110110111011110000101011010001000111111001111110100101000011110111111100010000111110110111100001001000101101011110111100010010100000011111101101110101011010111000000011110000100011101111011011000100101100110100101110001010001101101110000010001000111100101010010110110111101110011011001011111011010101011000011011000111011011111001101010111100101100110001011010010101110011101001100111000011110111000001101110000001111100000100000101111100010110111001110011010000011011110110011000001101011111111010110011010111010101001000010011110110011110110101011110111010011010010110111111010011101000110101111101111000110011111110010110000100100100101101010101110010101001101010101011110111010011101110000100101111010110101111110001111111110010000000001110011100100001011111110100111011000101001101001110010010001100011000001101000111010010000101101111101011000000101000001110001011001010010001000011000000100010010010010111010011111111011100100100100101111111001110000111110110001111001111100101001001100010', '0010000000001010111100001100011101111101111000100100111010101110010110011001011110101100011101010000001100000110000000011000000110101111111011100100110111011010000100011111000111001000101001110010110010001000110010101011110011101000011111101101011000011110001101011111000110111000011000110011100100101100111100000100100101111001011101110001011011111111011010100010111011000010010101110110100000110100000100010101000010111101001000011000000000111010010101010111101101011111011001000101000100011001100101010110110001010010001010110111011011111101011100111001101111111111010011101111010010011110011111110100110011111110110001000111100010111000101111000011011011111101110101110100111000011100001010110111100011001011010011010111000110101100110100011101101011101000111011000100110110001100110101010110010011011110000111110100111101110000100010000111100010111000010000010001111110110100001000110110100100110110010110111010011111101011110000011101010100110101011110000110101110111011010110110000010000110001', '1110110110010001011100111110111110111001111101010011001111100100001000111001101011010100010111110101110101111010111100101100010011001001011101000101011000110111000010000101001000100111010110001010000111110110111000011001100010001101000010001111111100000101111000100101000000001001001001101110000100111001110001001011010111111010111101101101001110111010111110110011001000010001010100010010110110101011100000101111100100110011110001001001111100101111001111011011010111001001111010001100110001100001100000110000011111010100101111000000101011111010000111110000101111100010000010010111010110100101010101001111100101011100011001001011000101010101001101100010110000010001110011110011100111000110101010111010011010000001100001011000011101101000000011111000101111101011110011000011011000100100110111010011001111101100101100011000101001110101111001000010110010111101110110010101101000000101001011000000001110001110000100000001001111100011010011000000011011101111101001111110001011101100000010001001010011000001', '0001101010101010100001001001100010000101010100001010001000100011101100110001001100001001110000110100010101111010110111001101011011101110000011001000100100101000011011101000111001001010011100010001010110111011100100111110111001010010111010100000100111110101110010010110100001000010010001101111001110100010001011101100111011101011101100100101011010101000101001000101110011011111110110011111111100000000011100000010011000110001000110101010001011000010101000110000101001110101010111011010010111011001010011100010101001100110000110101100010000100110101110100001101001011011110011100110011001010110100101010111110110111100000111010001111101110000000000111011011101000011001010010111001110111000100111011110100101000100011011101100011111000101110110110111111001111000000011100011000010000101001011001101110101000010101001000100110010000101001111100101000001011011010011110001101000001101111010100101001100010100000111000011110101010100011011001110001011110111010111011010101101100000110000001010010101111011']
flag=''
for i in range(4):
nextbit=output[i]
R = []#列表方便插入,因为我们需要从头部插入,推结果的时候是倒着推的
for _ in range(32):#每次求解1bit,一共32bit 因为与0xffffffff 为限制位数的作用
temp='0'+''.join(R)+nextbit[:32-1-len(R)]#总共32位,第一个是猜测位为0,第二部分是已知R位(方便推导前面的bit),第三部分是nextbit填充位
#猜测检验
if (int(temp[0])^int(temp[4])^int(temp[7])^int(temp[12])^int(temp[17])^int(temp[21])^int(temp[24])^int(temp[28])^int(temp[31])
== int(nextbit[32-1-len(R)])):#nextbit的值(str型)要转为int型,有效位的异或会等于nextbits校验位的值
R.insert(0,'0')#猜测正确在首位填充0
#insert(a,b) a为索引位置,b为插入对象
else:
R.insert(0,'1')#否则填充1
R=''.join(R)#第一段求完转为字符串
R=hex(int(R,2))[2:] # 二进制转十进制 转16进制,[2:] 是因为十六进制有0x前缀,所以从索引位置为2的地方开始
flag+=R
print(flag)
# fbbbee823f434f919337907880e4191a
答案:hgame{fbbbee82-3f43-4f91-9337-907880e4191a}
奇怪的图片
题目:
import time
from PIL import Image, ImageDraw, ImageFont
import threading
import random
import secrets
flag = "hgame{fake_flag}"
def generate_random_image(width, height):#生成指定宽度和高度的随机颜色图像
image = Image.new("RGB", (width, height), "white")
pixels = image.load()#获取像素数据,然后可以使用pixels[x, y]来访问和操作图像中的单个像素
for x in range(width):
for y in range(height):
red = random.randint(0, 255)
green = random.randint(0, 255)
blue = random.randint(0, 255)
pixels[x, y] = (red, green, blue)
return image
def draw_text(image, width, height, token):#在给定图像上随机位置绘制一个文本标志
font_size = random.randint(16, 40)#字体大小
font = ImageFont.truetype("arial.ttf", font_size)#字体类型
text_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))#文本颜色
x = random.randint(0, width - font_size * len(token))
y = random.randint(0, height - font_size)
draw = ImageDraw.Draw(image)# 创建一个ImageDraw对象,用于在图像上绘制
draw.text((x, y), token, font=font, fill=text_color)#在图像上的 (x, y) 坐标处绘制给定的文本标志 token,使用指定的字体、颜色进行填充。 同时x和y的操作 保证随机坐标一定在图像内部
return image
def xor_images(image1, image2):#图像异或
if image1.size != image2.size:#大小要一致
raise ValueError("Images must have the same dimensions.")
xor_image = Image.new("RGB", image1.size)
pixels1 = image1.load()
pixels2 = image2.load()
xor_pixels = xor_image.load()
for x in range(image1.size[0]):
for y in range(image1.size[1]):
r1, g1, b1 = pixels1[x, y]
r2, g2, b2 = pixels2[x, y]
xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)#三个值分别异或
return xor_image
def generate_unique_strings(n, length):#生成一定数量的指定长度的唯一随机字符串
unique_strings = set()#集合对象
while len(unique_strings) < n:
random_string = secrets.token_hex(length // 2)
unique_strings.add(random_string)
return list(unique_strings)
#给图像命名 图片个数就是flag的字符数
random_strings = generate_unique_strings(len(flag), 8)
current_image = generate_random_image(120, 80)
key_image = generate_random_image(120, 80)
def random_time(image, name):
time.sleep(random.random())
image.save(".\\png_out\\{}.png".format(name))
for i in range(len(flag)):
current_image = draw_text(current_image, 120, 80, flag[i])#flag分别写入了每个图片中
threading.Thread(target=random_time, args=(xor_images(current_image, key_image), random_strings[i])).start()#当调用start()方法时,新线程将开始执行random_time函数,并以xor_images(current_image, key_image)和random_strings[i]作为参数。
根据对代码的分析:首先生成了current_image和key_image,然后循环依次写入flag前i个字符进current_image,然后再把current_image和key_image进行异或,最后输出了得到的图片
总共21张图片,说明flag的长度为21位,我们直接取一张图片和其他图片异或,然后就可以得到写入了flag的21张图片,手动排序即可得到答案。
我们在使用第一张图片与其他图片异或后得到的结果如下:
我们可以看到含有{的图片有5个,说明原图片上的字符正好是hgame{,只有这个与其他异或能够得到5个含{的图片,剩下的我们直接手动排序即可(含有{的图片可以不去看,里面包含的信息我们已知为hgame{,此外需要注意的是因为图片的异或,相同的相素点会消失)
解题代码:
from PIL import Image
import os
def xor_images(image1, image2):#图像异或
if image1.size != image2.size:#大小要一致
raise ValueError("Images must have the same dimensions.")
xor_image = Image.new("RGB", image1.size)
pixels1 = image1.load()
pixels2 = image2.load()
xor_pixels = xor_image.load()
for x in range(image1.size[0]):
for y in range(image1.size[1]):
r1, g1, b1 = pixels1[x, y]
r2, g2, b2 = pixels2[x, y]
xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)#三个值分别异或
return xor_image
def list_files(path):
a=[]
for root, dirs, files in os.walk(path):#文件夹路径,文件夹名字,文件名
for i in range(len(files)):
a.append(os.path.join(root,files[i]))
return a
path='E:\Crypto\png_out'#要提取的文件地址
png_list=list_files(path)
print(len(png_list))
c1=Image.open(png_list[0])
for i in range(len(png_list)):
c2=Image.open(png_list[i])
xor_images(c1,c2).save("E:\Crypto\png_in\\image_{}.png".format(i))
答案:hgame{1adf_17eb_803c}
参考wp: https://blog.csdn.net/qq_42880719/article/details/136053063
Reverse
ezUPX
解题分析:
根据题目可以知道是upx加壳,直接解壳,分析代码即可(代码比较简单,异或)
解题代码:
#include<stdio.h>
int main()
{
int data[] =
{
100, 123, 118, 115, 96, 73, 101, 93, 69, 19,
107, 2, 71, 109, 89, 92, 2, 69, 109, 6,
109, 94, 3, 70, 70, 94, 1, 109, 2, 84,
109, 103, 98, 106, 19, 79, 50
};
int flag[37];
for ( int i = 0;i<=37; ++i ){
flag[i]=(data[i] ^ 0x32);
printf("%c",flag[i]);
}
return 0;
}
答案:VIDAR{Wow!Y0u_kn0w_4_l1ttl3_0f_UPX!}
ezIDA
ida打开就看到答案了
答案:hgame{W3lc0me_T0_Th3_World_of_Rev3rse!}
ezASM
解题分析:
主要考的应该是汇编语言的掌握,但是我学的不咋地,直接扔给了chat GPT分析知道了大致操作,写出代码(会去恶补汇编知识的,要命)
代码:
#include<stdio.h>
int main()
{
int data[] =
{
74, 69, 67, 79, 71, 89, 99, 113, 111, 125, 107, 81, 125, 107, 79, 82, 18, 80, 86, 22, 76, 86, 125, 22, 125, 112, 71, 84, 17, 80, 81, 17, 95, 34
};
int flag[33];
for ( int i = 0;i<33; ++i ){
flag[i]=(data[i] ^ 0x22);
printf("%c",flag[i]);
}
return 0;
}
答案:hgame{ASM_Is_Imp0rt4nt_4_Rev3rs3}
ezPYC
这个我看了wp,但是下载了pyinstxtractor.py这个没办法从exe文件中获取pyc文件,不知道为啥,先放一下,我后面补上
这里是分界线(我回来了,终于知道为啥了,是因为我的python版本和给的exe文件python版本不同,所以不行,这里需要改一下python版本)
根据题目可以知道是python逆向,但是给的是exe文件,需要先从里面提取出pyc文件,通过pyinstxtractor.py进行提取即可
下载地址: extremecoders-re/pyinstxtractor: PyInstaller Extractor (github.com)
但是但是,这里我把exPYC.exe和pyinstxtractor.py文件置于同一文件夹内,在该路径内打开cmd
然后输入命令:python pyinstxtractor.py exPYC.exe没反应,离谱了,上网查也没查到什么(困惑了好久,不明白为啥自己不行),突然想起之前学长叫我们python逆向最好下载一个Anaconda进行python环境的匹配(和给的exe文件python版本一致),于是跑去下载了
Anaconda下载和安装: https://blog.csdn.net/fan18317517352/article/details/123035625
不过下载的时候最好下载新一点的版本,我因为下载的版本太老了,也不行,于是又删掉了重新下(说多了都是泪)
下载完之后先检测一下自己配置好了没
这样子就是配置好了,此外如果版本不太行的话可以升级一下
conda update conda 更新至最新版本,也会更新其它相关包
conda update --all 更新所有包
conda create -n xxx python=3.7 创建一个python3.7 名为xxx的虚拟环境
conda remove -n xxx --all 移除环境
conda info --env 或者 conda env list 查看当前有几个环境
conda activate python35 切换环境
然后我们创建一个匹配exe文件的python环境(我这是已经创建好了的)
然后切换到需要的环境即可(下面是切换成功的)
然后就正常操作即可,输入命令:python pyinstxtractor.py ezPYC.exe
然后在ezPYC.exe_extracted文件夹中找到ezPYC.pyc文件
得到了pyc文件还没结束,我们需要反编译pyc文件获取源码,这里直接在cmd中输入pycdc ezPYC.pyc是不行的,我们需要下载pycdc项目
那我这边的话因为没下载,偷个懒直接在线网站反编译了
源码是一个很简单的异或加密,对应写出解密代码即可
解密代码:
flag = [
87,
75,
71,
69,
83,
121,
83,
125,
117,
106,
108,
106,
94,
80,
48,
114,
100,
112,
112,
55,
94,
51,
112,
91,
48,
108,
119,
97,
115,
49,
112,
112,
48,
108,
100,
37,
124,
2]
c = [
1,
2,
3,
4]
for i in range(0, 36, 1):
print(chr(flag[i]^ c[i % 4]),end='')
答案:VIDAR{Python_R3vers3_1s_1nter3st1ng!}