首页 > 其他分享 >CTF总结

CTF总结

时间:2024-05-12 20:44:22浏览次数:23  
标签:总结 __ .__ http chr CTF print import

CTF misc crypto re pyjail总结

MISC

常见文件16进制头尾

一些CTF题目的附件会去掉文件头,需要补全文件头,在一些文件里也可能隐藏多个文件,这就需要熟悉文件尾/文件头以方便提取或做判断,题目附件在下载的时候可能会没有文件后缀,无法判断是那种文件,由于各文件的16进制都有规定格式,在将文件在 010Editor 中打开后根据文件16进制头可以判断是哪一种文件,总之需要熟悉常见文件头以及格式,010里面有模板,方便识别各类文件,但也会有识别出错的情况,MISC题目千变万化...

PNG

文件头 89 50 4E 47 0D 0A 1A 0A

文件尾 AE 42 60 82

**JPEG **

文件头 FF D8 FF

文件尾 FF D9

GIF

**文件头 47 49 46 38 39(37) 61 **

文件尾 00 3B

BMP

文件头 42 4D

ZIP

文件头 50 4B 03 04

**文件尾 50 4B 01 02 / 50 4B 05 06 **

RAR Archive (rar)

文件头:52 61 72 21

Wave (wav)

文件头:57 41 56 45

其他16进制

TGA

未压缩的前4字节 00 00 02 00 RLE压缩的前5字节 00 00 10 00 00

TIFF (tif)

文件头:49 49 2A 00

ico

文件头:00 00 01 00

MS Word/Excel (xls.or.doc)

文件头:D0 CF 11 E0

MS Access (mdb) 文件头:

53 74 61 6E 64 61 72 64 20 4A

WordPerfect (wpd) 文件头:

FF 57 50 43

Adobe Acrobat (pdf) 文件头:

25 50 44 46 2D 31 2E

application/vnd.visio(vsd) 文件头:

D0 CF 11 E0 A1 B1 1A E1

Email [thorough only] (eml) 文件头:

44 65 6C 69 76 65 72 79 2D 64 61 74 65 3A

Outlook Express (dbx) 文件头:

CF AD 12 FE C5 FD 74 6F

Outlook (pst) 文件头:

21 42 44 4E

Rich Text Format (rtf) 文件头:

7B 5C 72 74 66

txt 文件(txt) 文件头:Unicode:FE FF / Unicode big endian:FF FE / UTF-8:EF BB BF /ANSI编码是没有文件头的

audio(Audio)

文件头: 4D 54 68 64

audio/x-aac(aac)

文件头:FF F1(9)

AVI (avi) 文件头:41 56 49 20

Real Audio (ram) 文件头:2E 72 61 FD

Real Media (rm) 文件头:2E 52 4D 46

MPEG (mpg) 文件头:00 00 01 BA(3)

Quicktime (mov) 文件头:6D 6F 6F 76

Windows Media (asf) 文件头:30 26 B2 75 8E 66 CF 11

MIDI (mid) 文件头:4D 54 68 64

XML (xml) 文件头:3C 3F 78 6D 6C

HTML (html) 文件头:68 74 6D 6C 3E

Quicken (qdf) 文件头:AC 9E BD 8F

Windows Password (pwl) 文件头:E3 82 85 96

windows证书文件(der) 文件头:30 82 03 C9

CAD (dwg) 文件头:41 43 31 30

Windows Shortcut (lnk) 文件头:4C 00 00 00

Windows reg(reg) 文件头:52 45 47 45 44 49 54 34

注:并非全部文件只收集常见,够用

隐写术

常用工具:

**16进制查看:010Editor winhex **

音频查看:Audacity

等等

遇到举例

png:

首先介绍一款好用的检测png隐写工具

zsteg:https://github.com/zed-0xff/zsteg

一些隐藏的文件,lsb隐写等都可以检测到

binwalk:

可以检测分离文件

#检测图片
binwalk filename
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 640 x 1743, 8-bit/color RGBA, non-interlaced
#分离图片
binwalk -e filename
(可能报错使用 binwlak -e filename --run-as=root)
#刀操作,也可以分离图片
dd if=filename of=newfilename skip=DECIMAL bs=1

foremost:

同样可以分离文件,而且细分化,有log,有时候有奇效

foremost -o 存放文件名 文件名

使用非常方便:

zsteg filename
或
zsteg filename -a
还有其他参数指令
zsteg -h

宽高隐写:

png文件最常见的就是宽高隐写,通过修改宽高隐藏一些内容,这类图片肉眼一般无法判断,有的倒非常明显,可以通过修改宽高的16进制来尝试恢复,但有可能无法得到预期图片,可以通过工具或者crc爆破得到正确的宽高再修改文件的16进制得到原来的图片。

文件16进制中:

隐藏的信息可能存放在16进制文件尾,使用010打开在末尾处查看,也可能存放在文件中,使用搜索尝试寻找

010功能强大

IDAT隐写:

pngcheck可以检测文件IDAT,损坏,多余

文件IDAT通常中间的会保持一致再满了的时候才会进行下一个

此时就需要提取或者删除来达到恢复的目的

里面通常会有zilb,也可能隐写在这里面

StegSolve:一款工具

png jpg gif都可以使用,检测图片lsb隐写,各颜色通道等

Data Extract:lsb隐写等

Frame Browser:gif帧分析

exiftool:

查看图片exif等信息,flag可能隐藏在这里

PNGdebugger/TweakPNG(png工具):

均可查看png文件数据,支持修改删除等操作

stegpy:

带有key的隐写

stegpy filename -p

png相关隐写暂时这么多

JPEG/JPG:

EXIF:

最常见的就是EXIF,备注,详细信息等,会有提示信息或者flag,

使用exiftool:

exiftool filename

或在线:EXIF信息查看器 (tuchong.com)

文件16进制:

同png一样,也可能存放在末尾或者文件中。

文件提取:

存在附件文件,使用binwalk/foremost

JSteg&&JPHide&&OutGuess&&F5:

四个隐写方式

可以使用相应工具提取

Stegdetect 可以帮助探测

SilentEye:

jpg或者wav文件隐写flag

一些非预期(strings filename)

音频隐写:

MP3/WAV:

使用Audacity查看波形图或者频谱图,一些信息会隐藏在上面,波形图的摩斯密码,频谱图可能有key,pass,甚至flag等

MP3Stego:MP3隐写工具

encode -E txt -P 密码 MP3文件
decode -X -P 密码 MP3name

这种一般会有pass提示在文件尾等

LSB:DerbyCon CTF - WAV Steganography · ethackal

deepsound:WAV工具

需要密码

dtmf2num:拨号音

音频滴滴滴

MMSSTV:

一种电报,可以将音频转化为图片,音频多嘈杂

SilentEye:wav工具

xls:

文件可能存在隐写有二维码,手点检测块是否不同,将其黑白变化得到二维码,可以使用QR扫描得到flag

使用7z点开里面存在内容,这类不好找可以使用程序寻找等

word:

字体隐藏:ctrl+a修改全局字体得到隐藏内容,修改设置得到隐藏文字,修改后缀或使用7z打开得到里面的文件,可能存在flag等有用信息

pyc隐写:

使用剑龙隐写可以得到隐藏的flag

stegosaurus -x pycname

CRYPTO

常见编码:

rabbit/aes/des加密:

U2FsdGVkX1通常为rabbit密文头,特征类似base64(aes ,des相似)

rabbit为一种流密码,其详情高速流密码——Rabbit - 掘金 (juejin.cn)

在线解密网:在线Rabbit加密 | Rabbit解密- 在线工具 (sojson.com)

例子:
U2FsdGVkX188nKW3XYAppATn9y3lZg==  解密为:flag

base家族:

(base64是每6bit位一个映射base32是每5bit位一个映射base16是每bit4位一个映射)

