# [SWPUCTF 2021 新生赛]简简单单的逻辑 # [SWPUCTF 2021 新生赛]简简单单的逻辑 ## 题目: ```py flag = 'xxxxxxxxxxxxxxxxxx' list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25] result = '' for i in range(len(list)): key = (list[i]>>4)+((list[i] & 0xf)<<4) result += str(hex(ord(flag[i])^key))[2:].zfill(2) print(result) # result=bcfba4d0038d48bd4b00f82796d393dfec ``` ​ ## 分析 - `>>`:位右移运算符。`x >> n` 表示将 `x` 的二进制表示向右移动 `n` 位,移出的位将被丢弃,左边则用符号位填充(对于带符号整数) - `<<`:位左移运算符。`x << n` 表示将 `x` 的二进制表示向左移动 `n` 位,在右边填充零 - `&`:按位与运算符。用于对两个二进制数的每一位执行与操作。对于每一对比特位,如果两个相应的位都是1,则结果位是1,否则是0 - `^`:按位异或运算符。它对两个二进制数的每一位执行异或操作。对于每一对比特位,如果两个相应的位不同,则结果位是1,如果相同则为0。 - `ord()`:将一个字符转换为对应的 ASCII 值 - `hex()`:将一个整数转换为十六进制字符串表示形式 - `str()`:将对象转换为字符串 - `[2:]`:切片。从第3位开始 - `zfill()`:在字符串的左侧填充零,使字符串达到指定的宽度。即如果字符串的长度小于指定的宽度,则在左侧用零进行填充 ​ ```py key = (list[i]>>4)+((list[i] & 0xf)<<4) ``` key 的算法不用在意,不管正向还是逆向 key 都不变 ```python result += str(hex(ord(flag[i])^key))[2:].zfill(2) ``` 将 flag 的每一个字符与 key 异或运算后转成 ascii 码再转成 16 进制再转成字符串再截取第 3 位开始之后的内容,如果内容长度不到 2 则在前面用 0 补上 ​ 逆向算法: 将 result 字符串每隔两个转成 10 进制再和 key 异或再转为 ascii 对应的字符 ```py flag = '' list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25] result = 'bcfba4d0038d48bd4b00f82796d393dfec' for i in range(len(list)): key = (list[i]>>4)+((list[i] & 0xf)<<4) flag+=chr(int(result[i*2:i*2+2],16)^key) print(flag) ``` - `chr()`:将 Unicode 码点转换为对应的字符 - `int(hex_str, 16)`:将 16 进制转成 10 进制