题目如下所示,考点是仿射密码:

下面是对仿射密码的一个简介,仿射密码对相同字母加密后的结果是一样的,这是一个入手点:

题目说这是一个图片文件,一般想到有png和jpg两种,先看下一张普通png图片的hex数据:


可以看到明显和题目给的bin文件有相同的重复,说明这个bin文件就是png图片经过仿射密码加密得到的,一般一个简单的仿射密码的字母表长度为英文字母的总数26,而这里应该是ascii码的总数256,所以需要在网上找到的脚本上改下关键数值,目前我们已知了部分明文,就可以通过这部分得到密钥key,也就是a和b的值,之后再算出a的逆元,就可以decode出原来的图片了,爆破脚本如下所示:
#coding:utf-8
png = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]
zakukozh = [0x60, 0x09, 0xeb, 0x82, 0x1c, 0xef, 0xdf, 0xef]
for a in range(3,256):
for b in range(0,256):
x=[]
for i in range(len(png)):
x.append((a*png[i]+b)%256)
if x == zakukozh:
print a,b
exit(0)

得出结果a=15,b=89,可以再计算下a的逆元,也是通过爆破的方式:
#coding:utf-8
png = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]
zakukozh = [0x60, 0x09, 0xeb, 0x82, 0x1c, 0xef, 0xdf, 0xef]
b=89
for a in range(3,256):
x=[]
for i in range(len(zakukozh)):
x.append(a*(zakukozh[i]-b)%256)
if x == png:
print a,b
exit(0)

可以得出a的乘法逆元为239,现在就可以复原png图片了,将decode的每一个字节写入即可:
f=open("zakukozh.bin",'rb')
f1=open("flag.png",'wb')
a=239
b=89
x=''
for i in f.read():
x+=chr(a*(ord(i)-b)%256)
f1.write(x)
f.close()
f1.close()

网友评论