base64加密:( 编码后的数据比原始数据略长,为原来的4/3)

密文结尾通常为,由(A-Z、a-z、0-9、+、/)组成,以为填充

加密原理:用64个可打印字符表示二进制所有数据的方法...(Base64 算法原理,以及编码、解码【加密、解密】 介绍 - 程默 - 博客园 (cnblogs.com))

例子:
ZmxhZ3tiYXNlfQ== 解密为:flag{base}

在线解密网:Base64 编码/解码 - 在线工具 (toolhelper.cn)

base58加密:(在比特币加密中有涉及,区块链)

base58的编码表相比base64少了数字0,大写字母I,O,小写字母 l (这个是L),以及符号‘+’和‘/’

加密原理:将字符流转成256进制的一个超大数 然后不断的模58

例子:
2w6zoHymm2SU4UfhE 解密为: flag{base58}

在线解密网:在线Base58编码解码 (lddgo.net)

base32加密:

由(A-Z、2-7)32个可见字符构成,“=”符号用作后缀填充,无数字+/,会有多个=。

例子:
MZWGCZ33MJQXGZJTGJ6Q====  解密为: flag{base32}

在线解密网:Base32编码解码,Base32在线转换工具 - 千千秀字 (qqxiuzi.cn)

base16加密:

将二进制文件转换成由16个字符组成的文本,由a-z,0-9组成,无=填充,与md5,hex相似。

例子:
666c61677b6261736531367d  解密为:flag{base16}

在线解密网:Base16编码解码,Base16在线转换工具 - 千千秀字 (qqxiuzi.cn)

除此之外还有

base62,base85,base91,base92,base100。

