# 一见如故

又是 mt19937 系列的

class Myrand():
	def __init__(self,seed):
		self.index = 0
		self.isInit = 1
		self.MT = [seed] + [0] * 623
		for i in range(1,624):
			t = 1314433253 * (self.MT[i-1] ^ (self.MT[i-1] >> 30)) + 1
			self.MT[i] = t & 0xffffffff
	def generate(self):
		for i in range(624):
			y = (self.MT[i] & 0x80000000) + (self.MT[(i+1)%624] & 0x7fffffff)
			self.MT[i] = self.MT[(i+397)%624] ^ (y >> 1)
			if y & 1:
				self.MT[i] ^= 2567483520
	def rand(self):
		if self.index == 0:
			self.generate()
		y = self.MT[self.index]
		y = y ^ self.cs2l(y, 11) ^ self.cs2l(y,15)
		y = y ^ self.cs2r(y,7) ^ self.cs2r(y,19)
		self.index = (self.index + 1) % 624
		return y
	def cs2l(self, y, shift):
		return ((y << shift) ^ (y >> (32 - shift))) & 0xffffffff
 
	def cs2r(self, y, shift):
		return ((y >> shift) ^ (y << (32 - shift))) & 0xffffffff
import os
r = Myrand(int(os.urandom(4).hex(),16))
out = []
for i in range(624):
	out.append(r.rand())
with open("output.txt","w") as f:
	f.write(str(out))
from hashlib import md5
flag = 'flag{' + md5(str(r.rand()).encode()).hexdigest() + '}'
print(flag)

rand () 有点不一样,是循环异或,在网上找到了可逆的脚本

# 破解右移
def decrypted_first(y, key):
    for _ in range(32):
        y = y ^ cs2r(y, key[0]) ^ cs2r(y, key[1])
        key = [k << 1 for k in key]
    return y
# 破解左移
def decrypted_second(y, key):
    for _ in range(32):
        y = y ^ cs2l(y, key[0]) ^ cs2l(y, key[1])
        key = [k << 1 for k in key]
    return y

然后就可以求了

def cs2l( y, shift):
    shift %= 32
    return ((y << shift) ^ (y >> (32 - shift))) & 0xffffffff
def cs2r( y, shift):
    shift %= 32
    return ((y >> shift) ^ (y << (32 - shift))) & 0xffffffff
def aa(y):
    y = y ^ cs2l(y, 11) ^ cs2l(y,15)
    y = y ^ cs2r(y,7) ^ cs2r(y,19)
    return y
def decrypted_first(y, key):
    for _ in range(32):
        y = y ^ cs2r(y, key[0]) ^ cs2r(y, key[1])
        key = [k << 1 for k in key]
    return y
# 破解左移
def decrypted_second(y, key):
    for _ in range(32):
        y = y ^ cs2l(y, key[0]) ^ cs2l(y, key[1])
        key = [k << 1 for k in key]
    return y
