逆向中常用的Python代码和库


前言

ctypes

简介

ctypes是Python的一个内置库,可以调用 C 语言编写的动态链接库。它允许 Python 代码与 C 语言库进行交互,从而实现对底层系统 API 和 C 函数的调用。

基本使用

  • 加载动态链接库
1
2
3
4
5
6
7
import ctypes

#Linux 下加载 .so 库
libc=ctypes.CDLL("libc.so.6")

#Windows 下加载 .dll库
libc=ctypes.WinDLL("msvcrt.dll")
  • 调用C函数

加载库后,可以直接调用库中的函数

1
2
3
4
5
6
import ctypes

libc=ctypes.CDLL(None)
libc.srand(int(0))
result=libc.rand()
print(result)
  • 使用指针和结构体

指针

1
2
3
4
5
6
7
8
# 定义整数类型的指针
int_ptr = ctypes.POINTER(ctypes.c_int)

# 创建指针
value = ctypes.c_int(10)
p_value = ctypes.pointer(value)
print(p_value.contents)
# 输出: c_int(10)

结构体

1
2
3
4
5
6
7
class Point(ctypes.Structure):
_fields_ = [("x", ctypes.c_int), ("y", ctypes.c_int)]

# 创建结构体实例
p = Point(3, 4)
print(p.x, p.y)
# 输出: 3 4
  • 使用数组
1
2
3
4
5
6
7
# 创建包含 10 个整数的数组
IntArray10 = ctypes.c_int * 10
arr = IntArray10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

# 输出数组内容
for num in arr:
print(num)

hashlib

简介

hashlib 是 Python 标准库中的一个模块,提供了各种常见的哈希算法的实现,常用于数据加密、完整性验证、数字签名等任务。

基本使用

  • 计算MD5
1
2
3
4
5
6
import hashlib

data="hello"
#hexdigest将生成的MD5哈希值以十六进制字符串的形式输出
enc=hashlib.md5(data.encode()).hexdigest()
print(f"MD5:{enc}")
  • 计算SHA-256
1
2
3
4
5
6
import hashlib

data="hello"
#hexdigest将生成的MD5哈希值以十六进制字符串的形式输出
enc=hashlib.sha256(data.encode()).hexdigest()
print(f"SHA-256:{enc}")

binascii

简介

binascii 模块提供了二进制和 ASCII 数据之间转换的工具,常用于处理 base64 编码、hexadecimal 编码等数据格式。

基本使用

  1. Hex 编码和解码

binascii 提供了将二进制数据转换为十六进制字符串,以及从十六进制字符串转换回二进制数据的功能。

1
2
3
4
5
6
7
8
9
10
11
12
import binascii

# 将二进制数据转换为ASCII十六进制字符串
data = b"hello"
hex_encode = binascii.hexlify(data)
print(hex_encode)
# 输出:b'68656c6c6f'

# 将十六进制字符串转换为二进制数据
hex_decode = binascii.unhexlify(hex_encoded)
print(hex_decode)
# 输出:b'hello'
  1. Base64 编码和解码

虽然binascii可以处理 Base64 编码,但一般推荐使用base64模块。binasciib2a_base64方法仍可用于 base64 编码。

1
2
3
4
5
6
7
8
9
10
import binascii

# 将二进制数据转换为Base64编码
binary_data = b"hello"
base64_encoded = binascii.b2a_base64(binary_data)
print(base64_encoded) # 输出:b'aGVsbG8=\n'

# 将Base64编码转换回二进制数据
base64_decoded = binascii.a2b_base64(base64_encoded)
print(base64_decoded) # 输出:b'hello'
  1. CRC32 校验

binascii可以用于计算数据的CRC32校验值,常用于数据完整性验证。

1
2
3
4
5
import binascii

data = b"hello world"
crc32_value = binascii.crc32(data)
print(crc32_value) # 输出一个校验值,如:222957957
  1. 转换二进制到ASCII表示

将二进制数据转换为只包含可打印ASCII字符的表示方式。

1
2
3
4
5
6
7
8
9
10
import binascii