base91的密文由91个字符(0-9,a-z,A-Z,!#$%&()*+,./:;<=>?@[]^_`{|}~”)组成

base100为表情包

base85为BOu!rDst>tGAhM<A1fSl1GgsI特征:特点是奇怪的字符比较多,但是很难出现等号

等等十分多

这里推荐一个工具ToolsFx非常多内容,编码(CTF站点导航 | 猫捉鱼铃 (mzy0.com)

古典密码还有非常多类型:

推荐网站:CTF常见编码及加解密(超全) - ruoli-s - 博客园 (cnblogs.com)

一些好用的加密解密网站:

爆破维吉尼亚:Vigenere Solver | guballa.de

词频分析:https://quipqiup.com/

佛曰http://hi.pcmoe.net/buddha.html

盲文:http://www.atoolbox.net/Tool.php?Id=837

RSA:

推荐大佬博客:https://tangcuxiaojikuai.xyz/

神 糖醋小鸡快

from Crypto.Util.number import *
n = p * q
m = "flag"
m = bytes_to_long(m)
e = 65537
phi = (p-1)*(q-1)
d = inverse(e,phi)
c = pow(m,e,n)
m = pow(c,d,n)
flag = long_to_bytes(m)

一些常见攻击方式的脚本和方法:

【CTF-RSA】基于N分解的RSA题目

1.在线查询分解网站
http://www.factordb.com/index.php

2.使用yafu工具分解
下载地址:https://sourceforge.net/projects/yafu/

3.使用费马分解
网上找的脚本,p和q接近

def isqrt(n):
  x = n
  y = (x + n // x) // 2
  while y < x:
    x = y
    y = (x + n // x) // 2
  return x

def fermat(n, verbose=True):
    a = isqrt(n) # int(ceil(n**0.5))
    b2 = a*a - n
    b = isqrt(n) # int(b2**0.5)
    count = 0
    while b*b != b2:
        # if verbose:
        #     print('Trying: a=%s b2=%s b=%s' % (a, b2, b))
        a = a + 1
        b2 = a*a - n
        b = isqrt(b2) # int(b2**0.5)
        count += 1
    p=a+b
    q=a-b
    assert n == p * q
    # print('a=',a)
    # print('b=',b)
    # print('p=',p)
    # print('q=',q)
    # print('pq=',p*q)
    return p, q
fermat(n)

4.分解出来后,用脚本解密即可

import gmpy2
import libnum

p=
q=
e=
c=

n=p*q
phi_n=(p-1)*(q-1)

#求逆元
#d=libnum.invmod(e,phi_n)
d=gmpy2.invert(e,phi_n)

m=pow(c,d,n)
print(m)
print(libnum.n2s(int(m)).decode())
出题脚本
p,q接近,很快就能分解
import libnum
import gmpy2

p=libnum.generate_prime(1024)
#下一个素数
q=gmpy2.next_prime(p)
print(p)
print(q)
print(gmpy2.is_prime(q))
e=65537
m="flag{20d6e2da95dcc1fa5f5432a436c4be18}"
m=libnum.s2n(m)
n=p*q
phi_n=(p-1)*(q-1)
d=libnum.invmod(e,phi_n)
c=pow(m,e,n)

print("n=",n)
print ("e=",e)
print ("c=",c)

解题脚本

import  gmpy2
import libnum

def isqrt(n):
  x = n
  y = (x + n // x) // 2
  while y < x:
    x = y
    y = (x + n // x) // 2
  return x

def fermat(n, verbose=True):
    a = isqrt(n) # int(ceil(n**0.5))
    b2 = a*a - n
    b = isqrt(n) # int(b2**0.5)
    count = 0
    while b*b != b2:

        # if verbose:

        #     print('Trying: a=%s b2=%s b=%s' % (a, b2, b))

        a = a + 1
        b2 = a*a - n
        b = isqrt(b2) # int(b2**0.5)
        count += 1
    p=a+b
    q=a-b
    assert n == p * q

    # print('a=',a)

    # print('b=',b)

    print('p=',p)
    print('q=',q)

    # print('pq=',p*q)

    return p, q
n= 
e= 65537
c= 
pq=fermat(n)
p=pq[0]
q=pq[1]
phi_n=(p-1)*(q-1)
#求逆元
#d=libnum.invmod(e,phi_n)
d=gmpy2.invert(e,phi_n)
m=pow(c,d,n)
print(m)
print(libnum.n2s(int(m)).decode()) 

RSA密钥生成与读取

from Crypto.PublicKey import RSA

p= 
q= 
n= 
d= 
e= 65537


rsa_components = (n, e)
keypair = RSA.construct(rsa_components)
with open('pubckey.pem', 'wb') as f :
    f.write(keypair.exportKey())
from Crypto.PublicKey import RSA

p= 787228223375328491232514653709
q= 814212346998672554509751911073
n= 640970939378021470187479083920100737340912672709639557619757
d= 590103645243332826117029128695341159496883001869370080307201
e= 65537


rsa_components = (n,e,d,p,q)
keypair = RSA.construct(rsa_components)
with open('private1.pem', 'wb') as f :
    f.write(keypair.exportKey())
公钥读取
from Crypto.PublicKey import RSA
with open("pubckey.pem","rb") as f:
    key = RSA.import_key(f.read())
    print('n = %d' % key.n)
    print('e = %d' % key.e)
私钥读取
from Crypto.PublicKey import RSA
with open("private1.pem","rb") as f:
    key = RSA.import_key(f.read())
    print('n = %d' % key.n)
    print('e = %d' % key.e)
    print('d = %d' % key.d)
    print('p = %d' % key.p)
    print('q = %d' % key.q)
出题脚本 -基于N分解的题目
import libnum
import gmpy2
from Crypto.PublicKey import RSA

p=libnum.generate_prime(1024)
#下一个素数
q=int(gmpy2.next_prime(p))
e=65537
m="flag{}"
m=libnum.s2n(m)
n=p*q
c=pow(m,e,n)
flag_c=libnum.n2s(c)
rsa_components = (n, e)
keypair = RSA.construct(rsa_components)
with open('pubckey1.pem', 'wb') as f :
    f.write(keypair.exportKey())
with open("flag.txt","wb") as f:
    f.write(flag_c)


解题脚本
import libnum
import gmpy2
from Crypto.PublicKey import RSA


def isqrt(n):
  x = n
  y = (x + n // x) // 2
  while y < x:
    x = y
    y = (x + n // x) // 2
  return x

def fermat(n, verbose=True):
    a = isqrt(n) # int(ceil(n**0.5))
    b2 = a*a - n
    b = isqrt(n) # int(b2**0.5)
    count = 0
    while b*b != b2:
        # if verbose:
        #     print('Trying: a=%s b2=%s b=%s' % (a, b2, b))
        a = a + 1
        b2 = a*a - n
        b = isqrt(b2) # int(b2**0.5)
        count += 1
    p=a+b
    q=a-b
    assert n == p * q
    # print('a=',a)
    # print('b=',b)
    # print('p=',p)
    # print('q=',q)
    # print('pq=',p*q)
    return p, q


with open("pubckey1.pem","rb") as f:
    key = RSA.import_key(f.read())
    n=key.n
    e=key.e

with open("flag.txt","rb") as f:
    c=f.read()
    c=libnum.s2n(c)

#费马分解,
n1=fermat(n)
p=n1[0]
q=n1[1]
phi_n=(p-1)*(q-1)
#求逆元
d=libnum.invmod(e,phi_n)
m=pow(c,d,n)
print(m)
print(libnum.n2s(int(m)).decode())

进阶——自动生成密钥及加解密
from Crypto.Cipher import PKCS1_v1_5
from Crypto import Random
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP


random_generator = Random.new().read
rsa = RSA.generate(2048, random_generator)

生成私钥

private_key = rsa.exportKey()

# print(private_key.decode('utf-8'))

with open('rsa_private_key.pem', 'wb')as f:
    f.write(private_key)

生成公钥

public_key = rsa.publickey().exportKey()

# print(public_key.decode('utf-8'))

with open('rsa_public_key.pem', 'wb')as f:
    f.write(public_key)


#测试用密钥加密
public_key = RSA.importKey(public_key)
msg='flag'
pk = PKCS1_v1_5.new(public_key)
encrypt_text = pk.encrypt(msg.encode())
print(encrypt_text)

#测试密钥解密
private_key = RSA.importKey(private_key)
pk = PKCS1_v1_5.new(private_key)
msg = pk.decrypt(encrypt_text,0)
print(msg)

#两种标准
rsa_components = (n, e, int(d), p, q)
arsa = RSA.construct(rsa_components)
rsakey = RSA.importKey(arsa.exportKey())
rsakey = PKCS1_OAEP.new(rsakey)
decrypted = rsakey.decrypt(c)
print(decrypted)

共模攻击脚本

解密脚本

#coding:utf-8
import gmpy2
import libnum

n= 
e1= 
c1= 
e2= 
c2= 

#共模攻击
#共模攻击函数
def rsa_gong_N_def(e1,e2,c1,c2,n):
    e1, e2, c1, c2, n=int(e1),int(e2),int(c1),int(c2),int(n)
    s = gmpy2.gcdext(e1, e2)
    s1 = s[1]
    s2 = s[2]
    if s1 < 0:
        s1 = - s1
        c1 = gmpy2.invert(c1, n)
    elif s2 < 0:
        s2 = - s2
        c2 = gmpy2.invert(c2, n)
    m = (pow(c1,s1,n) * pow(c2 ,s2 ,n)) % n
    return int(m)
m = rsa_gong_N_def(e1,e2,c1,c2,n)
print(m)
print(libnum.n2s(int(m)))

共模攻击原理
两个及以上的公钥(n,e)来加密同一条信息m

c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
e1,e2互质,则有

gcd(e1,e2)=1
根据扩展欧几里德算法 对于不完全为 0 的整数 a,b,gcd(a,b)表示 a,b 的最大公约数。那么一定存在整数 x,y 使得 gcd(a,b)=ax+by

e1*s1+e2*s2 = 1
s1、s2皆为整数,但是一正一负,假设s1为正数,s2为负数

因为

c1 = m^e1%n
c2 = m^e2%n
可得:

(c1^s1*c2^s2)%n = ((m^e1%n)^s1(m^e2%n)^s2)%n
根据模运算性质: 幂运算是一种关于幂的数学运算。同底数幂相乘,底数不变,指数相加。同底数幂相除,底数不变,指数相减。幂的乘方,底数不变,指数相乘。

(a * b) % p = (a % p * b % p) % p
a ^ b % p = ((a % p) ^ b) % p

简化公式为:

(c1^s1*c2^s2)%n = ((m^e1%n)^s1*(m^e2%n)^s2)%n

=> (c1^s1*c2^s2)%n = ((m^e1%n)^s1%n*(m^e2%n)^s2%n)%n #(a * b) % p = (a % p * b % p) % p

=> (c1^s1*c2^s2)%n = ((m^e1)^s1%n*(m^e2)^s2%n)%n #((a % p) ^ b) % p =a ^ b % p

=> (c1^s1*c2^s2)%n = ((m^e1)^s1*(m^e2)^s2)%n # (a % p * b % p) % p=(a * b) % p

=>(c1^s1*c2^s2)%n = ((m^(e1*s1)*(m^(e2*s2))%n #。幂的乘方,底数不变,指数相乘。

(c1^s1*c2^s2)%n = (m^(e1*s1+e2*s2))%n  # 同底数幂相乘,底数不变,指数相加。
因为 e1*s1+e2*s2 = 1 得:

(c1^s1*c2^s2)%n = (m^1)%n

(c1^s1*c2^s2)%n=m

同一m,同一n,不同e,进行加密。在不知道d的情况下,可以进行解密

wiener(维纳)攻击脚本

解密脚本
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= 
e= 
c= 

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

低加密指数广播攻击

import libnum
from gmpy2 import invert, gcd, iroot

def op(x):
    res = 1
    for i in x:
        res *= i
    return res

def CRT(m, a):
    assert (len(m) == len(a))
    M = op(m)
    sum = 0
    for m, a in zip(m, a):
        Mi = M // m
        ti = invert(Mi, m)
        sum += a * ti * Mi
    return sum % M
def GCRT(m, a):
    assert (len(m) == len(a))
    curm, cura = m[0], a[0]
    for m, a in zip(m[1:], a[1:]):
        d = gcd(curm, m)
        c = a - cura
        assert (c % d == 0)
        K = c // d * invert(curm // d, m // d)
        cura += curm * K
        curm = curm * m // d
    return cura % curm

e= 23
n= [, , , , , , ]
c= [, , , , , , ]

m = CRT(n, c)
m1 = iroot(m, e)  # 开e次方
print(m1)
print(libnum.n2s(int(m1[0])))

解密脚本2

import binascii,gmpy2
from functools import reduce

import libnum


def CRT(mi, ai):
    assert(reduce(gmpy2.gcd,mi)==1)
    assert (isinstance(mi, list) and isinstance(ai, list))
    M = reduce(lambda x, y: x * y, mi)
    ai_ti_Mi = [a * (M // m) * gmpy2.invert(M // m, m) for (m, a) in zip(mi, ai)]
    return reduce(lambda x, y: x + y, ai_ti_Mi) % M

e= 23
n= [, , , , , , ]
c= [, , , , , , ]

m=gmpy2.iroot(CRT(n, c), e)[0]
print(m)
print(libnum.n2s(int(m))) 

N不互素(共享素数)

解题脚本

import libnum
import gmpy2


e= 65537
n1= 
n2= 
c1= 
c2= 


#求最大公约数
q=gmpy2.gcd(n1,n2)
p1=n1//q

phi_n=(q-1)*(p1-1)
#求逆元d
d1=libnum.invmod(e,phi_n)
m=pow(c1,d1,n1)
print(m)
#数字转字节,转字符串
print(libnum.n2s(int(m)).decode()) 

dp泄露

解密脚本

#coding:utf-8
import libnum
import gmpy2

n= 
e= 65537
dp= 
c= 

for i in range(1,65535):
    p=(dp*e-1)//i+1
    if n%p==0:
        q=n//p
        break
print(p)
print(q)
phi_n= (p-1)*(q-1)
d=gmpy2.invert(e,phi_n)
m=pow(c,d,n)
print(m)
flag=libnum.n2s(int(m)).decode()
print(flag)

dp,dq

解题脚本

# coding=utf-8

import gmpy2
import libnum

def decrypt(dp,dq,p,q,c):
    InvQ = gmpy2.invert(q, p)
    mp = pow(c, dp, p)
    mq = pow(c, dq, q)
    m = (((mp-mq)*InvQ) % p)*q+mq
    print(libnum.n2s(int(m)).decode())

p= 
q= 
dq= 
dp= 
c= 


decrypt(dp,dq,p,q,c) 

n是p的r次方

解密脚本
先分解n

import libnum import gmpy2 
n=  
e= 65537 
c=  #分解n #yafu-x64.exe factor() p= 
phi_n=p**4-p**3 #求逆元 
d=libnum.invmod(e,phi_n) 
m=pow(c,d,n) 
print(m) #数字转字节,转字符串 
print(libnum.n2s(int(m)).decode())

RSA NC不互素

解题脚本

import gmpy2
import libnum

n = 
c = 
e = 0x10001
p = gmpy2.gcd(n, c)
q = n // p
assert n == p * q
phi_n=(p-1)*(q-1)
d=gmpy2.invert(e,phi_n)
M=pow(c,d,n)
#M= 2021 * 1001 * p*m
m=M//(2021 * 1001 * p)
print(libnum.n2s(int(m))) 

sage脚本_p高位攻击

脚本1

根据题目,注意 2^60  60需要修改相应的位数  a = (p >> 60) << 60

def phase3(high_p, n):
    R.<x> = PolynomialRing(Zmod(n), implementation='NTL')
    p = high_p + x
    x0 = p.small_roots(X = 2^60, beta = 0.1)[0]

    P = int(p(x0))
    Q = n // P
    print(P)
    print(Q)
    assert n == P*Q

n=
p4=
e=
c=

phase3(p4, n)

脚本2

n = 
p4=
e = 0x10001
pbits = 1024
kbits = pbits - p4.nbits()
print(p4.nbits())
p4 = p4 << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X=2^kbits, beta=0.4)
if roots:
    p = p4+int(roots[0])
    print ("n: ", n)
    print ("p: ", p)
    print ("q: ", n/p)

sage脚本_m高位攻击

解题脚本

import libnum
def phase2(high_m, n, c):
    R.<x> = PolynomialRing(Zmod(n), implementation='NTL')
    m = high_m + x
    M = m((m^3 - c).small_roots()[0])
    print(libnum.n2s(int(M)))

n= 
e= 3
c= 
high_m= 

phase2(high_m, n, c) 

sage脚本_Franklin-Reiter attack

#针对RSA的Franklin Reiter攻击

https://paper.seebug.org/727/#43-franklin-reiter


#如果两条消息之间仅存在已知的固定差异

m1 = bytes_to_long(flag)

m2 = a*m1 + b

#和RSA是否在相同的RSA模N下加密

#这样就有可能同时恢复它们



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

m1 = bytes_to_long(flag)
N = getPrime(512)*getPrime(512)
e = 17

c1 = pow(m1, e, N)

a = getRandomNBitInteger(512)
b = getRandomNBitInteger(512)
m2 = a*m1 + b
c2 = pow(m2, e, N)

print(N, a, b, c1, c2, sep="\n")

sage解题脚本

https://github.com/ValarDragon/CTF-Crypto/blob/master/RSA/FranklinReiter.sage

n=
a=
b=
c1=
c2=
e=17

import libnum
def franklinReiter(n,e,c1,c2,a,b):
    R.<X> = Zmod(n)[]
    f1 = X^e - c1
    f2 = (X*a+ b)^e - c2
    # coefficient 0 = -m, which is what we wanted!
    return Integer(n-(compositeModulusGCD(f1,f2)).coefficients()[0])

  # GCD is not implemented for rings over composite modulus in Sage

  # so we do our own implementation. Its the exact same as standard GCD, but with

  # the polynomials monic representation

def compositeModulusGCD(a, b):
    if(b == 0):
        return a.monic()
    else:
        return compositeModulusGCD(b, a % b)

m=franklinReiter(n,e,c1,c2,a,b)
print(m)
print(type(m))
print(libnum.n2s(int(m))) 

sage脚本_d 低位攻击

import libnum 
def getFullP(low_p, n): 
R.<x> = PolynomialRing(Zmod(n), implementation='NTL') 
p = x*2^512 + low_p 
root = (p-n).monic().small_roots(X = 2^128, beta = 0.4) 
if root: return p(root[0]) return None 
def phase4(low_d, n, c): 
maybe_p = [] 
for k in range(1, 4): 
p = var('p') 
p0 = solve_mod([3*p*low_d == p + k*(n*p - p^2 - n + p)], 2^512) 
maybe_p += [int(x[0]) 
for x in p0] #print(maybe_p) 
for x in maybe_p: 
P = getFullP(x, n) 
if P: 
break 
P = int(P) 
Q = n // P 
assert P*Q == n 
print(P) 
print(Q) 
d = inverse_mod(3, (P-1)*(Q-1)) 
print(d) 
print(libnum.n2s(int(power_mod(c, d, n)))) 
n =  
c =  
low_d =  
phase4(low_d, n, c) 

sage脚本_广播攻击

import libnum 
e=13 
n1=  
n2=  
n3=  
c1=  
c2=  
c3=  
def phase5(n1, c1, n2, c2, n3, c3): 
r = CRT([c1, c2, c3], [n1, n2, n3]) 
m = int(r)^(1/13) 
print(m) 
print(libnum.n2s(int(m))) 
phase5(n1, c1, n2, c2, n3, c3) 

sage脚本_Boneh Durfee 攻击

跟维纳攻击类似 用于e很大的情况

import time

"""
Setting debug to true will display more informations
about the lattice, the bounds, the vectors...
"""
debug = True

"""
Setting strict to true will stop the algorithm (and
return (-1, -1)) if we don't have a correct
upperbound on the determinant. Note that this
doesn't necesseraly mean that no solutions
will be found since the theoretical upperbound is
usualy far away from actual results. That is why
you should probably use `strict = False`
"""
strict = False

"""
This is experimental, but has provided remarkable results
so far. It tries to reduce the lattice as much as it can
while keeping its efficiency. I see no reason not to use
this option, but if things don't work, you should try
disabling it
"""
helpful_only = True
dimension_min = 7 # stop removing if lattice reaches that dimension

############################################

# Functions

##########################################

# display stats on helpful vectors

def helpful_vectors(BB, modulus):
    nothelpful = 0
    for ii in range(BB.dimensions()[0]):
        if BB[ii,ii] >= modulus:
            nothelpful += 1

    print (nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")

# display matrix picture with 0 and X

def matrix_overview(BB, bound):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d ' % ii)
        for jj in range(BB.dimensions()[1]):
            a += '0' if BB[ii,jj] == 0 else 'X'
            if BB.dimensions()[0] < 60:
                a += ' '
        if BB[ii, ii] >= bound:
            a += '~'
        print (a)

# tries to remove unhelpful vectors

# we start at current = n-1 (last vector)

def remove_unhelpful(BB, monomials, bound, current):
    # end of our recursive function
    if current == -1 or BB.dimensions()[0] <= dimension_min:
        return BB

    # we start by checking from the end
    for ii in range(current, -1, -1):
        # if it is unhelpful:
        if BB[ii, ii] >= bound:
            affected_vectors = 0
            affected_vector_index = 0
            # let's check if it affects other vectors
            for jj in range(ii + 1, BB.dimensions()[0]):
                # if another vector is affected:
                # we increase the count
                if BB[jj, ii] != 0:
                    affected_vectors += 1
                    affected_vector_index = jj
    
            # level:0
            # if no other vectors end up affected
            # we remove it
            if affected_vectors == 0:
                print ("* removing unhelpful vector", ii)
                BB = BB.delete_columns([ii])
                BB = BB.delete_rows([ii])
                monomials.pop(ii)
                BB = remove_unhelpful(BB, monomials, bound, ii-1)
                return BB
    
            # level:1
            # if just one was affected we check
            # if it is affecting someone else
            elif affected_vectors == 1:
                affected_deeper = True
                for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
                    # if it is affecting even one vector
                    # we give up on this one
                    if BB[kk, affected_vector_index] != 0:
                        affected_deeper = False
                # remove both it if no other vector was affected and
                # this helpful vector is not helpful enough
                # compared to our unhelpful one
                if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
                    print ("* removing unhelpful vectors", ii, "and", affected_vector_index)
                    BB = BB.delete_columns([affected_vector_index, ii])
                    BB = BB.delete_rows([affected_vector_index, ii])
                    monomials.pop(affected_vector_index)
                    monomials.pop(ii)
                    BB = remove_unhelpful(BB, monomials, bound, ii-1)
                    return BB
    # nothing happened
    return BB

"""
Returns:

* 0,0   if it fails

* -1,-1 if `strict=true`, and determinant doesn't bound

* x0,y0 the solutions of `pol`
  """
  def boneh_durfee(pol, modulus, mm, tt, XX, YY):
    """
    Boneh and Durfee revisited by Herrmann and May

    finds a solution if:

    * d < N^delta
    * |x| < e^delta
    * |y| < e^0.5
      whenever delta < 1 - sqrt(2)/2 ~ 0.292
        """

    # substitution (Herrman and May)

    PR.<u, x, y> = PolynomialRing(ZZ)
    Q = PR.quotient(x*y + 1 - u) # u = xy + 1
    polZ = Q(pol).lift()

    UU = XX*YY + 1

    # x-shifts

    gg = []
    for kk in range(mm + 1):
        for ii in range(mm - kk + 1):
            xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk
            gg.append(xshift)
    gg.sort()

    # x-shifts list of monomials

    monomials = []
    for polynomial in gg:
        for monomial in polynomial.monomials():
            if monomial not in monomials:
                monomials.append(monomial)
    monomials.sort()

    # y-shifts (selected by Herrman and May)

    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk)
            yshift = Q(yshift).lift()
            gg.append(yshift) # substitution

    # y-shifts list of monomials

    for jj in range(1, tt + 1):
        for kk in range(floor(mm/tt) * jj, mm + 1):
            monomials.append(u^kk * y^jj)

    # construct lattice B

    nn = len(monomials)
    BB = Matrix(ZZ, nn)
    for ii in range(nn):
        BB[ii, 0] = gg[ii](0, 0, 0)
        for jj in range(1, ii + 1):
            if monomials[jj] in gg[ii].monomials():
                BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)

    # Prototype to reduce the lattice

    if helpful_only:
        # automatically remove
        BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1)
        # reset dimension
        nn = BB.dimensions()[0]
        if nn == 0:
            print ("failure")
            return 0,0

    # check if vectors are helpful

    if debug:
        helpful_vectors(BB, modulus^mm)

    # check if determinant is correctly bounded

    det = BB.det()
    bound = modulus^(mm*nn)
    if det >= bound:
        print ("We do not have det < bound. Solutions might not be found.")
        print ("Try with highers m and t.")
        if debug:
            diff = (log(det) - log(bound)) / log(2)
            print ("size det(L) - size e^(m*n) = ", floor(diff))
        if strict:
            return -1, -1
    else:
        print ("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")

    # display the lattice basis

    if debug:
        matrix_overview(BB, modulus^mm)

    # LLL

    if debug:
        print ("optimizing basis of the lattice via LLL, this can take a long time")

    BB = BB.LLL()

    if debug:
        print ("LLL is done!")

    # transform vector i & j -> polynomials 1 & 2

    if debug:
        print ("looking for independent vectors in the lattice")
    found_polynomials = False

    for pol1_idx in range(nn - 1):
        for pol2_idx in range(pol1_idx + 1, nn):
            # for i and j, create the two polynomials
            PR.<w,z> = PolynomialRing(ZZ)
            pol1 = pol2 = 0
            for jj in range(nn):
                pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY)
                pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)

            # resultant
            PR.<q> = PolynomialRing(ZZ)
            rr = pol1.resultant(pol2)
      
            # are these good polynomials?
            if rr.is_zero() or rr.monomials() == [1]:
                continue
            else:
                print ("found them, using vectors", pol1_idx, "and", pol2_idx)
                found_polynomials = True
                break
        if found_polynomials:
            break

    if not found_polynomials:
        print ("no independant vectors could be found. This should very rarely happen...")
        return 0, 0

    rr = rr(q, q)

    # solutions

    soly = rr.roots()

    if len(soly) == 0:
        print ("Your prediction (delta) is too small")
        return 0, 0

    soly = soly[0][0]
    ss = pol1(q, soly)
    solx = ss.roots()[0][0]

    #
    return solx, soly

def example():
    ############################################
    # How To Use This Script
    ##########################################

    #
    # The problem to solve (edit the following values)
    #
    
    # the modulus
    N = 
    # the public exponent
    e = 
    
    # the hypothesis on the private exponent (the theoretical maximum is 0.292)
    delta = 0.280 # this means that d < N^delta
    
    #
    # Lattice (tweak those values)
    #
    
    # you should tweak this (after a first run), (e.g. increment it until a solution is found)
    m = 4 # size of the lattice (bigger the better/slower)
    
    # you need to be a lattice master to tweak these
    t = int((1-2*delta) * m)  # optimization from Herrmann and May
    X = 2*floor(N^delta)  # this _might_ be too much
    Y = floor(N^(1/2))    # correct if p, q are ~ same size
    
    #
    # Don't touch anything below
    #
    
    # Problem put in equation
    P.<x,y> = PolynomialRing(ZZ)
    A = int((N+1)/2)
    pol = 1 + x * (A + y)
    
    #
    # Find the solutions!
    #
    
    # Checking bounds
    if debug:
        print ("=== checking values ===")
        print ("* delta:", delta)
        print ("* delta < 0.292", delta < 0.292)
        print ("* size of e:", int(log(e)/log(2)))
        print ("* size of N:", int(log(N)/log(2)))
        print ("* m:", m, ", t:", t)
    
    # boneh_durfee
    if debug:
        print ("=== running algorithm ===")
        start_time = time.time()
    
    solx, soly = boneh_durfee(pol, e, m, t, X, Y)
    
    # found a solution?
    if solx > 0:
        print ("=== solution found ===")
        if False:
            print ("x:", solx)
            print ("y:", soly)
    
        d = int(pol(solx, soly) / e)
        print ("private key found:", d)
    else:
        print ("=== no solution was found ===")
    
    if debug:
        print("=== %s seconds ===" % (time.time() - start_time))

if __name__ == "__main__":
    example()

sage脚本_维纳变形(三素数pqr)

这一段代码求d

def wiener(e, n):
    m = 12345
    c = pow(m, e, n)
    q0 = 1
    list1 = continued_fraction(Integer(e) / Integer(n))
    conv = list1.convergents()
    for i in conv:
        k = i.numerator()
        q1 = i.denominator()
        for r in range(20):
            for s in range(20):
                d = r * q1 + s * q0
                m1 = pow(c, d, n)
                if m1 == m:
                    return d
        q0 = q1

c = 
e = 
n = 

d=wiener(e, n)
print(d)
这一段代码是完整求flag的

from Crypto.Util.number import *
import gmpy2
import math
import libnum

c = 
e = 
n = 

def plus(e, n):
    m = 2
    c = pow(m, e, n)
    q0 = 1

list1 = continued_fraction(Integer(e)/Integer(n))
conv = list1.convergents()
for i in conv:
    k = i.numerator()
    #print(k)
    q1 = i.denominator()
    #print(q1)

for r in range(20):
    for s in range(20):
        d = r*q1 + s*q0
        m1 = pow(c, d, n)
        if m1 == m:
            print(r,s)
            return d

q0 = q1

d = plus(e, n)
print(d)
print(libnum.n2s(int(pow(c,d,n)))) 

PEM证书格式

  • 证书解Base64后再转换为16进制输出

    from base64 import b64decode
    import binascii
    
    s = '''MIICWwIBAAKBgHBkeHn6Q67opdN4V1S3mI0SsUuYzzm+IbXZDz4yZOMWz5nDBYuJ
    SA8rRqDtqb7mtNdTGZZx7xe6tOwleqvkXn629mgUZZegyaBdBSPnUR6IUqduqpLo
    HRavrHr1IkI6oAmDEQzi1lCZ03x0jMKuoOKp9LBhP9ijCoy9iRh9tH+FAgMBAAEC
    gYAvLn5E9oKjUpcKh2Jh9hDcaBR1n9iebOrJ5C059v3TNyg/bFdPlHnjpE8qD5tK
    wJ76JbCAL6QnWgHJgJJWxq/EAy/9SG+eApaBo94Sb2B2A1WceDf8F1idkXUOvU/3
    kd/wbw/gLZLya8WCFF4SUZx09TToMqSWDEJI4kN17pU5AQJBAJv9ShfSbaMNK31O
    kg9LSI7wFLq7iiFRl5kXvSKLsYB3HAKHNlV6/ZL1TV2jg37yf9Mi2f0Gx5AVXbwi
    /1ef9R0CQQC4c5EkR8VAw8lqePLwCkCJisXKAEOqPZFOiSCCIVnY+5J4kgiZiS33
    rskWwsYAIBHVKiXSy+5NdvWk51MeYi+JAkBiZNvmuOJVVkpXaUcyhH9JQmEhBIj1
    yVzBwbqY3trhOMCfS6DXPJRUrYzWgvzAB8Dfcn1kYHFjDkcpFD5SjGB1AkBtyKNH
    w8v820tjqu91vbRh6Q4GSBf+GL0G0IlfyrfudPXd+5VQxRxuAkM/39f3tR7IEFkI
    2UZSJw7YArMvL2N5AkEAmVGTH6DU3ygzjCtdl4/2dhonSHcEovCFWGZuCqBjYEw6
    IGYAlpOiv/BICMXrOBsdd1+4j6n1edxHSGH9q4Aoug=='''
    
    s = b64decode(s)
    
    print(binascii.hexlify(s))
    

    得到

    3082025b02010002818070647879fa43aee8a5d3785754b7988d12b14b98cf39be21b5d90f3e3264e316cf99c3058b89480f2b46a0eda9bee6b4d753199671ef17bab4ec257aabe45e7eb6f668146597a0c9a05d0523e7511e8852a76eaa92e81d16afac7af522423aa00983110ce2d65099d37c748cc2aea0e2a9f4b0613fd8a30a8cbd89187db47f8502030100010281802f2e7e44f682a352970a876261f610dc6814759fd89e6ceac9e42d39f6fdd337283f6c574f9479e3a44f2a0f9b4ac09efa25b0802fa4275a01c9809256c6afc4032ffd486f9e029681a3de126f607603559c7837fc17589d91750ebd4ff791dff06f0fe02d92f26bc582145e12519c74f534e832a4960c4248e24375ee9539010241009bfd4a17d26da30d2b7d4e920f4b488ef014babb8a2151979917bd228bb180771c028736557afd92f54d5da3837ef27fd322d9fd06c790155dbc22ff579ff51d024100b873912447c540c3c96a78f2f00a40898ac5ca0043aa3d914e8920822159d8fb9278920899892df7aec916c2c6002011d52a25d2cbee4d76f5a4e7531e622f8902406264dbe6b8e255564a57694732847f494261210488f5c95cc1c1ba98dedae138c09f4ba0d73c9454ad8cd682fcc007c0df727d646071630e4729143e528c607502406dc8a347c3cbfcdb4b63aaef75bdb461e90e064817fe18bd06d0895fcab7ee74f5ddfb9550c51c6e02433fdfd7f7b51ec8105908d94652270ed802b32f2f63790241009951931fa0d4df28338c2b5d978ff6761a27487704a2f08558666e0aa063604c3a2066009693a2bff04808c5eb381b1d775fb88fa9f579dc474861fdab8028ba
    

    这便是原始的ASN.1格式内容,首先我们要知道ASN.1是一种用来描述数据结构的抽象语法,它并不是只用来存储密钥,在ASN.1中你可以自定义你的数据类型和数值约束等条件,你可以把它理解为一种序列化数据的格式。其中数据格式如下

    数据 长度 名称 含义
    30 1 标记符 代表ASN.1结构的开始
    82 1 长度类型 代表后面跟着一个双字节长度
    025b 2 长度 代表后续内容的总长度为603字节
    02 1 类型 代表整型
    01 1 长度 代表1字节
    00 1 代表整数0
    02 1 类型 代表整型
    81 1 长度类型 代表后面跟着一个单字节长度
    80 1 长度 代表数据长度为128字节
    128 数据值1

    以此往复,所以除了最开始的标识符外,后续的内容都是由

    类型 + 长度 + 构成的,而这些值根据他们出现的位置不同有着不同的含义,例如最开始出现的值0在PEM中代表版本号信息。

    随后的数据值1代表模数。完整顺序如下

    版本
    模数 - n
    加密指数 - e
    解密指数 - d
    素因子1 - p
    素因子2 - q
    指数1 - dp
    指数2 - dq
    系数 - invert(q, p)
    其他额外信息
    

    在了解了该格式后我们就能对上面的16进制数据直接分段了

    标识头 30
    总长度 82 025b
    版本信息 0201 00
    n 028180 70647879fa43aee8a5d3785754b7988d12b14b98cf39be21b5d90f3e3264e316cf99c3058b89480f2b46a0eda9bee6b4d753199671ef17bab4ec257aabe45e7eb6f668146597a0c9a05d0523e7511e8852a76eaa92e81d16afac7af522423aa00983110ce2d65099d37c748cc2aea0e2a9f4b0613fd8a30a8cbd89187db47f85
    e 0203 010001
    d 028180 2f2e7e44f682a352970a876261f610dc6814759fd89e6ceac9e42d39f6fdd337283f6c574f9479e3a44f2a0f9b4ac09efa25b0802fa4275a01c9809256c6afc4032ffd486f9e029681a3de126f607603559c7837fc17589d91750ebd4ff791dff06f0fe02d92f26bc582145e12519c74f534e832a4960c4248e24375ee953901
    p 0241 009bfd4a17d26da30d2b7d4e920f4b488ef014babb8a2151979917bd228bb180771c028736557afd92f54d5da3837ef27fd322d9fd06c790155dbc22ff579ff51d
    q 0241 00b873912447c540c3c96a78f2f00a40898ac5ca0043aa3d914e8920822159d8fb9278920899892df7aec916c2c6002011d52a25d2cbee4d76f5a4e7531e622f89
    dp 0240 6264dbe6b8e255564a57694732847f494261210488f5c95cc1c1ba98dedae138c09f4ba0d73c9454ad8cd682fcc007c0df727d646071630e4729143e528c6075
    dq 0240 6dc8a347c3cbfcdb4b63aaef75bdb461e90e064817fe18bd06d0895fcab7ee74f5ddfb9550c51c6e02433fdfd7f7b51ec8105908d94652270ed802b32f2f6379
    inv(q,p) 0241 009951931fa0d4df28338c2b5d978ff6761a27487704a2f08558666e0aa063604c3a2066009693a2bff04808c5eb381b1d775fb88fa9f579dc474861fdab8028ba
    

    现在回到本题我们也先进行base64解码得到,因为这里是密钥的后半截,所以我们不能从前往后直接解析,需要先找到一个定位锚点,我们可以按照02先给数据初步分段

    3a1d7b10ba7f9f652b9ea83f81a15b2961e00cd63374f346a8d78f81dad1b697f3abe8eced0
    02260d89f2d12bc9395c233012b6f744a380d1d0aed78c9fb52a28d95f858c630bd3b164e857b406f541311426d64d5f0b6e0d1
    02818100befff9907f75bb7ad561131b5c76ae137bd67ae0e32b90f92b997b044277cab3dfeb84f255138127e1a4e53751a68db743a00ed8acc58f33107fe35db6b4813bc048db48bd530bcb35fba434dbb70e27d78aede2de0d4745df35a245417b8c74a31a7b55a77db45ebd6ed1dc4b3dcaa435a79dbf7240d96775372e64b58b0803
    02818077a554614c111b51dea903a8e8222be795b45948805fc6f5ea67e60ad493f117b3033ea2ee84d87c0a29a87ea38908a93e313e08fe83dc91ba8695ba969d40f243addff620ee40bda8562ff5389661efd8b9d5976bacf2bc9a1cfc54d7704c7098441b1e7253760fc7dbcef7a417082e7492e8e0808f34d830c772e800714f41
    0281801c1005fdea0c454075eb6e603dc49e2cf4abfd9fdf20be8b2d91be5650e1c2e18ccbd0dbbe0e4092b87f7ec212f812a8538247cc240e5eccd4e6c564367cece3f78b7cd482249a7dffef7a1fde0c56431a532a4283f7957a39a26ab61c39e7d81742c3ce40eea23aad40840b06ef0c3ff6362b623e8a32a715bcc6cf3b31333b
    028181008488efbea72e9abac7f71085b86e9071bece170f8c92a387aebdcc89f8915c33739609a73cacd5559b3a56fd59082ed311bab49f42ea0ba6be5e253453db0fc8b5b6aab458163b8a013121fd5c554dcc51d81c57e60f59d9d7f8f4d45fab24365da039ed8fb5401cfaff0c8aae2191ae8bd742351d11034ff0f0c32fb0586810
    

    不一定数据中出现了02就代表是数据开始的地方,因为也有可能数据中也包含02,我们要一一检验02后面的长度标识定义的长度时候符合后续数据的长度,我们会发现第一块后面的长度标识以及长度都不符合正常的定义,所以其实第一块这里的02是上一块数据中的内容而非新数据的开始标识。最终我们可以得到

    3a1d7b10ba7f9f652b9ea83f81a15b2961e00cd63374f346a8d78f81dad1b697f3abe8eced002260d89f2d12bc9395c233012b6f744a380d1d0aed78c9fb52a28d95f858c630bd3b164e857b406f541311426d64d5f0b6e0d1
    q 028181 00befff9907f75bb7ad561131b5c76ae137bd67ae0e32b90f92b997b044277cab3dfeb84f255138127e1a4e53751a68db743a00ed8acc58f33107fe35db6b4813bc048db48bd530bcb35fba434dbb70e27d78aede2de0d4745df35a245417b8c74a31a7b55a77db45ebd6ed1dc4b3dcaa435a79dbf7240d96775372e64b58b0803
    dp 028180 77a554614c111b51dea903a8e8222be795b45948805fc6f5ea67e60ad493f117b3033ea2ee84d87c0a29a87ea38908a93e313e08fe83dc91ba8695ba969d40f243addff620ee40bda8562ff5389661efd8b9d5976bacf2bc9a1cfc54d7704c7098441b1e7253760fc7dbcef7a417082e7492e8e0808f34d830c772e800714f41
    dq 028180 1c1005fdea0c454075eb6e603dc49e2cf4abfd9fdf20be8b2d91be5650e1c2e18ccbd0dbbe0e4092b87f7ec212f812a8538247cc240e5eccd4e6c564367cece3f78b7cd482249a7dffef7a1fde0c56431a532a4283f7957a39a26ab61c39e7d81742c3ce40eea23aad40840b06ef0c3ff6362b623e8a32a715bcc6cf3b31333b
    inv(q,p) 028181 008488efbea72e9abac7f71085b86e9071bece170f8c92a387aebdcc89f8915c33739609a73cacd5559b3a56fd59082ed311bab49f42ea0ba6be5e253453db0fc8b5b6aab458163b8a013121fd5c554dcc51d81c57e60f59d9d7f8f4d45fab24365da039ed8fb5401cfaff0c8aae2191ae8bd742351d11034ff0f0c32fb0586810
    

    我们发现有用的数据为q,dp,dq,inv(q,p)

from Crypto.Util.number import *

q = 0x00befff9907f75bb7ad561131b5c76ae137bd67ae0e32b90f92b997b044277cab3dfeb84f255138127e1a4e53751a68db743a00ed8acc58f33107fe35db6b4813bc048db48bd530bcb35fba434dbb70e27d78aede2de0d4745df35a245417b8c74a31a7b55a77db45ebd6ed1dc4b3dcaa435a79dbf7240d96775372e64b58b0803
dq = 0x1c1005fdea0c454075eb6e603dc49e2cf4abfd9fdf20be8b2d91be5650e1c2e18ccbd0dbbe0e4092b87f7ec212f812a8538247cc240e5eccd4e6c564367cece3f78b7cd482249a7dffef7a1fde0c56431a532a4283f7957a39a26ab61c39e7d81742c3ce40eea23aad40840b06ef0c3ff6362b623e8a32a715bcc6cf3b31333b
c = 2329206064672111950904450292941421573350591294207157652026787098178545948258554492347649016030892000747909819064473414536692222493030122267884839986067073054508582403564557167583565364976046083954888777809177108315052118912603290095925912298584322873410379937455462434313487981715516761071523410121549134193124709612876311518391130974466069686830456036397449773159386026998482557500868323733155606973727191287617806211911722356975478414165867941665666556476756617951672736466672410799762479373101996896644454778482896784598378016390592459460753042458284030795009957030383305268628413551730442224404807955926606496353

m = pow(c, dq, q)

print(long_to_bytes(m))


## openssl 格式

直接输入`openssl help`你会发现打印出来了命令列表

Standard commands
asn1parse ca ciphers cms
crl crl2pkcs7 dgst dhparam
dsa dsaparam ec ecparam
enc engine errstr gendsa
genpkey genrsa help list
nseq ocsp passwd pkcs12
pkcs7 pkcs8 pkey pkeyparam
pkeyutl prime rand rehash
req rsa rsautl s_client
s_server s_time sess_id smime
speed spkac srp storeutl
cast-cbc cast5-cbc cast5-cfb cast5-ecb
cast5-ofb des des-cbc des-cfb
des-ecb des-ede des-ede-cbc des-ede-cfb
des-ede-ofb des-ede3 des-ede3-cbc des-ede3-cfb
des-ede3-ofb des-ofb des3 desx
idea idea-cbc idea-cfb idea-ecb
idea-ofb rc2 rc2-40-cbc rc2-64-cbc
rc2-cbc rc2-cfb rc2-ecb rc2-ofb
rc4 rc4-40 seed seed-cbc
seed-cfb seed-ecb seed-ofb sm4-cbc
sm4-cfb sm4-ctr sm4-ecb sm4-ofb






这里的每一项都代表特定的算法或者证书格式,而我们这里涉及的是`rsa`,所以我们使用`openssl rsa -help`进一步查看帮助文档

Usage: rsa [options]
Valid options are:
-help Display this summary 查看帮助
-inform format Input format, one of DER PEM 指定输入格式
-outform format Output format, one of DER PEM PVK 指定输出格式
-in val Input file 输入文件
-out outfile Output file 输出文件
-pubin Expect a public key in input file 期望输入时一个公钥
-pubout Output a public key 输出公钥文件
-passout val Output file pass phrase source 给输出文件设置密码
-passin val Input file pass phrase source 输入文件的密码
-RSAPublicKey_in Input is an RSAPublicKey 指定输入是一个RSA公钥
-RSAPublicKey_out Output is an RSAPublicKey 指定输出是一个RSA公钥
-noout Don't print key out 不要打印输入的密钥内容
-text Print the key in text 用文本格式打印密钥内容
-modulus Print the RSA key modulus 打印RSA密钥的模数
-check Verify key consistency 检测密钥是否一致
-* Any supported cipher 其他参数
-pvk-strong Enable 'Strong' PVK encoding level (default) 启用“强”PVK编码级别(默认)
-pvk-weak Enable 'Weak' PVK encoding level 启用“弱”PVK编码级别
-pvk-none Don't enforce PVK encoding 不强制执行PVK编码
-engine val Use engine, possibly a hardware device 指定解析引擎




这里列出了和`rsa`证书有关的项,后面中文内容是我额外添加的释义,那么我们要查看密钥内容的话直接

openssl rsa -in key.pem -inform PEM


会发现他将密钥内容又打印了一遍,这是因为它默认就是只做解析不会有其他操作,我们需要具体指定我们想要的操作,例如`-text`以文本内容输出参数,

openssl rsa -in key.pem -inform PEM -text


此时我们得到输出

RSA Private-Key: (1023 bit, 2 primes)
modulus:
70:64:78:79:fa:43:ae:e8:a5:d3:78:57:54:b7:98:
8d:12:b1:4b:98:cf:39:be:21:b5:d9:0f:3e:32:64:
e3:16:cf:99:c3:05:8b:89:48:0f:2b:46:a0:ed:a9:
be:e6:b4:d7:53:19:96:71:ef:17:ba:b4:ec:25:7a:
ab:e4:5e:7e:b6:f6:68:14:65:97:a0:c9:a0:5d:05:
23:e7:51:1e:88:52:a7:6e:aa:92:e8:1d:16:af:ac:
7a:f5:22:42:3a:a0:09:83:11:0c:e2:d6:50:99:d3:
7c:74:8c:c2:ae:a0:e2:a9:f4:b0:61:3f:d8:a3:0a:
8c:bd:89:18:7d:b4:7f:85
publicExponent: 65537 (0x10001)
privateExponent:
2f:2e:7e:44:f6:82:a3:52:97:0a:87:62:61:f6:10:
dc:68:14:75:9f:d8:9e:6c:ea:c9:e4:2d:39:f6:fd:
d3:37:28:3f:6c:57:4f:94:79:e3:a4:4f:2a:0f:9b:
4a:c0:9e:fa:25:b0:80:2f:a4:27:5a:01:c9:80:92:
56:c6:af:c4:03:2f:fd:48:6f:9e:02:96:81:a3

标签:总结,__,.__,http,chr,CTF,print,import
From: https://www.cnblogs.com/huicry/p/18188139

相关文章

  • rdp利用技巧总结
    近期在项目中管理员在rdp挂载之后搞掉了管理员,想着有时间就整理下针对rdp的利用方法。针对挂盘的利用方法复制文件这个不多说,可以根据的不同的挂盘来决定是拖文件还是放启动项。有一些自动文件监控和拷贝的应用,如:https://github.com/cnucky/DarkGuardianDarkGuardian是一款用于监......
  • 软考知识点总结
    第一章计算机组成,操作系统CPU:运算器,控制器PU(中央处理器,CentralProcessingUnit)是计算机系统中负责执行程序指令和数据运算的核心部件。一个典型的CPU通常包括以下几个主要组成部分:   控制单元:控制单元负责从内存中获取待执行的指令并解码、译码。它还负责生成相应的操作......
  • 蓝桥杯大赛单片机比赛经验总结
    蓝桥杯大赛单片机比赛经验总结适当的延时很重要,可以解决一些不正常现象ds1302读取的时间是BCD码,操作时间时换成10进制操作例:(shi/16)*10+shi%16每次只接受和发送一个字符,字符用单引号‘’字符串用双引号“”if(SBUF==‘a’)而不是if(SBUF=="a")总中......
  • (非原创)Stable Diffusion 提示词prompt tag语法总结
    基本认知提示词会相互污染,要尽可能地做减法。XL版本主推使用自然语言使用注释将修饰词汇限定给某个主体,避免提示词污染1girl(silverlonghair,purpleeyes),yellowsuit2people(1girlAND1boy)2characters(1girlAND1dog)权重调整旧语法:(){}加大权重,[]......
  • [红明谷CTF 2021]write_shell
    [红明谷CTF2021]write_shell打开环境直接给出源代码<?phperror_reporting(0);highlight_file(__FILE__);functioncheck($input){if(preg_match("/'||_|php|;|~|\\^|\\+|eval|{|}/i",$input)){//if(preg_match("/'||_|=|php/",......
  • 考点总结
    一、图的基本运算代数运算加运算:C(x,y)=A(x,y)+B(x,y),其中C(x,y)为输出图像,A(x,y)、B(x,y)为输入图像。重要应用是对所获取的同一场景的多幅图像求平均,常常用来有效的削弱图像的加性随机噪声。减运算:C(x,y)=A(x,y)-B(x,y),其中C(x,y)为输出图像,A(x,y)、B(x,y)为输入......
  • 音视频播放异常现象总结
    播放卡顿或者卡住:1流媒体不发流给客户端,客户端停在当前画面不动也不销毁,也不重拉流;2弱网环境,tcp乱序,且发包间隔时间比较大,播放器收一包耗时较多,导致解码异常卡主;3流媒体(发流端)数据插入一些增强帧,其他的P帧等(一般是某些公司的定制)导致播放器得到的数据不是一个连续的GOP;解码......
  • buuctf-pwn-ciscn_2019_es_2
    checksecida我们看到在vul函数中,有两个read函数,每个都读取了0x30(48)大小的字符,并放入字符数组s中,也就是说我们能溢出的只有8个字节,刚好覆盖到ebp和返回地址所以我们需要栈迁移,使我们能溢出更多字节首先利用第一个read,输入40字节的数据,刚好覆盖到ebp,然后printf就会顺带打印......
  • salesforce零基础学习(一百三十六)零碎知识点小总结(八)
    本篇参考:SalesforceLWC学习(七)Navigation&Toasthttps://developer.salesforce.com/docs/platform/lwc/guide/use-navigate-url-addressable.htmlhttps://help.salesforce.com/s/articleView?id=release-notes.rn_lwc_UrlAddressable.htm&release=250&type=5Sal......
  • NewStarCTF 2023 week1 writeup
    NewStarCTF2023week1writeup花了几天时间,终于把week1的题目做完了,还是学到不少东西的,题目质量大多都挺高的,很适合新手入门。Web1.泄漏的秘密url/robots.txt查看robots协议,找到第一部分的flagPARTONE:flag{r0bots_1s_s0_us3fulurl/www.zip查看网站备份,找到第二部分的fla......