Tags: Crypto wp.
Categories: write up.

图片加密捏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from PIL import Image
from Crypto.Util.number import *
from numpy import array, zeros, uint8
import gmpy2 as gp
import cv2
from key import x,y,kn,hint
image = cv2.imread("flag.jpg")
img_gray = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
imagearray = array(img_gray)
h = len(imagearray)
w = len(imagearray[0])

assert 1301149798051259562945444365741194129602596348352064372203373*pow(x, 2) == 1175915431138623881271508290982969935822476052419526528443170552123*pow(y, 2) + 1301149798051259562945444365741194129602596348352064372203373
x1 = round(x/y*0.001, 16)
u1 = y*3650/x
x2 = round(x/y*0.00101, 16)
u2 = y*3675/x
x3 = round(x/y*0.00102, 16)
u3 = y*3680/x
kt = [x1, x2, x3]

temp_image = zeros(shape=[h, w, 3], dtype=uint8)
print(len(temp_image))
print(len(temp_image[0]))
print(len(temp_image[0][1]))
for k in range(0, kn):
for i in range(0, h):
for j in range(0, w):
x1 = u1 * x1 * (1 - x1)
x2 = u2 * x2 * (1 - x2)
x3 = u3 * x3 * (1 - x3)
r1 = int(x1*255)
r2 = int(x2*255)
r3 = int(x3*255)
for t in range(0, 3):
temp_image[i][j][t] = (((r1+r2) ^ r3)+imagearray[i][j][t]) % 256
x1 = kt[0]
x2 = kt[1]
x3 = kt[2]

encflagarray = Image.fromarray(temp_image)
encflagarray.show()
encflagarray.save("encflag.jpg")
#************************************hint**************************************
m = hint
p = getPrime(512)
q = getPrime(512)
n = p * q
e = 65537
phi = (p-1)*(q-1)
dp = gp.invert(e, p-1)
c = pow(m, e, n)
#n = 85413323752199019806030766630760449394238054889872415531186815348349883843039718091361611175963675771467536496812507338620957273406076058263122453235926619595761737396698699834116678598534261542535530241537247151318756003375573850725841254167462648747492270335084402716816450008370008491069875351593380154253
#dp = 1576424214336939000475035870826282526256046059505538052583882122452307602095912733650442447289122473348318614749578285418144935611098423641334952097553125
#c = 53653254613997095145108444611576166902006080900281661447007750088487109015427510365774527924664116641019490904245926171500894236952984157500461367769566121581870986304353174732328118576440353500038670030097108081972287049673200783198844842527470746431369314585103203118824985764754487936404004696485346196488

加密代码中给了个hint,一眼dp泄露,解出来后是hint = *********** kn = 8 **************

接下来就是对加密过程进行求解。审代码,发现加密过程用到的x和y都是由

1301149798051259562945444365741194129602596348352064372203373*pow(x, 2) == 1175915431138623881271508290982969935822476052419526528443170552123*pow(y, 2) + 1301149798051259562945444365741194129602596348352064372203373

这样一个方程给出的,将系数化简一下发现这个方程的形式满足佩尔方程 由于非平凡情形的佩尔方程有多解,所以我们只用求出最小整数解就行了

求出x,y之后再逆一下图片加密的算法,这里逆的算法为:

1
temp_image[i][j][t] = (((r1+r2) ^ r3)+imagearray[i][j][t]) % 256

逆后:

1
temp_image[i][j][t] = (imagearray[i][j][t]-((r1+r2) ^ r3)) % 256

这样就可以将图片恢复

完整exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
from PIL import Image
from numpy import array, zeros, uint8
import cv2
import math

def solvePell(n):
x = int(math.sqrt(n))

y, z, r = x, 1, x << 1

e1, e2 = 1, 0
f1, f2 = 0, 1
while True:
y = r * z - y
z = (n - y * y) // z
r = (x + y) // z

e1, e2 = e2, e1 + e2 * r
f1, f2 = f2, f1 + f2 * r

a, b = f2 * x + e2, f2
if a * a - n * b * b == 1:
return a, b

a = 1301149798051259562945444365741194129602596348352064372203373
b = 1175915431138623881271508290982969935822476052419526528443170552123
n = b//a
x,y = solvePell(n)
kn = 8

image = cv2.imread("encflag_1.jpg")
img_gray = image
imagearray = array(img_gray)
h = len(imagearray)
w = len(imagearray[0])

assert 1301149798051259562945444365741194129602596348352064372203373*pow(x, 2) == 1175915431138623881271508290982969935822476052419526528443170552123*pow(y, 2) + 1301149798051259562945444365741194129602596348352064372203373
x1 = round(x/y*0.001, 16)
u1 = y*3650/x
x2 = round(x/y*0.00101, 16)
u2 = y*3675/x
x3 = round(x/y*0.00102, 16)
u3 = y*3680/x
kt = [x1, x2, x3]

temp_image = zeros(shape=[h, w, 3], dtype=uint8)
print(len(temp_image))
print(len(temp_image[0]))
print(len(temp_image[0][1]))
for k in range(0, kn):
for i in range(0, h):
for j in range(0, w):
x1 = u1 * x1 * (1 - x1)
x2 = u2 * x2 * (1 - x2)
x3 = u3 * x3 * (1 - x3)
r1 = int(x1*255)
r2 = int(x2*255)
r3 = int(x3*255)
for t in range(0, 3):
temp_image[i][j][t] = (imagearray[i][j][t]-((r1+r2) ^ r3)) % 256
x1 = kt[0]
x2 = kt[1]
x3 = kt[2]

encflagarray = Image.fromarray(temp_image)
encflagarray.show()
encflagarray.save("flag.jpg")

yysy,不知道为什么解密脚本和图片不在同一路径就会报错(悲

记几个用到的库函数

1
2
3
4
5
cv2.imread:读取图片
cv2.cvtColor:颜色空间转换。如RGB2BGR,RGB2CRAY
numpy.array:创建数组(支持多维)
numpy.zero:创建0矩阵(支持多维)
numpy.uint8:专门用于存储图像,范围0-255