【CTF-编程-NC】罗马数字和整数的转换 题目罗马数字转整数欢迎来到编程世界你将连接到一个交互式服务。在每一轮中服务端会向你提供一个罗马数字你的任务是将其正确转换为对应的整数。请使用NC连接分数连接测试编写代码#!/usr/bin/env python3# -*- coding: utf-8 -*- CTF 解题脚本 - 罗马数字转整数自动解题器 该脚本用于自动连接 CTF 挑战服务器接收罗马数字转换题目计算答案并发送回服务器 直到获得 flag 或连接断开。 依赖库: - socket: 用于建立 TCP 连接 - re: 用于正则表达式匹配罗马数字 - time: 用于添加延迟防止请求过快 使用方法: 1. 确保脚本具有执行权限: chmod x exploit.py 2. 直接运行脚本: python3 exploit.py 注意事项: - 请确保网络连接正常 - 服务器地址和端口可能需要根据实际情况修改 - 脚本设置了 30 秒超时可根据需要调整 importsocket# 导入 socket 库用于网络通信importre# 导入正则表达式库用于解析罗马数字importtime# 导入时间库用于添加延迟defroman_to_int(roman): 将罗马数字字符串转换为整数的核心函数 参数: roman (str): 输入的罗马数字字符串仅包含大写字母 IVXLCDM 返回: int: 转换后的整数值 罗马数字转换规则: 1. 基本字符对应的值: I 1, V 5, X 10, L 50, C 100, D 500, M 1000 2. 组合规则: - 当较小的数字出现在较大的数字左边时需要减去该值如 IV 4, IX 9, XL 40 - 当较小的数字出现在较大的数字右边时需要加上该值如 VI 6, XI 11, LX 60 3. 限制规则: - 相同的数字最多连续出现三次如 III 3, XXX 30 - 左减不能跨越一个位数如 99 是 XCIX不是 IC 算法原理: 从右到左遍历罗马数字字符串维护一个前一个字符的值: - 如果当前字符值小于前一个字符值说明需要减去当前值 - 否则加上当前值 这种方法可以高效处理所有罗马数字组合包括特殊的左减情况 # 定义罗马数字字符到整数的映射字典roman_map{I:1,# 基本字符: I 1V:5,# 基本字符: V 5X:10,# 基本字符: X 10L:50,# 基本字符: L 50C:100,# 基本字符: C 100D:500,# 基本字符: D 500M:1000# 基本字符: M 1000}total0# 初始化总和为 0prev_value0# 初始化前一个字符的值为 0# 从右到左遍历罗马数字字符串forcharinreversed(roman):# 获取当前字符对应的整数值valueroman_map[char]# 根据规则判断是加还是减ifvalueprev_value:total-value# 当前值小于前一个值需要减去当前值else:totalvalue# 当前值大于等于前一个值需要加上当前值# 更新前一个字符的值用于下一次循环比较prev_valuevaluereturntotal# 返回转换后的整数值defsolve(): 主解题函数负责处理与 CTF 服务器的通信和解题流程 详细流程: 1. 配置服务器连接信息主机名和端口 2. 创建 TCP socket 并设置超时 3. 连接到指定的 CTF 服务器 4. 进入主循环持续接收服务器数据: a. 接收服务器发送的数据并解码 b. 检查是否接收到 flag 或连接断开 c. 检查是否需要退出收到 Bye 消息 d. 如果收到输入提示符 则解析题目: i. 分割接收到的数据为多行 ii. 查找包含 Round 的行表示新的一轮题目 iii. 获取下一行作为罗马数字行 iv. 使用正则表达式提取罗马数字 v. 调用 roman_to_int 函数计算答案 vi. 将答案发送回服务器 vii. 清空缓冲区准备下一轮 5. 异常处理捕获并打印所有异常 6. 无论是否发生异常都确保关闭 socket 连接 # 服务器配置信息hostchallenge.qsnctf.com# CTF 服务器主机名port32813# CTF 服务器端口号# 创建 TCP socket 对象# socket.AF_INET: 使用 IPv4 地址# socket.SOCK_STREAM: 使用 TCP 协议socksocket.socket(socket.AF_INET,socket.SOCK_STREAM)# 设置 socket 超时时间为 30 秒防止无限等待sock.settimeout(30)# 连接到 CTF 服务器sock.connect((host,port))try:# 初始化缓冲区用于存储接收到的数据buffer# 主循环持续处理服务器数据whileTrue:# 接收服务器数据最多接收 4096 字节# decode(utf-8, errorsignore): 使用 UTF-8 解码忽略解码错误datasock.recv(4096).decode(utf-8,errorsignore)# 如果没有接收到数据说明连接已断开退出循环ifnotdata:break# 将新接收到的数据添加到缓冲区bufferdata# 打印接收到的数据使用 repr() 显示不可见字符print(Received:,repr(data))# 检查缓冲区中是否包含 flag 或 qsnctf不区分大小写ifflaginbuffer.lower()orqsnctfinbuffer.lower():print(Found flag!)# 找到 flag打印提示print(buffer)# 打印完整的缓冲区内容break# 退出循环# 检查是否收到退出消息ifByeinbufferorbyeinbuffer:print(buffer)# 打印退出消息break# 退出循环# 检查是否收到输入提示符 ifinbuffer:# 将缓冲区按换行符分割为多行linesbuffer.split(\n)# 遍历每一行查找包含 Round 的行表示新的一轮forlineinlines:ifRoundinline:# 获取包含 Round 的行在列表中的索引idxlines.index(line)# 检查下一行是否存在ifidx1len(lines):# 获取下一行并去除首尾空白字符roman_linelines[idx1].strip()# 使用正则表达式匹配罗马数字仅包含 IVXLCDM 字符matchre.search(r[IVXLCDM],roman_line)ifmatch:# 提取匹配到的罗马数字romanmatch.group()print(Roman numeral:,roman)# 打印提取到的罗马数字# 调用罗马数字转换函数计算答案resultroman_to_int(roman)print(Answer:,result)# 打印计算结果# 将答案转换为字符串并添加换行符然后编码为字节发送sock.send((str(result)\n).encode(utf-8))# 清空缓冲区准备接收下一轮数据buffer# 添加 0.5 秒延迟防止请求过快导致服务器拒绝time.sleep(0.5)break# 跳出当前循环处理下一轮数据exceptExceptionase:# 捕获并打印所有异常print(Error:,e)finally:# 无论是否发生异常都确保关闭 socket 连接sock.close()# 主程序入口if__name____main__:# 调用主解题函数solve()运行结果Received:You need to convert the Roman numerals I provided to integersReceived:\nRound 1:\nMMDCCCIX\n Roman numeral: MMDCCCIX Answer:2809Received:Correct!\n\nRound 2:\nMMMCXLIV\n Roman numeral: MMMCXLIV Answer:3144Received:Correct!\n\nRound 3:\nCMXCIII\n Roman numeral: CMXCIII Answer:993Received:Correct!\n\nRound 4:\nMCDLXI\n Answer:528......Received:Correct!\n\nRound 97:\nMMCDXLIV\n Roman numeral: MMCDXLIV Answer:2444Received:Correct!\n\nRound 98:\nMMMLXX\n Roman numeral: MMMLXX Answer:3070Received:Correct!\n\nRound 99:\nMMDCXII\n Roman numeral: MMDCXII Answer:2612Received:Correct!\n\nRound 100:\nDCCXXXII\n Roman numeral: DCCXXXII Answer:732Received:Correct!\n\nCongratulations! Here is your flag:\nqsnctf{e1dc67cb2e7b4cf6a6247939ce2acdc7}\nFound flag!Correct!Congratulations!Here is your flag: qsnctf{e1dc67cb2e7b4cf6a6247939ce2acdc7}