Cryptohack wp (GENERAL篇)
本篇是GENERAL篇,以下题目中没提及到的题目均在course的其他篇目中
Encoding Challenge
给了三个文件,一个挑战文件和两个示例文件,主要是pwntools库的运用:挑战代码如下:
#!/usr/bin/env python3
from Crypto.Util.number import bytes_to_long, long_to_bytes
from utils import listener # this is cryptohack's server-side module and not part of python
import base64
import codecs
import random
FLAG = "crypto{????????????????????}"
ENCODINGS = [
"base64",
"hex",
"rot13",
"bigint",
"utf-8",
]
with open('/usr/share/dict/words') as f:
WORDS = [line.strip().replace("'", "") for line in f.readlines()]
class Challenge():
def __init__(self):
self.challenge_words = ""
self.stage = 0
def create_level(self):
self.stage += 1
self.challenge_words = "_".join(random.choices(WORDS, k=3))
encoding = random.choice(ENCODINGS)
if encoding == "base64":
encoded = base64.b64encode(self.challenge_words.encode()).decode() # wow so encode
elif encoding == "hex":
encoded = self.challenge_words.encode().hex()
elif encoding == "rot13":
encoded = codecs.encode(self.challenge_words, 'rot_13')
elif encoding == "bigint":
encoded = hex(bytes_to_long(self.challenge_words.encode()))
elif encoding == "utf-8":
encoded = [ord(b) for b in self.challenge_words]
return {"type": encoding, "encoded": encoded}
#
# This challenge function is called on your input, which must be JSON
# encoded
#
def challenge(self, your_input):
if self.stage == 0:
return self.create_level()
elif self.stage == 100:
self.exit = True
return {"flag": FLAG}
if self.challenge_words == your_input["decoded"]:
return self.create_level()
return {"error": "Decoding fail"}
listener.start_server(port=13377)
这是一个Python脚本,定义了一个名为Challenge的类,该类生成涉及各种编码的一系列挑战。
脚本首先导入一些模块:Crypto.Util.number中的bytes_to_long和long_to_bytes,以及Python标准库中的base64和codecs。它还导入一个名为listener的模块,该模块不是Python的一部分,而是专门针对cryptohack平台开发的。
接下来,脚本定义了一个可能的编码列表ENCODINGS。这些编码用于生成挑战。
然后,脚本打开一个名为/usr/share/dict/words的文件,其中包含一个单词列表,并将文件的内容读入一个名为WORDS的列表中。文件的每一行都被去除了任何空白,并且单引号被移除。
Challenge类有两个方法:__init__和challenge。__init__方法初始化了两个实例变量:challenge_words,用于保存当前阶段的挑战词,以及stage,用于跟踪当前挑战的阶段。
create_level方法为当前阶段生成一个新的挑战。它通过递增stage变量,从WORDS列表中随机选择三个单词来形成challenge_words字符串,并从ENCODINGS列表中随机选择一个编码。根据所选择的编码,create_level使用以下方法之一对challenge_words字符串进行编码:
base64.b64encode:将challenge_words字符串编码为base64。
encode().hex():将challenge_words字符串编码为十六进制字符串。
codecs.encode(challenge_words, 'rot_13'):使用ROT13编码challenge_words字符串。
hex(bytes_to_long(self.challenge_words.encode())):将challenge_words字符串编码为十六进制格式的大整数。
[ord(b) for b in self.challenge_words]:将challenge_words字符串编码为表示字符串中字符的Unicode代码点的整数列表。
create_level方法返回一个包含编码类型和编码后挑战词的字典。
challenge方法是主要的函数,它将用户输入作为参数,并返回响应。如果当前阶段为0,challenge通过调用create_level生成一个新的挑战。如果当前阶段为100,challenge将实例变量exit设置为True并返回标志。否则,如果用户输入与解码后的挑战词匹配,challenge通过调用create_level生成一个新的挑战。否则,它返回一个错误消息。
脚本最后通过使用listener模块在端口13377上启动服务器。
脚本的主要目的是生成一系列的编码挑战。每个挑战包括一个编码类型和一个经过特定编码的挑战词。用户需要解码挑战词并将其作为输入提供给脚本,以通过当前的挑战并进入下一个阶段。在挑战的前100个阶段中,用户需要成功解码挑战词才能进入下一个阶段。当达到第100个阶段时,脚本会返回标志。这意味着用户需要连续成功解码100个挑战才能获取完整的flag
解密代码如下:
from pwn import *
import json
r = remote('socket.cryptohack.org', 13377, level = 'debug')
def json_recv():
line = r.recvline()
return json.loads(line.decode())
def json_send(hsh):
request = json.dumps(hsh).encode()
r.sendline(request)
from binascii import *
from base64 import b64decode as dd
from string import *
def rot13(x):
ss = ascii_lowercase
res = ''
for i in x:
if i in ss:
res += ss[(13+ss.index(i))%26]
else:res += i
return res
def dec(tp,c):
if tp == 'bigint':
m = unhexlify(c[2:]).decode()
elif tp == 'base64':
m = dd(c.encode()).decode()
elif tp == 'rot13':
m = rot13(c)
elif tp == 'hex':
m = bytes.fromhex(c).decode()
elif tp == 'utf-8':
m = ''.join(chr(i) for i in c)
return m
def func(received):
print("Received type: ",end='')
print(received["type"])
print("Received encoded value: ",end='')
print(received["encoded"])
c = received["encoded"]
tp = received['type']
to_send = {"decoded": dec(tp,c)}
print('to_sent:',to_send)
json_send(to_send)
rrr = json_recv()
print(rrr,'================',sep = '\n')
return rrr
rcvd = json_recv()
for i in range(100):
rcvd = func(rcvd)
Lemur XOR
下载下来是两张图片:
lemur.png:
flag.png:
两张图片异或
from PIL import Image
import numpy as np
# 打开第一张图像
image1 = Image.open('flag.png')
# 打开第二张图像
image2 = Image.open('lemur.png')
# 将图像转换为NumPy数组
array1 = np.array(image1)
array2 = np.array(image2)
# 执行异或运算
result_array = np.bitwise_xor(array1, array2)
# 创建新的图像对象
result_image = Image.fromarray(result_array)
# 保存结果图像
result_image.save('result.jpg')
得到图像为:
Privacy-Enhanced Mail?
给了一个pem文件,把里面的私钥信息解密出来即可
from Crypto.PublicKey import RSA
from Crypto.PublicKey import RSA
# Import the RSA key from a file
with open('1.pem', 'r') as f:
private_key_data = f.read()
private_key = RSA.importKey(private_key_data)
print(private_key.d)
CERTainly not
PEM是一种基于ASCII的格式,用于将密钥和证书编码为可读的文本。它通常以"-----BEGIN..."和"-----END..."之间的标识行包围,并使用Base64编码将二进制数据表示为可打印字符。PEM格式可以包含私钥、公钥和证书等。
DER是一种二进制格式,用于将密钥和证书编码为紧凑的二进制数据。DER格式不包含可打印字符,适合在网络传输中使用。它通常用于在各种编程语言和通信协议中表示密钥和证书。
在Python中,pycryptodome库的RSA模块可以处理PEM和DER格式的密钥。你可以使用import_key()方法从PEM或DER格式的字符串或文件中导入密钥。
from Crypto.PublicKey import RSA
# Import the RSA key from a file
with open('1.der', 'rb') as f:
public_key_der = f.read()
public_key = RSA.import_key(public_key_der)
print(public_key.n)
求证书的模,也就是n,即flag。
SSH Keys
这道题也和上题差不多,求n,直接上代码:
from Crypto.PublicKey import RSA
with open('bruce_rsa.pub',"rb") as f:
public_key =f.read()
public_data = RSA.importKey(public_key)
print(public_data.n)
Transparency
主打的就是一个信息搜集,题目中说了,“由于此类事件,再加上欺诈证书可能需要很长时间才能被发现,自 2018 年以来,Google Chrome 已强制实施证书透明度。每个 CA 都必须将他们颁发的所有证书发布到日志中,任何人都可以搜索该日志”,找到在其 TLS 证书中使用这些参数的 cryptohack.org 的子域,并访问该子域以获取flag。
由于crptohack.org服务器在英国,所以直接锁定英国,在说题目中说flag在cryptohack.org子域名下,所以直接fofa搜索,fofa语法如下:
domain="cryptohack.org" && region="England" && "crypto"
然后可以得到几组结果,在第三个结果中看到“thetransparencyflagishere”:
点开这个网站:得到flag。
还或者:https://crt.sh/?q=cryptohack.org,直接在这个网站搜索cryptohack.org,找到
或者可以直接使用以下linux命令:
curl -s "https://crt.sh/?q=cryptohack.org" | grep "flag"
打开后找到flag