# 将二进制数据转换为ASCII字符表示
binary_data = b"hello"
ascii_encoded = binascii.b2a_uu(binary_data)
print(ascii_encoded) # 输出:b'&5L;&\\``\n'

# 将ASCII字符表示转换回二进制数据
ascii_decoded = binascii.a2b_uu(ascii_encoded)
print(ascii_decoded) # 输出:b'hello'

base64

简介

base64 是 Python 标准库中的一个模块,用于对数据进行 Base64 编码和解码。

基本使用

  • base64常规加密

base.b64decode()将base64编码的字符串解码为原始字节数据
decode表示将字节码数据解码为UTF-8编码的字符串

1
2
3
4
5
6
7
8
#!/usr/bin/python3
import base64

enc="aGVsbG8="

flag=base64.b64decode(enc).decode()

print(flag)
  • base64换表加密

str.maketrans(string1,string2)创建一个映射表,用于将string1中的字符一一对应的替换为strings2中的字符
str1.translate()根据映射表来转换str1中的字符。

1
2
3
4
5
6
7
8
import base64 
import string

str1 = "GyAGD1ETr3AcGKNkZ19PLKAyAwEsAIELHx1nFSH2IwyGsD=="
string1 = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print(base64.b64decode(str1.translate(str.maketrans(string1,string2))))
1
2
3
4
5
6
7
l = [0x7D2E370A180F1604, 0x3F7D132A2A252822, 0x392A7F3F39132D13, 0x0031207C7C381320]
cipher = b''.join(map(lambda x: x.to_bytes(8, "little"), l))

for i in range(256):
plain = bytes(map(lambda x: x ^ i, cipher))
if b"CTF" in plain:
print(plain[:-1])

base58

简介

Base58 是一种用于编码和解码数据的方式,通常用于加密货币(如比特币)地址等地方。它的特点是避免了类似 Base64 编码中容易混淆的字符(如 0, O, I, l 等)。

基本使用

1
2
3
4
5
6
7
8
#!/usr/bin/python3
import base58

enc="aGVsbG8="

flag=base64.b64decode(enc).decode()

print(flag)
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
26
27
28
29
30
31
32
33
34

## pycryptodome

### 简介

`pycryptodome` 是 Python 的一个加密库,它提供了丰富的加密算法实现,包括对称加密、非对称加密、哈希函数、消息认证码(MAC)、数字签名等。

### 基本使用

`pycryptodome`是一个Python库,提供加密和解密功能,包括对称和非对称加密、哈希函数等。它是`pycrypto`的一个更安全的替代品,广泛用于各种加密任务。

#### 1. 对称加密

- RC4

