Introduction to CryptoHack
最后更新时间:
文章总字数:
这大概算是我的第一篇博客吧,想通过写博客来记录自己学习的过程,方便自己回顾或者帮助之后的初学者。
作为CTF初学者,目前最感兴趣且希望深入研究的是密码学-Crypto,校内的学长向我推荐了CryptoHack这个网站,有许多类似闯关的教程,接下来打算以此网站入门Crypto.
Finding Flags
Each challenge is designed to help introduce you to a new piece of cryptography. Solving a challenge will require you to find a “flag”.
These flags will usually be in the format
crypto{y0ur_f1rst_fl4g}
. The flag format helps you verify that you found the correct solution.Try submitting this flag into the form below to solve your first challenge.
第一道没什么好说的,介绍了CTF解题是要找出flag。这里flag已经给出,输入便可通关。
Great Snakes
Modern cryptography involves code, and code involves coding. CryptoHack provides a good opportunity to sharpen your skills.
Of all modern programming languages, Python 3 stands out as ideal for quickly writing cryptographic scripts and attacks. For more information about why we think Python is so great for this, please see the FAQ.
Run the attached Python script and it will output your flag.
Challenge files:
- great_snakes.pyResources:
- Downloading Python
第二道题则是介绍了Crypto解题需要的工具:Python.
我们打开附件
1 |
|
直接运行即可得到flag:crypto{z3n_0f_pyth0n}
ASCII
ASCII is a 7-bit encoding standard which allows the representation of text using the integers 0-127.
Using the below integer array, convert the numbers to their corresponding ASCII characters to obtain a flag.
1[99, 114, 121, 112, 116, 111, 123, 65, 83, 67, 73, 73, 95, 112, 114, 49, 110, 116, 52, 98, 108, 51, 125]
In Python, the
chr()
function can be used to convert an ASCII ordinal number to a character (theord()
function does the opposite).
第三题介绍了ASCII码以及Python中的相关函数。
我们进入Python写一段脚本
1 |
|
运行可得到flag:crypto{ASCII_pr1nt4bl3}
Hex
When we encrypt something the resulting ciphertext commonly has bytes which are not printable ASCII characters. If we want to share our encrypted data, it’s common to encode it into something more user-friendly and portable across different systems.
Hexadecimal can be used in such a way to represent ASCII strings. First each letter is converted to an ordinal number according to the ASCII table (as in the previous challenge). Then the decimal numbers are converted to base-16 numbers, otherwise known as hexadecimal. The numbers can be combined together, into one long hex string.
Included below is a flag encoded as a hex string. Decode this back into bytes to get the flag.
163727970746f7b596f755f77696c6c5f62655f776f726b696e675f776974685f6865785f737472696e67735f615f6c6f747d
In Python, the
bytes.fromhex()
function can be used to convert hex to bytes. The.hex()
instance method can be called on byte strings to get the hex representation.
第四题介绍了Hex,即16进制数。
在Python中可以使用bytes.fromhex()
和.hex()
实现bytes类型与hex类型的转换。
依旧是使用Python
1 |
|
运行可得到flag:crypto{You_will_be_working_with_hex_strings_a_lot}
Base64
Another common encoding scheme is Base64, which allows us to represent binary data as an ASCII string using an alphabet of 64 characters. One character of a Base64 string encodes 6 binary digits (bits), and so 4 characters of Base64 encode three 8-bit bytes.
Base64 is most commonly used online, so binary data such as images can be easily included into HTML or CSS files.
Take the below hex string, decode it into bytes and then encode it into Base64.
172bca9b68fc16ac7beeb8f849dca1d8a783e8acf9679bf9269f7bf
In Python, after importing the base64 module with
import base64
, you can use thebase64.b64encode()
function. Remember to decode the hex first as the challenge description states.
第五题介绍了另一个常用的编码:Base64. Base64使用一个64个字符的密码表,即
Base64中1个字符编码6个二进制数字,4个字符编码3个8位字节。
这道题的题目要求很明确,让我们解码为bytes类型再编码为Base64类型。
代码如下
1 |
|
Bytes and Big Integers
Cryptosystems like RSA works on numbers, but messages are made up of characters. How should we convert our messages into numbers so that mathematical operations can be applied?
The most common way is to take the ordinal bytes of the message, convert them into hexadecimal, and concatenate. This can be interpreted as a base-16/hexadecimal number, and also represented in base-10/decimal.
To illustrate:
message: HELLO
ascii bytes: [72, 69, 76, 76, 79]
hex bytes: [0x48, 0x45, 0x4c, 0x4c, 0x4f]
base-16: 0x48454c4c4f
base-10: 310400273487Convert the following integer back into a message:
111515195063862318899931685488813747395775516287289682636499965282714637259206269
Python’s PyCryptodome library implements this with the methods
bytes_to_long()
andlong_to_bytes()
. You will first have to install PyCryptodome and import it withfrom Crypto.Util.number import *
.
第六题介绍了bytes与大整数之间的换算,这在后面的RSA加密中也会用到。转换的具体步骤题目中也已经列出,不过我们实际计算只需要一段简单的代码
1 |
|
运行可得到flag:crypto{3nc0d1n6_4ll_7h3_w4y_d0wn}
XOR Starter
XOR is a bitwise operator which returns 0 if the bits are the same, and 1 otherwise. In textbooks the XOR operator is denoted by ⊕, but in most challenges and programming languages you will see the caret
^
used instead.
A B Output 0 0 0 0 1 1 1 0 1 1 1 0 For longer binary numbers we XOR bit by bit:
0110 ^ 1010 = 1100
. We can XOR integers by first converting the integer from decimal to binary. We can XOR strings by first converting each character to the integer representing the Unicode character.Given the string
label
, XOR each character with the integer13
. Convert these integers back to a string and submit the flag ascrypto{new_string}
.The Python
pwntools
library has a convenientxor()
function that can XOR together data of different types and lengths. But first, you may want to implement your own function to solve this.
这一题介绍了异或运算,当两个二进制数值相同时结果为0,不同时结果为1。
题目中介绍了利用pwntools
这个库可以快速进行异或运算,但建议我们第一次还是自己来做。
既然他都那么说了,我们就先不用这个库。当然实在想用也没关系
题目说将每一位都与13进行异或,那我们就先将每个字都转成对应的ASCII码,分别与13异或后再转回字符串
1 |
|
得到答案为crypto{aloha}
XOR Properties
In the last challenge, you saw how XOR worked at the level of bits. In this one, we’re going to cover the properties of the XOR operation and then use them to undo a chain of operations that have encrypted a flag. Gaining an intuition for how this works will help greatly when you come to attacking real cryptosystems later, especially in the block ciphers category.
There are four main properties we should consider when we solve challenges using the XOR operator
Commutative: A ⊕ B = B ⊕ A
Associative: A ⊕ (B ⊕ C) = (A ⊕ B) ⊕ C
Identity: A ⊕ 0 = A
Self-Inverse: A ⊕ A = 0Let’s break this down. Commutative means that the order of the XOR operations is not important. Associative means that a chain of operations can be carried out without order (we do not need to worry about brackets). The identity is 0, so XOR with 0 “does nothing”, and lastly something XOR’d with itself returns zero.
Let’s put this into practice! Below is a series of outputs where three random keys have been XOR’d together and with the flag. Use the above properties to undo the encryption in the final line to obtain the flag.
1
2
3
4KEY1 = a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313
KEY2 ^ KEY1 = 37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e
KEY2 ^ KEY3 = c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1
FLAG ^ KEY1 ^ KEY3 ^ KEY2 = 04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf
这一题介绍了异或运算的一些运算性质,更像是一道数学题。
逐步运算,将KEY消掉,得到
接下来就很简单了
1 |
|
得到答案为:crypto{x0r_i5_ass0c1at1v3}
Favourite byte
For the next few challenges, you’ll use what you’ve just learned to solve some more XOR puzzles.
I’ve hidden some data using XOR with a single byte, but that byte is a secret. Don’t forget to decode from hex first.
173626960647f6b206821204f21254f7d694f7624662065622127234f726927756d
这一题没有教什么新东西,撂下一串数字就让我们综合所学知识求解。
没什么思路,先转成bytes看一眼
b”sbi`d\x7fk h! O!%O}iOv$f eb!’#Ori’um”
是一串没有什么意义的字符,题目中说这串字符经过XOR加密,但我们并不知道密钥是什么。
穷举
既然如此,我们可以用穷举法依次尝试
1 |
|
1 |
|
可以在里面找到crypto{0x10_15_my_f4v0ur173_by7e},这便是答案了
倒推
从另一个角度想,虽然我们不知道密钥是什么,但我们知道答案一定是以crypto{
开头。那由异或的运算性质,将密文的第一位与c进行异或运算,得出的结果就是密钥了
1 |
|
输出结果为
16
b’crypto{0x10_15_my_f4v0ur173_by7e}’
You either know, XOR you don’t
I’ve encrypted the flag with my secret key, you’ll never be able to guess it.
10e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104
Remember the flag format and how it might help you in this challenge!
新手村的最后一题,提示中提到了flag形式,那就是暗示我们用倒推法解这道题
复制上一题的代码
1 |
|
得出结果…
109
b’cfLRKis%fKL\x12JYCz0cjgQ6}SHKL\x12JYCz0cj\x13KY<xli’
呃,好像不太对?
那就把所有已知片段都异或进去看看
1 |
|
b’myXORke+y_Q\x0bHOMe$~seG8bGURN\x04DFWg)a|\x1dTM!an\x7f’
myXORke+y……?
根据语义判断,密钥很可能是myXORkey,代入试试
1 |
|
b’crypto{1f_y0u_Kn0w_En0uGH_y0u_Kn0w_1t_4ll}’
显然这就是答案了。
新手村的内容到此就结束了,这一章节里学到了像ASCII码、16进制、Base64以及XOR运算等密码学中常用的内容,并且锻炼了一些使用Python解题的能力。下一章等什么时候有空再学吧(