【攻防世界】reverse | answer_to_everything 详细题解 WP
下载附件

main函数伪代码:
c
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+Ch] [rbp-4h] BYREF
printf("Gimme: ");
__isoc99_scanf("%d", &v4);
not_the_flag(v4);
return 0;
}
not_the_flag函数伪代码:
c
__int64 __fastcall not_the_flag(int a1)
{
if ( a1 == 42 )
puts("Cipher from Bill \nSubmit without any tags\n#kdudpeh");
else
puts("YOUSUCK");
return 0LL;
}
分析这两个函数,结合题目描述,将原始字符串kdudpeh进行 sha1 加密加上 flag{} 即可得到 flag,这里写了一个exp方便进行加密
exp:
python
import hashlib
import sys
import argparse
def string_to_sha1(input_str: str, uppercase: bool = True, with_space: bool = False) -> str:
"""
计算字符串的SHA1哈希值(CTF中最常用场景)
:param input_str: 待加密的字符串
:param uppercase: 是否输出大写(CTF中多要求大写/小写统一)
:param with_space: 是否每2个字符加空格(部分题目格式要求)
:return: SHA1哈希值字符串
"""
try:
# 字符串转bytes(UTF-8编码,兼容中文/特殊字符)
str_bytes = input_str.encode('utf-8')
# 计算SHA1哈希
sha1_obj = hashlib.sha1()
sha1_obj.update(str_bytes)
# 获取十六进制结果
sha1_hex = sha1_obj.hexdigest()
# 格式处理:大写/小写、空格分隔
if uppercase:
sha1_hex = sha1_hex.upper()
if with_space:
sha1_hex = ' '.join([sha1_hex[i:i+2] for i in range(0, len(sha1_hex), 2)])
return sha1_hex
except Exception as e:
raise ValueError(f"字符串SHA1加密失败:{e}")
def file_to_sha1(file_path: str, uppercase: bool = True, with_space: bool = False, chunk_size: int = 4096) -> str:
"""
计算文件的SHA1哈希值(验证文件完整性/匹配题目哈希)
:param file_path: 文件路径
:param uppercase: 是否输出大写
:param with_space: 是否每2个字符加空格
:param chunk_size: 读取文件的块大小(避免大文件内存溢出)
:return: 文件的SHA1哈希值
"""
try:
sha1_obj = hashlib.sha1()
with open(file_path, 'rb') as f:
# 分块读取大文件(避免内存占用过高)
while chunk := f.read(chunk_size):
sha1_obj.update(chunk)
# 格式处理
sha1_hex = sha1_obj.hexdigest()
if uppercase:
sha1_hex = sha1_hex.upper()
if with_space:
sha1_hex = ' '.join([sha1_hex[i:i+2] for i in range(0, len(sha1_hex), 2)])
return sha1_hex
except FileNotFoundError:
raise FileNotFoundError(f"文件不存在:{file_path}")
except PermissionError:
raise PermissionError(f"无权限读取文件:{file_path}")
except Exception as e:
raise ValueError(f"文件SHA1加密失败:{e}")
def main():
"""
命令行交互入口(支持参数化调用,CTF中直接运行)
"""
# 解析命令行参数
parser = argparse.ArgumentParser(description="CTF专用SHA1加密工具:支持字符串/文件加密")
parser.add_argument('-s', '--string', type=str, help='待加密的字符串(与-f二选一)')
parser.add_argument('-f', '--file', type=str, help='待加密的文件路径(与-s二选一)')
parser.add_argument('-u', '--uppercase', action='store_true', default=True, help='输出大写(默认开启)')
parser.add_argument('-l', '--lowercase', action='store_false', dest='uppercase', help='输出小写(覆盖-u)')
parser.add_argument('-ws', '--with-space', action='store_true', default=False, help='每2个字符加空格(默认关闭)')
args = parser.parse_args()
# 校验参数:必须指定-s或-f
if not args.string and not args.file:
print("❌ 错误:必须指定 -s <字符串> 或 -f <文件路径>")
parser.print_help()
sys.exit(1)
# 执行加密并输出结果
try:
if args.string:
sha1_result = string_to_sha1(args.string, args.uppercase, args.with_space)
print(f"✅ 字符串SHA1加密结果:")
print(f" 原始字符串:{args.string}")
print(f" SHA1哈希值:{sha1_result}")
print(f" flag:flag{{{sha1_result}}}")
else:
sha1_result = file_to_sha1(args.file, args.uppercase, args.with_space)
print(f"✅ 文件SHA1加密结果:")
print(f" 文件路径:{args.file}")
print(f" SHA1哈希值:{sha1_result}")
except Exception as e:
print(f"❌ 加密失败:{e}")
sys.exit(1)
if __name__ == "__main__":
# 示例调用(直接运行脚本时使用命令行参数,也可在代码中调用函数)
main()
运行 exp 脚本

