xor
最简单的签到,但对完完全全零基础的同学来说,这道题涉及的知识点可能还不少,我们看题。
from pwn import xor
from Crypto.Util.number import bytes_to_long
key = b'New_Star_CTF'
flag='flag{*******************}'
m1 = bytes_to_long(bytes(flag[:13], encoding='utf-8'))
m2 = flag[13:]
c1 = m1 ^ bytes_to_long(key)
c2 = xor(key, m2)
print('c1=',c1)
print('c2=',c2)首先使用了两个 Python 库,pwntools 是 CTF nc 题的交互好工具(不仅仅是 pwn 题,密码、Misc 等的交互题也会用到),pycryptodome 是一个好用的密码学加密库。确保 Python 环境正常后,在终端中分别输入以下命令进行安装:
pip install pwntools
pip install pycryptodome这些库未来它们会是你的好帮手。这里展现的功能都只是冰山一角,具体功能是什么我们稍后解释。
此处出题人刻意地定义 key 为 bytes 类型而 flag 为 str 类型。Python3 重要的特性之一是对字符串和二进制数据流做了明确的区分。文本总是 Unicode,由 str 类型表示,二进制数据则由 bytes 类型表示。Python3 不会以任意隐式的方式混用 str 和 bytes,你不能拼接字符串和字节流,也无法在字节流里搜索字符串(反之亦然),也不能将字符串传入参数为字节流的函数(反之亦然)。需要进行编码操作才能转换为 bytes 类型进行后续的运算。大家可以通过这两篇博客详细了解:
接着是 bytes_to_long 函数,从函数名也可以猜出来,这个函数是将 bytes 类型转换为数字,具体是怎么转换的?大家可以尝试的将最后的整数变成 16 进制来看,举个例子:
text=b'NewStar'
print(bytes_to_long(text))
# 22066611359080818
print(hex(bytes_to_long(text)))
# 0x4e657753746172从 16 进制来看就很直观了 0x4e657753746172,N 的 ASCII 值是 e 的 ASCII值是 bytes 类型的 NewStar 转成了一个整数。
那么我们终于进入了这道题考查的重点——异或(XOR),在某些书中也称它为「模二加」。异或运算的规则是:
- 当两个输入位不同时,输出为
1 - 当两个输入位相同时,输出为
0
就像不进位的模2加法一样。异或在编程语言中常用符号 ^ 表示,在数学中常用符号
当两个数异或之后,异或的结果与其中一个数再异或即可得到剩下的一个数字。此处我使用了 2 种方式进行异或:一个是直接用 ^ 对整数进行运算;另一个是用 pwntools 中的 xor(),它可以将不同类型和长度的数据进行异或。
既然已知 key 的话,利用异或的性质,再异或 1 次即可获得 flag.
from pwn import xor
from Crypto.Util.number import long_to_bytes,bytes_to_long
key = b'New_Star_CTF'
c1 = 8091799978721254458294926060841
c2 = b';:\x1c1<\x03>*\x10\x11u;'
m1 = c1 ^ bytes_to_long(key)
m2 = xor(key, c2)
flag = long_to_bytes(m1) + m2
print(flag)
# flag{0ops!_you_know_XOR!}