Crypto常用的python库

常用库函数功能

gmpy2

  • 安装指令:pip install gmpy2

  • 使用场景:一些大整数运算,特别是在RSA中。

    • 初始化大整数

      1
      2
      3
      4
      import gmpy2
      gmpy2.mpz(909090)

      result:mpz(909090)
    • 求大整数a,b的最大公因数

      1
      2
      3
      4
      import gmpy2
      gmpy2.gcd(6,18)

      result:mpz(6)
    • 求大整数x模m的逆元y

      1
      2
      3
      4
      5
      import gmpy2
      #4*6 ≡ 1 mod 23
      gmpy2.invert(4,23)

      result:mpz(6)
    • 检验大整数是否为偶数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      import gmpy2
      gmpy2.is_even(6)

      result:True

      -----------
      import gmpy2
      gmpy2.is_even(7)

      result:False
    • 检验大整数是否为奇数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      import gmpy2
      gmpy2.is_odd(6)

      result:False

      -----------
      import gmpy2
      gmpy2.is_odd(7)

      result:True
    • 检验大整数是否为素数

      1
      2
      3
      4
      import gmpy2
      gmpy2.is_prime(5)

      result:True
    • 求大整数x开n次根

      1
      2
      3
      4
      import gmpy2
      gmpy2.iroot(81,2)

      result:(mpz(9),True)
    • 求大整数x的y次幂模m取余(主要用于RSA)

      1
      2
      3
      4
      5
      import gmpy2
      #2^4 mod 5
      gmpy2.powmod(2,4,15)

      result:mpz(1)

pwntools

  • 安装指令:pip install pwntools

  • 使用场景: 不仅是在Pwn方向上的神器,pwntools在Crypto中也能用来绕过pow(proof of work)共识机制、向提供的ip端口发送payload以及快速编写exp。

    • 基础用法

      首先就是导入包

      1
      from pwn import *

      你将在全局空间里引用pwntools的所有函数。现在可以用一些简单函数进行汇编反汇编packunpack等等操作。
      将包导入后,我一般都会设置日志记录级别,方便出现问题的时候排查错误

      1
      context.log_level = 'debug'

      这样设置后,通过管道发送和接收的数据都会被打印在屏幕上。
      然后就是连接了,一般题目都会给你一个ip和一个端口,让你用nc连接访问,也有的题是让你通过ssh连接,这两种方式都可以通过pwntools实现。

      1
      2
      3
      4
      5
      6
      # 第一种连接方式,通过ip和port去连接
      conn = remote('127.0.0.1', 8888)
      # 第二种连接方式,通过ssh连接
      shell = ssh(host='192.168.14.144', user='root', port=2222, password='123456')
      # 也可将可执行文件下载到本地进行调试
      conn = process('./test')

      在编写exp时,最常见的工作就是在整数之间转换,而且转换后,它们的表现形式就是一个字节序列,pwntools提供了打包函数

      1
      2
      p32/p64: 打包一个整数,分别打包为32位或64位
      u32/u64: 解包一个字符串,得到整数

      具体用法

      1
      2
      3
      # 比如将0xdeadbeef进行32位的打包,将会得到'\xef\xbe\xad\xde'(小端序)
      payload = p32(0xdeadbeef) #pack 32 bits number
      payload = p64(0xdeadbeef) #pack 64 bits number

      打包的时候要指定程序是32位还是64位的,他们之间打包后的长度是不同的。
      建立连接后就可以发送和接收数据了。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      conn.send(data) #发送数据
      conn.sendline(data) #发送一行数据,相当于在数据后面加\n
      #接收数据,numb指定接收的字节,timeout指定超时
      conn.recv(numb = 2048, timeout = default)
      #接受一行数据,keepends为是否保留行尾的\n
      conn.recvline(keepends=True)
      #接受数据直到我们设置的标志出现
      conn.recvuntil("Hello,World\n",drop=fasle)
      conn.recvall() #一直接收直到 EOF
      conn.recvrepeat(timeout = default) #持续接受直到EOF或timeout
      #直接进行交互,相当于回到shell的模式,在取得shell之后使用
      conn.interactive()

      一般来说做Crypto题目时通过nc连接即可,如果是通过nc连接的话,一进去就相当于开启了一个进程,你只需要发送数据和程序交互就行了。
      如果是通过ssh连接进去的,你需要手动创建一个进程,就跟正常通过ssh连接一样,你需要打开一个程序。
      比如:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      >>>shell = ssh(host='192.168.14.144', user='root', port=2222, password='123456')
      # 也可以用shell.process('/bin/sh') 来实现,但是前提是服务器有python2的 interpreter,否则会报错,优先使用shell.run()
      >>> sh = shell.run('/bin/sh') # 创建进程,这里开了一个shell
      >>> sh.sendline('sleep 3; echo hello world;') # 发送命令
      >>> sh.recvline(timeout=1) # 接收数据
      ''
      >>> sh.recvline(timeout=5)
      'hello world\n'
      >>> sh.close() # 关闭进程
    • 绕过pow共识机制:

      本质就是去爆破前四位拿到相同的sha256结果,在Crypto题目中比较常用,一些新手可能会被难住

      以下是通用模板:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      import binascii
      from pwn import remote
      import string
      import itertools
      from hashlib import sha256
      from pwn import *
      #定义字母表
      table = string.ascii_letters+string.digits
      #定义PoW函数
      def PoW(hash_value, part):
      alphabet = string.ascii_letters + string.digits
      for x in itertools.product(alphabet, repeat=4):
      nonce = ''.join(x)
      if sha256((nonce + part.decode()).encode()).hexdigest() == hash_value.decode():
      return nonce
      conn = remote('ip', 端口)
      msg = conn.recvuntil(b'Plz tell me XXXX:')
      print(msg)
      part = msg[12:28]
      hashvalue = msg[33:-18]
      print(part, hashvalue)
      nonce = PoW(hashvalue, part)
      print(nonce)
      conn.sendline(nonce.encode())
      conn.recvuntil(b'> ')

