###### tags: `writeups`
# Writeup for Zakukozh in CyBRICS
## Description
题目描述如下图:

意思是说,这是一个被`Affine Cipher`(仿射密码)加密过的一个图片文件,试着解密。
## Analysis
仿射密码是个什么东西? [wiki](https://zh.wikipedia.org/wiki/%E4%BB%BF%E5%B0%84%E5%AF%86%E7%A2%BC)

说白了,就是一个线性变换。
看到只是mod 26,心里一喜,爆破分分钟啊。瞬间又意识到这是个二进制文件,应该不会是mod 26这么简单,估计是mod 256,但这个爆破也分分钟(后面可以看到,其实都不要用1秒)。
题目里面另外一个信息:**图片**
图片格式也就那么几种,能说的上来的也就`png`,`jpg`,... 好吧,说不出来了。
那么。。直接拖进`WinHex`,再把一个真正的`png`图片拖进来,对比分析一下:

仿射密码就说明,映射是一一对应的。这可以从上图看出,`png`里面一样的byte,在映射后的`bin`中也是一样的!由此推断:是`png`格式的图片没错了。
开始写脚本喽!
## Script
这肯定是mod 256了,有两个未知数`a, b`,那么就有256*256=65536种可能,爆破起来肯定不要太快。其实,仿射密码里的`a`是有限制的,要满足`gcd(a, 256) == 1`,这样还可以减少点计算量。
爆破`a, b`:
```python
from Crypto.Util.number import GCD, inverse
# d^-1(x) = a^-1 (x - b) % 256
pre = [0x89, 0x50, 0x4e]
post = [0x60, 0x09, 0xeb]
for a in range(256):
if GCD(a,256)!=1:
continue
inv_a = inverse(a, 256)
for b in range(256):
q = 1
for i in range(3):
if (inv_a * (post[i] - b) ) % 256 != pre[i]:
q=0
break
if(q):
print(a, b)
# 15, 89
```
结果瞬间就有了,`a = 15, b = 89`。那么接下来只需要一个一个解密就行了:
```python
a = 15
inv_a = 239
b = 89
with open("zakukozh.bin", "rb") as f1:
t = f1.read()
with open("flag.png", "wb") as f2:
for c in t:
p = inv_a * (c - b) % 256
f2.write(bytes[p])
```
打开写好的文件,获得`flag`:

## Summary
还是需要再深入了解下图片文件的格式,这样分析起来就更有感觉了。