key_r=[7,19]
key_l=[11,15]
mm=[1789930006, 1667540600, 1001134734, 2771087402, 1555158361, 3802425413, 186740355, 3238827425, 3822371986, 105656880, 2147674756, 4002398195, 999630311, 1043379329, 1844438614, 1573901879, 809580137, 1920530747, 3068490029, 188533208, 2352442425, 1356383568, 2045787189, 41701596, 2897419387, 1607593844, 3662695680, 3047281611, 2550334039, 3570740927, 1611931707, 2189890620, 4237125709, 696324445, 4021392896, 1806994450, 2017807642, 2469125736, 734874395, 1366419998, 2557317677, 2318441391, 1527271185, 739939051, 403949506, 2981867143, 3479641228, 1959324850, 38609469, 1962013477, 3446172738, 1254910762, 498476574, 255458888, 3793625513, 1630158993, 2279485383, 3669744498, 1492854939, 4097328621, 3192323478, 2071597028, 630826397, 428827189, 2368696996, 3055253655, 593469606, 3076863624, 55835342, 2766583770, 154612766, 2291460996, 2457259482, 3820553176, 1285798282, 3380034060, 3785911726, 281115523, 1685346148, 346211580, 589754395, 3153381906, 133879663, 2099773182, 4085199561, 4289422268, 1845420994, 4276887982, 2578038523, 3104059048, 3840618724, 3517595196, 1437174425, 331861497, 3020629410, 3612884080, 2364533907, 650538235, 3732309667, 3952278564, 27956256, 873990544, 1106130616, 4062763861, 1345922125, 1949409112, 543740334, 2356386296, 362665448, 569292348, 2417069446, 856220117, 610337377, 3715002089, 75605257, 1359669327, 549235605, 4147201887, 828943849, 3241074648, 3798702438, 4062212606, 2292101898, 2536161810, 2058208049, 1371637722, 3537388759, 2330897706, 771687299, 1810758562, 4075266992, 3136752169, 2965867171, 1907532906, 541865577, 833813451, 912325166, 3504529207, 4146661260, 43513704, 1188055084, 1460669959, 1441372078, 965044416, 1376283370, 1008912061, 2828206579, 2979859088, 1336911334, 2267227202, 3590615152, 2027071742, 4165198949, 2476117139, 4113179387, 842152977, 3334863091, 3208261808, 2491700976, 2416025359, 909914002, 1456853392, 584405349, 3450410558, 1008058255, 2173899613, 3454522095, 852025171, 4068323283, 1835293050, 2776504669, 2896956540, 1059582696, 3355842312, 3785046506, 3150432227, 899248345, 765362151, 297765964, 1839721704, 4135076330, 3802971234, 174032740, 330869440, 806730448, 2836319408, 1204866576, 1453685093, 1780827587, 2465584847, 485334173, 2258975595, 1604958487, 3091044353, 3654969666, 3179521007, 2914051939, 3077520681, 3529930595, 91469044, 100193981, 599625224, 175812373, 730628631, 264187248, 1956283294, 3644810780, 50475246, 3129247701, 3163094393, 2355260862, 436241481, 2960675442, 507658429, 1438698679, 554120231, 3160228468, 2149714696, 3217008673, 2829426481, 2509658698, 160550864, 998344493, 3224059883, 3706071477, 4013203721, 3039203009, 1900724496, 599236194, 1909569250, 3861601181, 2563580453, 2673673488, 1811137326, 1551186191, 1335639405, 1814773819, 2487495823, 1553705944, 4152430522, 3813662590, 939620828, 837675780, 1556020329, 3795725159, 2611629000, 2383061798, 171350680, 3683361407, 2953427424, 156701361, 1394830409, 1479716728, 1663136970, 1905123702, 3880810480, 3741001193, 4195599478, 3119408159, 3345902277, 1692442050, 418072450, 466246575, 3584148391, 1286172340, 3298303405, 153813789, 251189750, 1406369637, 1255015138, 164783996, 3071333073, 2013577078, 4169783817, 67626950, 908042796, 1581987189, 2808914198, 3187755899, 4150429886, 1568391086, 2787622463, 44688232, 2752263608, 600382819, 2685059730, 2082696936, 1651886831, 3260180554, 1454325295, 339099905, 2416413405, 292264001, 224448308, 2820205760, 800750924, 1692655009, 2940110853, 3206125267, 1284023574, 188806571, 1018253822, 1218521588, 127630641, 4272005916, 1983115840, 3724335557, 1480875599, 258556015, 387690320, 3307867721, 4092260344, 411103465, 719069720, 4215323854, 4112776693, 2889404156, 3574835124, 1159298981, 2305866473, 3158909197, 2452926716, 3463698794, 4186406925, 619215353, 2136303535, 841071810, 4209975253, 1563920806, 2788664963, 2285692078, 164748453, 3260915529, 2078551236, 1108180616, 2313020701, 2711601953, 3040284072, 4061505008, 3080883125, 46794326, 2539557719, 4235587220, 3713965477, 483788504, 2241106354, 400682955, 3283095717, 1851426695, 1064000523, 972160394, 1076563962, 1753602608, 1375888517, 1174039560, 4004713212, 2778702664, 2391507606, 2502750773, 3138779242, 3696713679, 3532841104, 515077954, 2342382087, 3418303246, 1721076811, 4019877170, 3829378939, 843608060, 1700376709, 649828753, 3070886865, 3433695660, 3059502160, 216554272, 2738464975, 2474575567, 3905056712, 645624775, 94893154, 2265734034, 2278406680, 566706528, 1904629525, 1293783964, 2146173917, 811121006, 3729400006, 3517862941, 195028545, 791864928, 1645052848, 1415212344, 1820637799, 362298413, 3473886649, 452928246, 898416880, 233774116, 1645021426, 3987051044, 39196131, 121419869, 2351563057, 680652927, 857972607, 3029438980, 1229946962, 233655181, 521122864, 2183657742, 484407290, 914882001, 146950515, 1082974333, 874762514, 3422883704, 3485156975, 3435115319, 2818202953, 3586825327, 2480062760, 3425716891, 1450326644, 3016221424, 2839134064, 2757606141, 2225601033, 3015322180, 1475949095, 2911465824, 1922094339, 383821393, 4250196262, 1199207077, 1170250221, 4010073388, 3538244808, 1066047253, 3579784593, 1100739262, 442414517, 1424751121, 490632186, 77339557, 777239460, 94846550, 2041789208, 1088291027, 1088989393, 1996188731, 1922726080, 173542137, 1660633903, 42490668, 4175299400, 546941808, 389670698, 4087711464, 953403827, 2689272300, 146383210, 991964967, 589177132, 2666116981, 2742384553, 2256937027, 3362235285, 1768372794, 2301508627, 3039631246, 4029873796, 3542162044, 4011314855, 3208705188, 3093664599, 955117791, 1898323176, 481158655, 1739494699, 3999748502, 2748166481, 1468096930, 269614143, 2539058881, 2437163900, 116042410, 2888056328, 3166050770, 764018772, 2895875342, 295377743, 301081897, 3242097759, 4133492089, 121772966, 3507787903, 857540916, 1013203234, 2930783587, 160548021, 1098790273, 6930677, 377945170, 1426843203, 30674711, 4194624825, 2844475300, 4050845555, 540285564, 4153161923, 3285107975, 3804387100, 1041301233, 1372558892, 2049773675, 975400211, 1602341781, 2428168445, 727020991, 3642365909, 2995017542, 1121830157, 1135422177, 1446184945, 1954739253, 2512295081, 1243062575, 2888686736, 1345095331, 2776320960, 2520780914, 3030218952, 3507873505, 566559925, 607563266, 2760603675, 2559643053, 370523859, 4152951015, 420593291, 3641300208, 4090307006, 4030514342, 3982102048, 3448920208, 3333296945, 2890840327, 403831131, 3053314412, 3541216602, 451345357, 2160618328, 4219999429, 334887708, 303960012, 2746583794, 167680781, 2646881889, 2222628925, 1589802426, 3647326978, 4214450178, 3942275726, 1184937518, 414660795, 4279106429, 3994881863, 1665475094, 3978476438, 417885097, 1914795868, 102257118, 2758276810, 528295518, 3523517380, 721631837, 4139270503, 239587328, 1468101505, 2955694973, 244330841, 3087815728, 1829583230, 416887979, 2145765582, 324272834, 2842681465, 3300197476, 1981480955, 3111840730, 819777040, 2973685169, 414658425, 149938512, 571957804, 1917410782, 1997835257, 4207405089, 3980449531, 1117683541, 1723925501, 3325014266, 3363338245, 2344916144, 3220067359, 3726608337, 175710897, 2941327892, 1316886944, 1279444044, 610743939, 2680076058, 1001211105, 3037856246, 207632498, 2702573225, 2008747623, 1711166061, 3635886836, 2103874588, 3661613767, 3624138576, 620466897]
MT=[]
for i in mm:
    MT.append(decrypted_second(decrypted_first(i,key_r),key_l))
