我是菜鸡,我是菜鸡,我是菜鸡,重要的事情说三遍。
Crypto
1. bbcrypto
这个...直接就解同余方程组。
#! /usr/bin/env python3
from Crypto.Util.number import inverse
from itertools import cycle
hexstr = "177401504b0125272c122743171e2c250a602e3a7c206e014a012703273a3c0160173a73753d"
[x1, x2, x3, x4, x5] = [ord("flag{"[i]) for i in range(5)]
[c1, c2, c3, c4, c5] = [int(hexstr[2*i:2*(i+1)],16) for i in range(5)]
a1 = (c4-c1)*inverse((x4-x1), 128) % 128
a2 = (c5-c2)*inverse((x5-x2), 128) % 128
assert a1 == a2
a = a1
b1 = (c1 - a * x1) % 128
b2 = (c2 - a * x2) % 128
b3 = (c3 - a * x3) % 128
a_ = inverse(a, 128)
salt = [b1, b2, b3]
si = cycle(salt)
cycletimes = len(hexstr) // 2
clist = [int(hexstr[2*i:2*(i+1)],16) for i in range(cycletimes)]
flag = b""
for i in range(cycletimes):
flag += bytes([(clist[i]-next(si))*a_ % 128])
print(flag)
2. Encrypt_Img
这个其实也能想到。首先看到了Plaintext1和Plaintext2的长度差1,又发现是RC4流加密。设Key产生的密钥流是Keystream,那么
因为已知,因此可以求得前P1和P2长度的,其中。
设现在是加密到了图像(Image)的第i字节,那么有
现在已知,想求。
,即
那么
以此类推,能求得全部的Keystream和Image。
from numpy import array
from PIL import Image
from Crypto.Util.number import long_to_bytes, bytes_to_long
Plaintext1 = "RC4IsInteresting"
Plaintext2 = "ThisIsAEasyGame"
ciphertext1 = 12078640933356268898100798377710191641
ciphertext2 = 79124196547094980420644350061749775
keystream1 = long_to_bytes(bytes_to_long(Plaintext1.encode()) ^ ciphertext1)
keystream2 = long_to_bytes(bytes_to_long(Plaintext2.encode()) ^ ciphertext2)
keystream = [keystream1[0]]
enc1 = Image.open(r"enc1.png")
enc2 = Image.open(r"enc2.png")
img1 = array(enc1)
img2 = array(enc2)
a, b, _ = img1.shape
m = 0
for i in range(a):
for j in range(b):
pixel1 = img1[i][j]
pixel2 = img2[i][j]
for k in range(3):
pixel2[k] ^= keystream[m]
keystream.append(pixel1[k]^pixel2[k])
m += 1
img2[i][j] = pixel2
dec = Image.fromarray(img2)
# dec.show()
dec.save("flag.png")
3. easyLCG
LCG写C语言开满优化爆破就完事啦
#include <stdio.h>
#include <limits.h>
const __int64 a = 3844066521;
const __int64 b = 3316005024;
const __int64 m = 2249804527;
const __int64 state1 = 16269;
const __int64 state2 = 4249;
int main() {
__int64 i = 0;
__int64 seed;
for (;;) {
seed = (a*i + b) % m;
if ((seed >> 16) == state1) {
seed = (a*seed + b) % m;
if ((seed >> 16) == state2) {
printf("%lld", i);
return 0;
}
}
if (i == UINT_MAX) break;
i++;
}
}
#/usr/bin/env python3
from Crypto.Util.number import *
class LCG:
def __init__(self):
self.a = 3844066521
self.b = 3316005024
self.m = 2249804527
self.seed = 714405490 # 写C开满优化爆破
def next(self):
self.seed = (self.a*self.seed+self.b) % self.m
return self.seed >> 16
def output(self):
print("a = {}\nb = {}\nm = {}".format(self.a, self.b, self.m))
print("state1 = {}".format(self.next()))
print("state2 = {}".format(self.next()))
class DH:
def __init__(self):
self.lcg = LCG()
# self.lcg.output()
self.g = 183096451267674849541594370111199688704
self.m = 102752586316294557951738800745394456033378966059875498971396396583576430992701
self.A, self.a = self.gen_AB()
self.B, self.b = self.gen_AB()
self.key = pow(self.A, self.b, self.m)
def gen_AB(self):
x = ''
for _ in range(64):
x += '1' if self.lcg.next() % 2 else '0'
return pow(self.g, int(x, 2), self.m), int(x, 2)
dh = DH()
Cipher = 13040004482819935755130996285494678592830702618071750116744173145400949521388647864913527703
Plaintext = Cipher ^ dh.key
print(long_to_bytes(Plaintext))