[CISCN 2018]sm

chall.py

from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from Crypto.Cipher import AES
import hashlib
from random import randint
def gen512num():
    order=[]
    while len(order)!=512:
        tmp=randint(1,512)
        if tmp not in order:
            order.append(tmp)
    # order[]:1~512的一个随机排列
    ps=[]
    for i in range(512):
        p=getPrime(512-order[i]+10)
        pre=bin(p)[2:][0:(512-order[i])]+"1"
        ps.append(int(pre+"0"*(512-len(pre)),2))
    return ps

def run():
    choose=getPrime(512)
    ps=gen512num()
    print ("gen over")
    bchoose=bin(choose)[2:]
    r=0
    bchoose = "0"*(512-len(bchoose))+bchoose
    for i in range(512):
        if bchoose[i]=='1':
            r=r^ps[i]
    flag=open("flag","r").read()

    key=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
    aes_obj = AES.new(key, AES.MODE_ECB)
    ef=aes_obj.encrypt(flag).encode("base64")

    open("r", "w").write(str(r))
    open("ef","w").write(ef)
    gg=""
    for p in ps:
        gg+=str(p)+"\n"
    open("ps","w").write(gg)

run()

分析:
重点是要注意到
image
这个0是补在右边的!
也就是每个ps中的p 它右边的0个数是不同的
那么 r 作为这些数中间某些数的xor 就可以通过r某位的值是0/1来推断对应的p的位置 从而得到flag每位的bit
实现思路:

  • 先计算并保存每个p右边0的个数 num0[]
  • r从低位开始判断 1:找num0[]中值为当前r位数的下标
    solution.py
from Crypto.Util.number import *
from Crypto.Cipher import AES
import hashlib
from base64 import *

r = 6753785483255906709117615805253027649453460653974415214642466102672301763943358839905575042938258141827000621474498066533397472809407687579125519939754658
ef = '5eFo3ANg2fu9LRrFktWCJmVvx6RgBFzd0R8GXQ8JD78='
ps = open('.\[CISCN 2018]sm\ps','r+').readlines()

def Get0snum(x):
    x = int(x)
    tot = 0
    while((x&1)==0):
        tot += 1
        x>>=1
    return tot

flag = [0]*512
num0 = []
for p in ps:
    num0.append(Get0snum(p))

for i in range(511,-1,-1):
    if((r>>(511-i))&1 == 1):
        r ^= int(ps[num0.index(511-i)])
        flag[num0.index(511-i)] = '1'
    else:
        flag[num0.index(511-i)] = '0'

flag = ''.join(flag)
flag = int(flag,2)
choose = flag
key = long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
aes_obj = AES.new(key, AES.MODE_ECB)
flag = b64decode(ef.encode())
flag = aes_obj.decrypt(flag)
print(flag)
posted @ 2023-11-07 08:53  N0zoM1z0  阅读(20)  评论(0编辑  收藏  举报