hashlib

  • 安装指令:从Python2.7开始python环境就已经自带,无需安装

  • 使用场景:hashlib 支持的加密算法有:md5、sha1、sha256 和 sha512。加密复杂度和花费时间依次增加。

    • 基础用法

      简单的加密操作为:

      1
      2
      3
      4
      5
      import hashlib
      s = 'abc'
      md5 = hashlib.md5() # 选择加密方式,初始化一个加密
      md5.update(s.encode('utf-8')) # 将要加密的内容,添加到m中
      print(md5.hexdigest())

      或者

      1
      s_md5=hashlib.md5(s.encode()).hexdigest()

      同样的内容使用同样的方法加密,即便使用不同的方式编码,最终加密出来的结果也是相同的:

      1
      2
      3
      4
      5
      6
      7
      import hashlib
      sha256 = hashlib.sha256()
      sha256.update('wusir'.encode('utf-8'))
      print(sha256.hexdigest())
      sha256 = hashlib.sha256()
      sha256.update('wusir'.encode('gbk'))
      print(sha256.hexdigest())

ciphey

  • 安装指令:pip install -U ciphey

    该库在安装中存在一个可能遇到的问题:

    ciphey在windows的安装问题

    如果出现编码问题:'gbk' codec can't decode byte 0xbf in position 695’如下图:

    解决方法如下:

    1. 找到pywhat这个包的位置,一般是在你的python安装目录下:….\python3\Lib\site-packages\pywhat

    2. 在该目录下找到:regexidentifier.py这个文件,把 _init()函数内的with open(fullpath,"r") 改为with open(fullpath,"rb") 即可,如下图:

    参考链接: Ciphey在windows下的安装问题(’gbk’ codec can’t decode byte 0xbf in position 695)

    安装要求:python版本$\le$3.8

  • 使用场景: 不仅是在Misc方向上的神器,ciphey在Crypto中也能用来简单分析第一眼无法看出来的密文,由于使用自然语言处理和人工智能,它在分析使用的加密方法上功能非常强大,但是经过本人测试,其在某些场景也存在局限性,在下文介绍完使用方法后会具体介绍。

    • 基础用法

      在终端或者cmd进入安装了ciphey的虚拟环境,可以通过文件输入或直接输入密文:

      1
      2
      3
      4
      5
      6
      #文件输入
      ciphey -f encrypted.txt
      python -m ciphey -f encrypted.txt
      #直接输入密文
      ciphey -t "Encrypted input" &
      python -m ciphey -t "Encrypted input"

      当密文较为短小时,使用直接输入密文的方式更为方便

    • 适用范围&局限性

      • 当涉及到多层编码时,ciphey的分析速度可以很快,比如下面的例子:

        将flag经过base32->base58->base64加密,运行ciphey -t "I44EOOLCIFUDQ5KLME======",结果如下:

        image-20230521103427519

      • 当明文包含flag{}格式,或者是有强烈的英文语义时,ciphey的识别效果比较好✔,但是ciphey基本无法识别明文带有中文语义或者没有语义的复杂密文🚫

      • 识别效果好的密码和编码包括:凯撒密码、各种base编码、url编码

      • 识别效果差的密码和编码包括:莫尔斯密码、unicode编码等等

      可以看出这个工具并非万能,后续我会写文章为ciphey不适用的编码和密码形式提供本地或在线解码方案