```python
from Crypto.Cipher import ARC4

key=b"test_key"

#加密
dec=b"hello world"
rc4=ARC4.new(key)
enc=rc4.encrypt(dec)
print(enc.hex())
#密文:80e2baf4b502cd9b412fe6

#解密
#需要重新重新创建ARC4对象,因为加密后对象的状态已经改变
rc4=ARC4.new(key)
enc=bytes.fromhex("80e2baf4b502cd9b412fe6")
dec=rc4.decrypt(enc)
print(dec)
#明文:hello world
  • AES
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes

# 生成密钥和IV
key = get_random_bytes(16) # 128位密钥
cipher = AES.new(key, AES.MODE_CBC) # 使用CBC模式
iv = cipher.iv

# 加密
data = b"Hello, World!"
ciphertext = cipher.encrypt(pad(data, AES.block_size))

# 解密
decipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = unpad(decipher.decrypt(ciphertext), AES.block_size)

print("Ciphertext:", ciphertext)
print("Plaintext:", plaintext)
  • DES
  • BlowFish

2. 非对称加密

  • RSA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

# 生成密钥对
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()

# 加密
cipher = PKCS1_OAEP.new(RSA.import_key(public_key))
ciphertext = cipher.encrypt(b"Hello, World!")

# 解密
decipher = PKCS1_OAEP.new(RSA.import_key(private_key))
plaintext = decipher.decrypt(ciphertext)

print("Ciphertext:", ciphertext)
print("Plaintext:", plaintext)
  • SM2

3. 哈希函数

  • MD5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Crypto.Hash import MD5

# 输入数据
data = "hello world"

# 创建 MD5 哈希对象
md5_hash = MD5.new()

# 更新哈希对象
md5_hash.update(data.encode())

# 获取十六进制表示的哈希值
md5_digest = md5_hash.hexdigest()

print(f"MD5 哈希值: {md5_digest}")
  • SHA-256
1
2
3
4
5
6
7
from Crypto.Hash import SHA256

data = b"Hello, World!"
hash_object = SHA256.new(data)
hash_value = hash_object.hexdigest()

print("SHA-256 Hash:", hash_value)

gmpy2

简介

gmpy2是一个高性能的数学库,特别适用于大整数运算、浮点数运算以及有理数运算。它是基于GNU MP(GMP)和GNU MPFR(多重精度浮点数库)的,因此在处理高精度数学时非常快速和高效。

基本使用

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
26
import gmpy2

# 创建大整数
a = gmpy2.mpz(123456789012345678901234567890)
b = gmpy2.mpz(987654321098765432109876543210)

# 大整数加法
c = a + b
print("Sum:", c)

# 大整数乘法
d = a * b
print("Product:", d)

# 创建浮点数
x = gmpy2.mpfr('3.14159265358979323846')

# 浮点数运算
y = x * 2
print("Double of pi:", y)

# 有理数
r = gmpy2.mpq(1, 3) # 1/3
s = gmpy2.mpq(1, 2) # 1/2
result = r + s
print("Sum of 1/3 and 1/2:", result)

gmssl

简介

gmssl 是一个 Python 库,提供了对中国国家标准加密算法(也称为国密算法,GM算法)的支持。它实现了中国的加密算法标准,主要包括 SM2SM3SM4 等算法。

基本使用

  • SM2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from gmssl import sm2, func

# SM2 密钥对生成
private_key = '00D474F0213D7A7B0A7607A5AA4E5C295D8B1F0248F7083DA1B62D052D4C1C36'
public_key = '04B92D4CCB3F3A5C4BDAA7D5631BC1775AFC7A2604C3B24090CC257A233CC851D92C14C9A0CFAAEBCF2F027EC22B4CC26F0DFFA320D6A35D6DC19F927E72130FDE'

# 创建 SM2 对象
sm2_crypt = sm2.CryptSM2(private_key=private_key, public_key=public_key)

# 待加密的数据
data = "hello world"
data_bytes = data.encode()

# SM2 加密
encrypted_data = sm2_crypt.encrypt(data_bytes)
print(f"Encrypted: {encrypted_data.hex()}")

# SM2 解密
decrypted_data = sm2_crypt.decrypt(encrypted_data)
print(f"Decrypted: {decrypted_data.decode()}")
  • SM3
1
2
3
4
5
6
7
8
from gmssl import sm3

# 消息
message = 'hello world'

# 计算 SM3 哈希值
hash_value = sm3.sm3_hash(message.encode())
print(f"SM3 Hash: {hash_value}")
  • SM4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from gmssl import sm4

# SM4 加密密钥
key = b'1234567890abcdef'

# 初始化 SM4 加密对象
sm4_crypt = sm4.CryptSM4()
sm4_crypt.set_key(key, sm4.SM4_ENCRYPT)

# 加密
plain_text = b"hello world"
cipher_text = sm4_crypt.encrypt(plain_text)
print(f"Ciphertext: {cipher_text}")

# 解密
sm4_crypt.set_key(key, sm4.SM4_DECRYPT)
decrypted_text = sm4_crypt.decrypt(cipher_text)
print(f"Decrypted text: {decrypted_text.decode()}")

例题

[GDOUCTF 2023]真男人下120层

  • 分析

  • exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
from ctypes import *
context.log_level='debug'
#io = process('./bin')
io=remote("node4.anna.nssctf.cn",28765)

lib = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
srand=lib.srand(lib.time(0))
srand=lib.srand(srand%3-1522127470)
io.recvuntil('Floor')
for i in range(121):
io.sendline(str(lib.rand()%4+1).encode())

io.interactive()