得到flag:
flag{80ee2a3fe31da904c596d993f7f1de4827c1450a}
【攻防世界】reverse | answer_to_everything 详细题解 WP 原理深度解析:
CTF 逆向实战:answer_to_everything 详细解题指南与原理深度解析
一、题目背景与初始分析
在 CTF 逆向工程领域,"answer_to_everything" 这类题目属于典型的 "输入验证 + 简单加密" 类型,适合逆向入门但又包含实战必备的分析思路。本题的核心目标是通过逆向程序逻辑,找到触发关键信息的条件,最终破解并生成符合格式的 flag。
从题目名称 "answer_to_everything"(万物的答案),我们可以联想到经典科幻小说《银河系漫游指南》中 "42 是宇宙的终极答案" 这一彩蛋,这其实已经暗示了输入的关键数值,为后续分析提供了隐性线索。
二、程序逆向分析:从伪代码到核心逻辑
2.1 主函数(main)逻辑拆解
程序的主函数伪代码如下:
c
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+Ch] [rbp-4h] BYREF
printf("Gimme: ");
__isoc99_scanf("%d", &v4);
not_the_flag(v4);
return 0;
}
关键分析:
- 程序首先输出提示语 "Gimme:",等待用户输入
- 通过
__isoc99_scanf("%d", &v4)读取一个整数(%d明确输入类型为十进制整数) - 将输入的整数传入
not_the_flag函数进行处理 - 无复杂逻辑,核心功能是 "读取输入→传递给验证函数"
2.2 验证函数(not_the_flag)逻辑解析
验证函数是本题的核心,伪代码如下:
c
__int64 __fastcall not_the_flag(int a1)
{
if ( a1 == 42 )
puts("Cipher from Bill \nSubmit without any tags\n#kdudpeh");
else
puts("YOUSUCK");
return 0LL;
}
关键分析:
- 函数接收一个整数参数
a1(即 main 函数中输入的v4) - 核心判断:当输入的整数等于 42 时,输出三段关键信息;否则输出 "YOUSUCK"(输入错误)
- 输出的关键信息包含三个部分:
- "Cipher from Bill":表面是加密相关提示(实际本题加密方式更直接)
- "Submit without any tags":明确要求提交时去除 "标签"(即去掉
#符号) - "#kdudpeh":核心字符串(去除
#后为kdudpeh)
2.3 逆向结论:触发条件与关键信息
通过对两个函数的分析,可直接得出:
- 触发关键信息的输入为整数42(与题目名称的彩蛋呼应)
- 关键字符串为kdudpeh (去除
#后) - 后续需对
kdudpeh进行处理以生成 flag
三、flag 生成逻辑:从关键字符串到最终答案
3.1 加密方式识别
题目提示 "将原始字符串 kdudpeh 进行 sha1 加密加上 flag {} 即可得到 flag",明确了加密算法为SHA1。
SHA1 是一种密码散列函数,可将任意长度的输入转换为固定长度(160 位,40 个十六进制字符)的哈希值,在 CTF 中常用于对关键字符串进行加密生成 flag,具有不可逆性(无法从哈希值反推原始字符串)。
3.2 实战操作:使用 Python 脚本计算 SHA1 哈希
提供的 Python 脚本专门用于 CTF 场景下的 SHA1 加密,支持字符串和文件两种模式,我们需要用它计算kdudpeh的 SHA1 值。
脚本核心函数解析
python
def string_to_sha1(input_str: str, uppercase: bool = True, with_space: bool = False) -> str:
# 字符串转bytes(UTF-8编码,兼容特殊字符)
str_bytes = input_str.encode('utf-8')
# 计算SHA1哈希
sha1_obj = hashlib.sha1()
sha1_obj.update(str_bytes)
sha1_hex = sha1_obj.hexdigest() # 获取十六进制结果
# 格式处理(大写/小写、空格分隔)
if uppercase:
sha1_hex = sha1_hex.upper()
if with_space:
sha1_hex = ' '.join([sha1_hex[i:i+2] for i in range(0, len(sha1_hex), 2)])
return sha1_hex
功能说明:
- 将输入字符串转为 UTF-8 编码的字节流(确保特殊字符正确处理)
- 调用
hashlib.sha1()计算哈希值 - 支持格式调整:默认输出大写十六进制,可通过参数改为小写或添加空格分隔
执行步骤与结果
-
运行脚本,指定字符串
kdudpeh:bashpython sha1_tool.py -s "kdudpeh" -l(小写) -
输出结果:
plaintext✅ 字符串SHA1加密结果: 原始字符串:kdudpeh SHA1哈希值:80ee2a3fe31da904c596d993f7f1de4827c1450a flag:flag{80ee2a3fe31da904c596d993f7f1de4827c1450a} -
包装为 flag 格式:
flag{80ee2a3fe31da904c596d993f7f1de4827c1450a}
四、原理深度解析:逆向与加密的核心逻辑
4.1 逆向分析的本质
本题的逆向过程体现了 "输入 - 验证 - 输出" 的经典模型:
- 输入层 :明确输入类型(整数)和范围(通过
unsigned int可推断为 0~4294967295,但实际有效输入仅 42) - 验证层 :通过简单的条件判断(
a1 == 42)决定输出内容,无复杂算法(如混淆、加密验证) - 输出层:直接暴露关键字符串,降低了解题难度
4.2 SHA1 加密的 CTF 应用场景
SHA1 在 CTF 中常见于:
- 对已知明文生成 flag(如本题,直接对关键字符串加密)
- 文件完整性验证(通过比对文件的 SHA1 哈希判断是否被篡改)
- 简单登录验证(程序存储密码的 SHA1 哈希,输入密码加密后比对)
其核心特点是固定输出长度 和单向性,使得它适合作为 "不可逆转换" 的工具。
五、同类题目解题方法论:举一反三
5.1 题型特征识别
"输入验证 + 哈希加密" 类题目通常具有以下特征:
- 主函数逻辑简单:读取输入→调用验证函数→输出结果
- 验证条件明确:多为简单的数值 / 字符串比对(如等于某个固定值)
- 关键信息直接暴露:在验证通过的分支中直接输出待处理的字符串
- 加密方式提示清晰:通过输出文本或函数名暗示加密算法(如 "sha"、"hash" 等关键词)
5.2 快速解题步骤
- 定位输入与验证逻辑 :
- 找到
scanf/gets等输入函数,确定输入类型(整数 / 字符串) - 跟踪输入值的传递路径,找到验证函数(通常是输入值直接作为参数的函数)
- 分析验证条件,确定触发关键信息的输入(如本题的 42)
- 找到
- 提取关键字符串 :
- 在验证通过的分支中寻找字符串输出(如
puts/printf函数的参数) - 注意处理特殊符号(如本题需去除
#)
- 在验证通过的分支中寻找字符串输出(如
- 识别并应用加密算法 :
- 根据提示确定加密算法(SHA1/SHA256/MD5 等哈希算法,或凯撒 / 异或等简单加密)
- 使用工具快速计算结果(如本题的 Python 脚本,或在线哈希工具)
- 按题目要求包装格式(如添加
flag{})
5.3 工具推荐
- 逆向分析工具:IDA Pro(静态分析伪代码)、x64dbg(动态调试验证输入)
- 哈希计算工具 :Python
hashlib库(灵活编程)、在线哈希计算器(快速验证) - 自动化脚本:如本题提供的 SHA1 工具,可提前准备各类加密算法的通用脚本,解题时直接调用
六、总结
"answer_to_everything" 作为一道入门级逆向题,核心考察了:
- 基础逆向分析能力:从伪代码中提取输入验证逻辑和关键信息
- 加密算法应用能力:识别 SHA1 算法并计算结果
- 格式处理能力:按要求处理字符串(去标签)和包装 flag
通过本题可掌握 "输入验证→关键字符串提取→加密计算" 的经典解题流程,这类思路可直接应用于大部分同类型逆向题目。记住:在 CTF 中,复杂的题目往往始于简单的逻辑,耐心分析每一个函数和字符串,就能找到破解的关键。