ROARCTF2020-Crypto

前言

这次ROARCTF我打得时间比较短,所以只做了Crypto_System,其余两题都是后来复现的…

Crypto_System

将式子都化简为以g为底的式子,这样可以将这题看起来的离散对数问题化简为简单的求逆元问题。由于可能求不出逆元,所以需要进行判断
(用Linux跑的)

from pwn import *
from libnum import *
from Crypto.Util.number import *
from hashlib import *
from gmpy2 import invert
# These three are constants
p = 12039102490128509125925019010000012423515617235219127649182470182570195018265927223
g = 10729072579307052184848302322451332192456229619044181105063011741516558110216720725

def int2str(data, mode="big"):
    if mode == "little":
        return sum([ord(data[_]) * 2 ** (8 * _) for _ in range(len(data))])
    elif mode == "big":
        return sum([ord(data[::-1][_]) * 2 ** (8 * _) for _ in range(len(data))])

def get_parameter(m):
    x = int2str(m, 'little')
    y = pow(g, x, p)
    a = bytes_to_long(sha256(long_to_bytes(y).rjust(128, "\0")).digest())
    b = pow(a, a, p - 1)
    h = pow(g, b, p)

    return y, h, b , x

def sign(m):
    y, h, b = get_parameter(m)
    r = getStrongPrime(512)
    s = (y * pow(h, r, p)) % p 

    return str(r),str(s)

def verify(m, r, s):
    y, h, b ,x= get_parameter(m)
    if s == ((y * pow(h, r, p)) % p):
        return True
    else:
        return False
def fuckhash():
    xx=sh.recvuntil('XXXX:')
    suffix=xx.split('+')[1].split(')')[0].strip(' ')
    res=xx.split('==')[1].split('\n')[0].strip(' ')
    print(suffix,res)

    S = ''
    for h in range(48,127):
        S += chr(h)

    for h in S:
        for i in S:
            for j in S:
                for k in S:
                    x = sha256((h + i + j + k + suffix).encode()).hexdigest()
                    if x == res:
                        sh.sendline(h+i+j+k)
                        return (h + i + j + k)

def test(r1,r2,s1,s2):
    if r1!=r2 and s1==s2 :
        return True
    else:
        return False



def attack(m1,m2,r1):
    (y1, h1, b1,x1) = get_parameter(m1)
    (y2, h2, b2,x2) = get_parameter(m2)
    s1 = (y1 * pow(h1, r1, p)) % p 
    b2_ = invert(int(b2),int(p-1)) 
    r2 = b2_*(x1 -x2+ b1*r1)%(p-1)
    print r2
    s2 = (y2 * pow(h2, r2, p)) % p 
    print verify(m2, r2, s2)
    print r2-r1
    
    print test(r1,r2,s1,s2)
    print ('r2,s2 = (%s,%s)')%(r2,s2)
    sh.recvuntil('Please choice your options:')
    sh.sendline('3')
    sh.recvuntil("message:")
    sh.sendline('('+str(r2)+','+str(s2)+')')
    print sh.recvuntil('\n')


def judgee(m1,m2):
    try:
        (y1, h1, b1,x1) = get_parameter(m1)
        (y2, h2, b2,x2) = get_parameter(m2)
        b2_ = invert(int(b2),int(p-1)) 
        return True
    except:
        return False

c=0
while True:
    c+=1
    print ("round:%s")%(c)
    sh=remote('139.129.98.9',30001)
    print(fuckhash())
    drop = 'options:'
    sh.recvuntil('(64 bytes):', drop=False)
    m1 = sh.recvuntil('\n', drop=False)[:-1].decode('hex')
    sh.recvuntil('(64 bytes):', drop=False)
    m2 = sh.recvuntil('\n', drop=False)[:-1].decode('hex')
    sh.recvuntil("'r':", drop=False)
    r1 = sh.recvuntil('\n', drop=False)
    r1=int(r1)
    print m1
    print m2
    print r1
    if judgee(m1,m2) == False:
        continue
    else:
        print('right!')
        attack(m1,m2,r1)
        break

结果截图:
在这里插入图片描述

EasyRSA

根据给的tips我们可以得到 2 ∗ x ∗ y ∗ b e t a + x + y 2*x*y*beta + x + y 2xybeta+x+y,

然后又知 p h i ( n ) = 4 ∗ x ∗ y ∗ b e t a phi(n)=4*x*y*beta phi(n)=4xybeta

所以我们可以通过 t i p s / b e t a tips/beta tips/beta再爆破 x ∗ y x*y xy求出 p h i phi phi

from Crypto.Util.number import *
from  gmpy2 import invert
n=17986052241518124152579698727005505088573670763293762110375836247355612011054569717338676781772224186355540833136105641118789391002684013237464006860953174190278718294774874590936823847040556879723368745745863499521381501281961534965719063185861101706333863256855553691578381034302217163536137697146370869852180388385732050177505306982196493799420954022912860262710497234529008765582379823928557307038782793649826879316617865012433973899266322533955187594070215597700782682186705964842947435512183808651329554499897644733096933800570431036589775974437965028894251544530715336418443795864241340792616415926241778326529055663
e=65537
enc=10760807485718247466823893305767047250503197383143218026814141719093776781403513881079114556890534223832352132446445237573389249010880862460738448945011264928270648357652595432015646424427464523486856294998582949173459779764873664665361437483861277508734208729366952221351049574873831620714889674755106545281174797387906705765430764314845841490492038801926675266705606453163826755694482549401843247482172026764635778484644547733877083368527255145572732954216461334217963127783632702980064435718785556011795841651015143521512315148320334442235923393757396733821710592667519724592789856065414299022191871582955584644441117223
beta=11864389277042761216996641604675717452843530574016671576684180662096506094587545173005905433938758559675517932481818900399893444422743930613073261450555599
tip = (n-1)//(2*beta)  
xy1=tip//beta
def attack(xy1):
    while True:
        try:
            xy1=xy1-2
            d=invert(e,2*xy1*pow(beta,2))
            c=pow(3,e,n)
            if pow(c,d,n)==3:
                return d
            else:
                continue
        except:
            continue
d=attack(xy1)
print long_to_bytes(pow(enc,d,n))

Reverse

参考 https://kt.gy/blog/2015/10/asis-2015-finals-rsasr/
因为p和q是二进制顺序相反的素数,所以p的每一位都和q有关系。所以我们可以尝试遍历p的二进制,通过判断生成的p与q再进行迭代。具体代码如下:

n = 158985980192501034004997692253209315116841431063210516613522548452327355222295231366801286879768949611058043390843949610463241574886852164907094966008463721486557469253652940169060186477803255769516068561042756903927308078335838348784208212701919950712557406983012026654876481867000537670622886437968839524889

def Brute_force(a,b,k):
    if k == 256:
        if a*b==n:
            print (a,b)
        return 0
  
    for i in range(2):
        for j in range(2):
            
            a1=a+i*(2**(511-k))+j*(2**k)
            b1=b+j*(2**(511-k))+i*(2**k)
            
            if a1*b1>n:
                continue 
                
            if  (a1+2**(511-k))*((b1+2**(511-k)))< n: 
                continue 
                
            if (a1*b1)%(2**(k+1)) != n%(2**(k+1)):
                continue

            Brute_force(a1,b1,k+1)

    return 0

Brute_force(0,0,0)        

结尾

这三道题统一的地方在于都是使用了爆破这一基本手法。做题的话有时候会纠结于某一个知识点,纠结于某种固定的解法,这样往往会思维封闭。其实我们更应该常驻爆破的思想去解题。结合各种已知解法灵活运用才是更好的做题方法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值