美文网首页
WHCTF-Untitled

WHCTF-Untitled

作者: 2mpossible | 来源:发表于2017-09-19 01:30 被阅读0次

    首先分析他的代码吧

    def gen_args():
        p=getPrime(1024)
        q=getPrime(1024)
        n=p*q
        e=0x10001
        d=primefac.modinv(e,(p-1)*(q-1))%((p-1)*(q-1))
        return (p,q,e,n,d)
    

    这里相当于随机生成了1024位的p和q,然后给了e,跟RSA的算法一样生成私钥d。继续分析

    def proof():
        salt=urandom(4)
        print salt.encode("base64"),
        proof=raw_input("show me your work: ")
        if hashlib.md5(salt+proof.decode("base64")).hexdigest().startswith("0000"):
            print "checked success"
            return 1
        return 0
    

    第一段验证的程度,需要我们给一段base64编码的work,然后salt+work的md5的开头要是"0000",直接用代码爆破得到合适的work

    salt=p.recvline()
    msg = base64.b64decode(salt)
    work=""
    for i in count():
        hashid = md5(msg+str(i)).hexdigest()
        if hashid.startswith('0000'):
            #print i,hashid
            work=base64.b64encode(str(i))
            break
    

    继续看

    def run():
        if not proof():
            return
        m=int(open("/home/bibi/PycharmProjects/work/whctf/flag","r").read().encode("hex"),16)#flag{*}
        (p,q,e,n,d)=gen_args()
        c=pow(m,e,n)
        print "n:",hex(n)
        print "e:",hex(e)
        print "c:",hex(c)
        t=int(hex(m)[2:][0:8],16) #取hex(m)的前八位      t=1718378855
        u=pow(t,e,n)
        print "u:",hex(u)
        print "===="
        x=int(hex(m)[2:][0:8]+raw_input("x: "),16)
        print "===="
        y=int(raw_input("y: "),16)
        if (pow(x,e,n)==y and pow(y,d,n)==t):
            print "s:",hex(int(bin(p)[2:][0:568],2))
    run()
    

    这里大概意思就是题目会返回给我们n,e,c,u的值,并且我们需要输入x,y使得pow(x,e,n)==y and pow(y,d,n)==t才会返回给我们s,那么仔细来看看,首先n,e,c的意思大家应该明白。看看t=int(hex(m)[2:][0:8],16)这句代码,我在后面写了备注,就是取hex(m)的前八位十六进制即4个字符,而题目给了tips,m是flag{*}形式的。所以t是固定的。然后继续看,需要我们输入一个x0,y0然后x=t+x0,y=y0使得pow(x,e,n)==y and pow(y,d,n)==t
    到这里我们可以分析一下数学逻辑,根据RSA的逻辑

    c=pow(m,e,n)<===>m=pow(c,d,n)
    u=pow(t,e,n)<===>t=pow(u,d,n)

    而题目要求t==pow(y,d,n) ==>y=u
    y==pow(x,e,n) <==> u==pow(x,e,n) ==>x=t

    所以我们可以知道y=u,x=t结合x=t+x0,y=y0可以得出x0=空字符 y0=u, 按要求输入x0,y0就能得到s了,这里放最终代码

    #coding=utf-8
    from pwn import *
    from itertools import count
    from hashlib import md5
    import base64
    
    p=remote('118.31.18.75',20013)
    
    salt=p.recvline()
    msg = base64.b64decode(salt)
    work=""
    for i in count():
        hashid = md5(msg+str(i)).hexdigest()
        if hashid.startswith('0000'):
            #print i,hashid
            work=base64.b64encode(str(i))
            break
    #print work
    t=1718378855
    p.recvuntil('work: ')
    p.sendline(work)
    print p.recvline()
    print p.recvline()
    print p.recvline()
    print p.recvline()
    u = int(p.recvline()[5:-2],16)   #u
    print "u:",hex(u)
    print p.recvline()
    p.recvuntil('x: ')
    #print str(hex(t))
    p.sendline("")  #x
    print p.recvline()
    p.recvuntil('y: ')  #y
    p.sendline(str(hex(u))[2:])
    # p_568=int(p.recvline()[5:-2],16)
    # print "p_568:",hex(p_568)
    print p.recvline()
    
    image.png

    继续分析得到s,是p的前568位二进制数组成的数,这里有个小坑,直接拿去高位攻击是不行的,因为必须要576位才能高位攻击(不要问我为什么,因为这是FlappyPig wp说的...)所以我们要爆破568到576中的八位二进制数即两位十六进制然后再进行已知高位攻击,直接放sage代码

    from sage.all import *
    import binascii
    n =   0x9d3a1a28ecb1bd245dd86b18dc4c5b729f23778710005118836129f08e31d6516de8ab47db1b3b7f660f50d283b1e9f2c06e7836136e4c0159f5d2b05771861d3ce6aa8715932eadc1cc0f380909a1961018340f7393142f9c177b1187151f97ac8cdc4ad17fa59a0f39d192af555f27de9cc800846eb2ca6ce78f87c0c0fbf47828328392b81771af624389fd779d130d80739bb7a608961125ba3f1800c766440fa70bfd3f834294d47d7ed9cfffd6d14ae18310f6c1d6d8f88b6c5d72a0b45608b4e21bbb8e314220ed7a2d6a8c95454e571c71b50f1d6a823778ca47131f5b889a1ed1957248bee8c4ac66872a5fd58a121560a27bad4958f1c763f2ffddL
    
    
    cipher = 0x1f2deea59244b14e53c72465febc2064172a35245842fa83ebff313344bed35ee8af8c3f8f61e6f498fa1fd35e63998a573d7717905f72ec01de0b0529eaab10eb0b0c2ca06e9d6e4245e748fd74f4f756a86e379559793389a3ae6c421d51bb78331a487fc3c3e68971e3e26991ab34ce2a2c07ffd5a5a1e215e766b51fb2d6aab63c2dafa3c87d0a5eb79b634740e1fca7a727de997958839bda684e19acad93cae4abfd1c8cc3684419f83696fe4840f3253e7c038adb13a1382667cf7e17ef55c1e950ea474594102e660e36a23bfd3fd830d1c18a434d0b34bed98308399a894dcab909d68bcab7c7ac990974a4f6ed7d612abb7044f6734eaaebcdc0b5L
    
    e2 = 0x10001
    pbits = 1024
    
    for i in range(0,127):
        p4=0xda5df16f286dbc825cd0c8ee48aa26ac27338a75172c5b92351f14d083216f7e91b9355e27cf930646fbbda6058dec3c4ddf751f36df5556359fbe671f9b947b4c79cadfdbb27b00
        p4=p4+int(hex(i),16)
        print hex(p4)
        kbits = pbits - p4.nbits()
        print p4.nbits()
        p4 = p4 << kbits
        PR.<x> = PolynomialRing(Zmod(n))
        f = x + p4
        roots = f.small_roots(X=2^kbits, beta=0.4)
        #rint roots
        if roots:
            p = p4+int(roots[0])
            print "p: ", hex(int(p))
            assert n % p == 0
            q = n/int(p)
            print "q: ", hex(int(q))
            print gcd(p,q)
            phin = (p-1)*(q-1)
            print gcd(e2,phin)
            d = inverse_mod(e2,phin)
            flag = pow(cipher,d,n)
            flag = hex(int(flag))[2:-1]
            print binascii.unhexlify(flag)
    
    image.png

    相关文章

      网友评论

          本文标题:WHCTF-Untitled

          本文链接:https://www.haomeiwen.com/subject/mxbisxtx.html