hashid

  • 安装指令:pip install hashid

  • 使用场景: 用于识别hash算法:给它一个hash值,它就能判断出这个值是哪种类型的hash值。

    • 基础用法

      打开hashid.exe文件,输入想要分析的hash值,软件会自动在列出可能的hash类型,排列越靠上概率越大,如下:

      image-20230521154651291

      hashid分析结果为:该hash值的类型为SHA224概率最大。

libnum

  • 安装指令:pip install libnum

  • 使用场景:进制转换、打素数表等等

    • 基础用法

      • 进制转换

      libnum.s2n(s)字符串转换为数字

      1
      2
      3
      4
      5
      import libnum
      s = "ab12"
      print(libnum.s2n(s))

      result: 1633825074

      libnum.s2n(n)数字转换为字符串

      1
      2
      3
      4
      5
      import libnum
      n = 1633825074
      print(libnum.n2s(n))

      result: ab12

      libnum.s2b(s)字符串转换为二进制字符串

      1
      2
      3
      4
      5
      import libnum
      s = "ab12"
      print(libnum.s2b(s))

      result: 01100001011000100011000100110010

      libnum.b2s(b)二进制字符串转换为字符串

      1
      2
      3
      4
      5
      import libnum
      b = "01100001011000100011000100110010"
      print(libnum.b2s(b))

      result: ab12
      • 素数相关

      libnum.primes(n)返回不大于n的素数列表

      1
      2
      3
      4
      import libnum
      print(libnum.primes(19))

      result: [2, 3, 5, 7, 11, 13, 17, 19]

      libnum.generate_prime(n)产生长度为n位的伪素数

      1
      2
      3
      4
      import libnum
      print(libnum.generate_prime(10))

      result: 1021

      libnum.factorize(n)返回n的所有素因子及每个素因子的个数

      1
      2
      3
      4
      import libnum
      print(libnum.factorize(60))

      result: {2: 2, 3: 1, 5: 1}

factordb-python

  • 安装指令:pip3 install factordb-python

  • 使用场景:FactorDB存储了该库已经知道的整数的分解,该库可以用在RSA中的大整数分解

    • 基础用法:

      命令行使用

      1
      factordb factor(需要分解的大数)

常用库函数清单

  1. gmpy2

  2. pwntools

  3. pycryptodome

  4. ciphey

  5. hashid

  6. libnum

  7. factordb-python

Crypto常用的工具

常用工具功能

yafu-1.34

  • 使用场景:yafu用于自动整数因式分解,在RSA中,当p、q的取值差异过大或过于相近的时候,使用yafu可以快速的把n值分解出p、q值,原理是使用Fermat方法与Pollard rho方法等

    • 基础用法

      在yafu-x64.exe所在的文件夹下打开终端,命令如下:

      1
      2
      3
      4
      #直接输入大整数
      yafu-x64 factor(需要分解的大数)
      #将大整数放在test.txt文件中
      yafu-x64 "factor(@)" -batchfile test.txt

      将大整数放在文件中时最后一定要换行。

  • 其他版本:当然也有yafu-v2.1版本,但是适合租一台高性能云主机来跑,docker镜像:docker run -ti --name yafu ssst0n3/yafu:2.10

常用工具清单

  1. hashcat

  2. John the Ripper

  3. crypto-attacks-master

  4. CTFCrackTools

  5. [随波逐流]CTF编码工具 V1.0.20201101

  6. yafu

  7. sagemath

  8. CaptfEncoder