def generate():
    for i in range(624):
        y = (MT[i] & 0x80000000) + (MT[(i + 1) % 624] & 0x7fffffff)
        MT[i] = MT[(i + 397) % 624] ^ (y >> 1)
        if y & 1:
            MT[i] ^= 2567483520
def rand(index=0):
    if index == 0:
        generate()
    y = MT[index]
    y = y ^ cs2l(y, 11) ^ cs2l(y, 15)
    y = y ^ cs2r(y, 7) ^ cs2r(y, 19)
    index = (index + 1) % 624
    return y
from hashlib import md5
flag = 'flag{' + md5(str(rand()).encode()).hexdigest() + '}'
print(flag)

# 二眼情深

class Myrand():
    def __init__(self, seed):
        self.index = 0
        self.isInit = 1
        self.MT = [seed] + [0] * 623
        for i in range(1, 624):
            t = 2037740385 * (self.MT[i - 1] ^ (self.MT[i - 1] >> 30)) + 1
            self.MT[i] = t & 0xffffffff
    # print(self.MT)
    def generate(self):
        for i in range(624):
            y = (self.MT[i] & 0x80000000) + (self.MT[(i + 1) % 624] & 0x7fffffff)
            self.MT[i] = self.MT[(i + 397) % 624] ^ (y >> 1)
            if y & 1:
                self.MT[i] ^= 2567483520
    # print(self.MT)
    def rand(self):
        if self.index == 0:
            self.generate()
        y = self.MT[self.index]
        y = y ^ self.cs2l(y, 11) ^ self.cs2l(y, 15)
        y = y ^ self.cs2r(y, 7) ^ self.cs2r(y, 19)
        self.index = (self.index + 1) % 624
        return y
    def cs2l(self, y, shift):
        return ((y << shift) ^ (y >> (32 - shift))) & 0xffffffff
    def cs2r(self, y, shift):
        return ((y >> shift) ^ (y << (32 - shift))) & 0xffffffff
