当前位置: 代码迷 >> 综合 >> BUUCTF 打卡5
  详细解决方案

BUUCTF 打卡5

热度:14   发布时间:2023-11-22 18:38:27.0

1.坏蛋是雷宾

根据题目分析可知进行了Rabin加密。

  • Rabin加密算法:
    Rabin加密算法
    通过上面这篇文章可知:
    mp = c(p+1)/4 mod p
    ?mq = c(q+1)/4 mod q
    yp * p + yq * q = 1
    以及四个明文:
    m1 = yp * p * mq + yq * q * mp (mod N)
    m2 = N - m1
    m3 = yp * p * mq - yq * q * mp (mod N)
    m4 = N - m3
    可以证明每一个密文对应四个原文,而真正的原文一般需要根据验证码来对应。
import gmpy2
import hashlib
n = 523798549
p = 10663
q = 49123
c = 162853095
yxm = 110001gcd = gmpy2.gcdext(p,q)
s,t = int(gcd[1]),int(gcd[2])mp = pow(c,(p+1)//4,p)
mq = pow(c,(q+1)//4,q)m1 = (s*p*mq + t*q*mp)%n
print(bin(m1)[2:])
m2= n - m1
print(bin(m2)[2:])
m3 = (s*p*mq - t*q*mp)%n
print(bin(m3)[2:])
m4 = n - m3
print(bin(m4)[2:])
#判断 是第一个flag = int(bin(m1)[2:-6],2)
print(flag)
print(hashlib.md5(str(flag).encode()).hexdigest())

输出结果为:

10010011100100100101010110001
1100110001100011110101100100
110111001100000100101111001
11000010100100111111010011100
4835626
ca5cec442b2734735406d78c88e90f35

2.[网鼎杯 2020 青龙组]you_raise_me_up

from Crypto.Util.number import *
import randomn = pow(2,512)
m = random.randint(2, n-1) | 1
c = pow(m, bytes_to_long(flag), n)
print('m = ' + str(m))
print('c = ' + str(c))
#m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
#c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499

假设e = bytes_to_long(flag), 根据c = pow(m, bytes_to_long(flag), n),可以推出 e = logm(c - t * n) ,t为未知数。因为n>c>m,所以t<0。
穷举的话,过了好久也没出答案。于是看了别人的wp,得知
在这里插入图片描述

#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' from Crypto.Util.number import * import randomn = pow(2,512) m = random.randint(2, n-1) | 1#仍是产生的随机数 c = pow(m, bytes_to_long(flag), n) print('m = ' + str(m)) print('c = ' + str(c)) '''
import sympy
from Crypto.Util.number import *
m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
n = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
e = sympy.discrete_log(n,c,m)
flag = long_to_bytes(e)
print(flag)

3.[WUSTCTF2020]情书

在这里插入图片描述
可以得出n = 2537,e = 13,d = 937(不知到另一个私钥是不是给错了)。根据密文是分段的,可以推测解密时是分段进行的,直接输出pow(c,d,n),很直观看出数字均在0~25之内,并且文件中第一句话提示了枚举字母表(下标0 ~ 25)。所以只要将得出的m转换成字母即可。

import libnum
n = 2537
p,q = 43,59
phi = (p-1)*(q-1)
e = 13
d = 937temp = 'abcdefghijklmnopqrstuvwxyz'
c = '0156 0821 1616 0041 0140 2130 1616 0793'.split(' ')
for i in c:m = pow(int(i),d,n)print(temp[m],end='')

4.EasyProgram

说实话,刚看到这样的代码时有点懵。不过后来想到应该是把这些代码改写成正常的。

#for i:0 to 256
# set s[i]:is = [i for i in range(0,256)]
#for i:0 to 256
# set t[i]:key[(i)mod(key.lenth)]t = [ord(key[i%6]) for i in range(0,256)]
#for i:0 to 256
# set j:(j+s[i]+t[i])mod(256)
# swap:s[i],s[j]j = 0
for i in range(0,256):j = (j+s[i]+t[i])%256s[i],s[j] = s[j],s[i]
''' for m:0 to 38set i:(i + 1)mod(256)set j:(j + S[i])mod(256)swap:s[i],s[j]set x:(s[i] + (s[j]mod(256))mod(256))set flag[m]:flag[m]^s[x] '''
for m in range(0,38):i = (i+1)%256j = (j+s[j])%256s[i],s[j] = s[j],s[i]x = (s[i]+s[j]%256)%256flag[m] = flag[m] ^ s[x]

在重新看一遍,发现解密的逆过程和加密的过程一样。
尝试读取文件,

with open(r'file.txt','rb')as f:flag = f.read()
print(flag)
print(len(flag))
#b'\x00\xba\x8f\x11+"\x9fQ\xa1/\xab\xb7K\xd7?\xef\xe1\xb5\x13\xbe\xc4\xd4]\x03\xd9\x00z\xca\x1dQ\xa4s\xb5\xef=\x9b1\xb3'
#38

这正好和最后一次循环的次数相同!
不过这个flag肯定是不能进行运算的,还要进一步变换。

with open(r'file.txt','rb')as f:flag = f.read()
flag = bytes_to_long(flag)
print(flag)#92780053907813030391312476357671729211720477366145816965623663010562496870843099194798515
print(len(str(flag)))#89

发现长度还变长了,故将其转换成16进制(因为一开始打印出来的flag内容也算是16进制)

with open(r'file.txt','rb')as f:flag = f.read()
flag = hex(bytes_to_long(flag))
print(flag[2:])#ba8f112b229f51a12fabb74bd73fefe1b513bec4d45d03d9007aca1d51a473b5ef3d9b31b3
print(len(flag[2:]))#74

貌似短了两位,后来才发现一开始打印的flag中第一个是’\x00‘,猜测应该是最高位的0被忽略了,故将其添回去。

from Crypto.Util.number import long_to_bytes,bytes_to_longkey = 'whoami's = [i for i in range(0,256)]t = [ord(key[i%len(key)]) for i in range(0,256)]j = 0
for i in range(0,256):j = (j+s[i]+t[i])%256s[i],s[j] = s[j],s[i]with open(r'file.txt','rb')as f:flag = f.read()
flag = '00'+ hex(bytes_to_long(flag))[2:]temp = []
for i in range(0,len(flag),2):temp.append(int(flag[i:i+2],16))mingwen = ''
i=0
j=0
for m in range(0,38):i = (i+1)%256j = (j+s[i])%256#我去,找了这么久才发现s[i]写成了s[j]s[i],s[j] = s[j],s[i]x = (s[i]+(s[j]%256))%256mingwen += chr(temp[m]^s[x])print(mingwen)