import socketserver
import os
class Task(socketserver.BaseRequestHandler):
    def _recvall(self):
        BUFF_SIZE = 2048
        data = b''
        while True:
            part = self.request.recv(BUFF_SIZE)
            data += part
            if len(part) < BUFF_SIZE:
                break
        return data.strip()
    def send(self, msg, newline=True):
        try:
            if newline:
                msg += b'\n'
            self.request.sendall(msg)
        except:
            pass
    def recv(self, prompt):
        self.send(prompt, newline=False)
        return self._recvall()
    def handle(self):
        secret = int(os.urandom(4).hex(), 16)
        r = Myrand(secret)
        out = []
        for i in range(624):
            out.append(r.rand())
        try:
            for i in range(2):
                a = int((self.recv(b"Your " + ['first', 'second'][i].encode() + b" see: ")).decode())
                self.send(str(out[a % len(out)]).encode())
                guess = int((input("You konw my secret? ")).decode())
                if guess == secret:
                    self.send(b"For you ~")
                    flag = open("flag", "rb").read()
                    self.send(flag)
                    exit()
                else:
                    self.send(["Try again~ ", "Bye~"][i].encode())
        except Exception as e:
            exit()
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass
class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
    pass
if __name__ == "__main__":
    HOST, PORT = '0.0.0.0', 80
    server = ForkedServer((HOST, PORT), Task)
    server.allow_reuse_address = True
    print(HOST, PORT)
    server.serve_forever()

交互的到两个数据,要求出 seed

昨天刚做过的 NPUCTF2020 Mersenne twister

也是两个数据恢复 seed

脚本参考

我们获取 s0 和 s227

227+397 %624 =0

然后求出 s228

def backtrace(cur):
    high = 0x80000000
    low = 0x7fffffff
    mask = 2567483520
    state = cur
    tmp = state[1]^state[0]
    if tmp & high == high:
        tmp ^= mask
        tmp <<= 1
        tmp |= 1
    else:
        tmp <<=1
    # recover highest bit
    state= tmp
    return state

再逆_init_

def invert_right(res,shift):
    tmp = res
    for i in range(32//shift):
        res = tmp^res>>shift
    return res&0xFFFFFFFF
def recover(last):
    n = 1<<32
    inv = invert(2037740385,n)
    for i in range(228,0,-1):
        last = ((last-i)*inv)%n
        last = invert_right(last,30)
    return last

完整 exp

from Crypto.Util.number import inverse
from gmpy2 import invert
from pwn import *
def cs2l( y, shift):
    shift %= 32
    return ((y << shift) ^ (y >> (32 - shift))) & 0xffffffff
def cs2r( y, shift):
    shift %= 32
    return ((y >> shift) ^ (y << (32 - shift))) & 0xffffffff
#破解右移
def decrypted_first(y, key):
    for _ in range(32):
        y = y ^ cs2r(y, key[0]) ^ cs2r(y, key[1])
        key = [k << 1 for k in key]
    return y
# 破解左移
def decrypted_second(y, key):
    for _ in range(32):
        y = y ^ cs2l(y, key[0]) ^ cs2l(y, key[1])
        key = [k << 1 for k in key]
    return y
def backtrace(cur):
    high = 0x80000000
    low = 0x7fffffff
    mask = 2567483520
    state = cur
    tmp = state[1]^state[0]
    if tmp & high == high:
        tmp ^= mask
        tmp <<= 1
        tmp |= 1
    else:
        tmp <<=1
    # recover highest bit
    state= tmp
    return state
def invert_right(res,shift):
    tmp = res
    for i in range(32//shift):
        res = tmp^res>>shift
    return res&0xFFFFFFFF
def recover(last):
    n = 1<<32
    inv = invert(2037740385,n)
    for i in range(228,0,-1):
        last = ((last-1)*inv)%n
        last = invert_right(last,30)
    return last
re=remote("ctf.mxx307.com", 28041)
re.recvuntil(b'Your first see:')
re.sendline(b'0')
s=[]
s.append(int(re.recvline().decode().strip()))
re.recvuntil(b'You konw my secret?')
re.sendline(b'1')
re.recvuntil(b'Your second see:')
re.sendline(b'227')
s.append(int(re.recvline().decode().strip()))
key_r=[7,19]
key_l=[11,15]
for i in range(len(s)):
    s[i]=decrypted_second(decrypted_first(s[i],key_r),key_l)
print(s)
s228=backtrace(s)
print(s228)
seed=(recover(s228))
print(seed)
re.sendline(str(seed).encode())
re.interactive()