中午才起床,舍友喊我起床恰烂钱。ak了密码。逆向只做了了一题。没时间了。不到五小时做了500分我个人感jio还行吧。
crypto
rsa
('c=', '0x7a7e031f14f6b6c3292d11a41161d2491ce8bcdc67ef1baa9eL')
('e=', '0x872a335')
#q + q*p^3 =1285367317452089980789441829580397855321901891350429414413655782431779727560841427444135440068248152908241981758331600586
#qp + q *p^2 = 1109691832903289208389283296592510864729403914873734836011311325874120780079555500202475594
入门难度,通过给出表达式轻松求出p和q
from Crypto.Util.number import *
from gmpy2 import *
a = 1285367317452089980789441829580397855321901891350429414413655782431779727560841427444135440068248152908241981758331600586
b = 1109691832903289208389283296592510864729403914873734836011311325874120780079555500202475594
e = 0x872a335
c = 0x7a7e031f14f6b6c3292d11a41161d2491ce8bcdc67ef1baa9e
gcd_ = gcd(a, b) # q*(1+p)
p = b // gcd_
q = b // (p*(p+1))
n = p * q
phi = (p-1)*(q-1)
d = inverse(e, phi)
m = pow(c, d, n)
print(long2str(m))
Yusa_cbc
from Crypto.Cipher import AES
import os
flag='flag{********************************}'
BLOCKSIZE = 16
def pad(data):
pad_len = BLOCKSIZE - (len(data) % BLOCKSIZE) if len(data) % BLOCKSIZE != 0 else 0
return data + "=" * pad_len
def unpad(data):
return data.replace("=","")
def enc(data,key,iv):
cipher = AES.new(key,AES.MODE_CBC,iv)
encrypt = cipher.encrypt(pad(data))
return encrypt
def dec(data,key,iv):
try:
cipher = AES.new(key,AES.MODE_CBC,iv)
encrypt = cipher.decrypt(data)
return unpad(encrypt)
except:
exit()
def task():
try:
key = os.urandom(16)
iv = os.urandom(16)
pre = "yusa"*4
for _ in range(3):
choice = raw_input(menu)
if choice == '1':
name = raw_input("What's your name?")
if name == 'admin':
exit()
token = enc(pre+name,key,iv)
print "Here is your token(in hex): "+iv.encode('hex')+token.encode('hex')
continue
elif choice == '2':
token = raw_input("Your token(in hex): ").decode('hex')
iv = token[:16]
name = dec(token[16:],key,iv)
print iv.encode('hex')+name.encode('hex')
if name[:16] == "yusa"*4:
print "Hello, "+name[16:]
if name[16:] == 'admin':
print flag
exit()
else:
continue
except:
exit()
menu='''
1. register
2. login
3. exit
'''
if __name__ == "__main__":
task()
cbc bit flipping攻击
两个密文块,通过改第一个密文块,可以使得第二个密文块解密出admin.
但是这会使得第一个密文块解密出乱码。而题目也需要第一个密文块的值为yusayusayusayusa.
好在题目给出了三次交互的机会,第一次用于登陆,第二次用于改第一个密文块,从而使第二个密文块解密出admin。
第三次交互,需要从第二次交互的输出中提取第一个密文块的明文,与yusayusayusayusa异或后,再与iv进行异或,作为新的iv。这样aes cbc解密出乱码也没关系,因为会被iv抵消掉乱码。
from binascii import *
import struct
def bstr_xor(s1, s2):
l = min(len(s1), len(s2))
res = b''
for i in range(l):
tmp = s1[i] ^ s2[i]
res += struct.pack('B', tmp)
return res
token = unhexlify('9b41cb6addcea48f7f2b682afd6b5e75a2c94d578c9a7050fd5c51883d6a238e0df403bcb027bab1c36accccac29cd0e')
iv, enc1, enc2 = token[:16], token[16:32], token[32:]
n_enc1 = bstr_xor(enc1, bstr_xor(b'iyzyi', b'admin')) + enc1[5:]
print(enc1)
print(n_enc1)
result = iv + n_enc1 + enc2
print(result)
print('第一次登陆:', hexlify(result))
print('\n\n\n\n')
token2 = unhexlify('9b41cb6addcea48f7f2b682afd6b5e759b55c130fc13ab03f31c142883099e3161646d696e')
enc1_2 = token2[16:32]
print(enc1_2)
n_iv = bstr_xor(iv, bstr_xor(enc1_2, b'yusayusayusayusa'))
print(n_iv)
result2 = n_iv + n_enc1 + enc2
print('第二次登陆:', hexlify(result2))
Yusa_ecb
from Crypto.Cipher import AES
import os
BLOCKSIZE = 16
flag='flag{********************************}'
def pad(data):
pad_len = BLOCKSIZE - (len(data) % BLOCKSIZE) if len(data) % BLOCKSIZE != 0 else 0
return data + chr(pad_len) * pad_len
def unpad(data):
num = ord(data[-1])
return data[:-num]
def enc(data,key):
cipher = AES.new(key,AES.MODE_ECB)
encrypt = cipher.encrypt(pad(data))
return encrypt
def dec(data,key):
try:
cipher = AES.new(key,AES.MODE_ECB)
encrypt = cipher.decrypt(data)
return unpad(encrypt)
except:
exit()
def task():
try:
key = os.urandom(16)
while True:
plaintext = raw_input("Amazing function: ").decode('hex')
yusa = plaintext+flag
print enc(yusa,key).encode('hex')
except Exception as e:
print str(e)
exit()
if __name__ == "__main__":
task()
byte at a time 攻击。
首先通过更改plaintext的长度,测出flag长度是38(plaintext长为10的时候,密文长度48,长为11的时候,密文长度64)
参考了这篇文章:ECB Byte at Time - scriptkid - 博客园 (cnblogs.com)
每次爆破一个字符即可。
from pwn import *
from binascii import *
context.log_level = 'debug'
p = remote('das.wetolink.com', 42887)
#while (b'flag' not in p.recvline()):
'''
p.sendlineafter(b'Amazing function: ', b'88' * 11)
r = p.recvline()
print((len(r)-1)//2) # 10 => 48, 11 = > 64, so flag's length is 38
'''
def n2b(n):
h = hex(n)[2:]
return struct.pack('B', ord(h[0])) + struct.pack('B', ord(h[1]))
enc = []
for i in range(38):
payload = b'88' * (47-i)
p.sendlineafter(b'Amazing function: ', payload)
enc.append(p.recvline()[64:96])
print(enc)
flag = b''
for i in range(38):
f = False
for c in range(32, 127):
payload = b'88' * (47-len(flag)//2) + flag + n2b(c)
p.sendlineafter(b'Amazing function: ', payload)
e = p.recvline()[:-1]
if e[64:96] in enc:
flag += n2b(c)
print(flag)
f = True
break
if not f:
exit()
print(unhexlify(flag))
逆向
RealEzRE
这题很有意思。
字符串都是加密过的了,走了一个类似base64的解码。
有两个反调试,一个是时间调试,另一个我没深入去看:
看了看,跟进这个函数:
里面是个smc,但我没找到具体的smc的解码代码。
索性直接解码后dump出来。虽然不能动调了,但是可以静态看。
dword_437FA0 = 825373492;
for ( i = 0; i < sub_40F3D0(*(_DWORD **)(a1 + 4)); ++i )
input[i] = *(_BYTE *)(*(_DWORD *)(a1 + 4) + i);
sub_40B3A0((__m128i *)v13, 0, 0x408u);
rc4_(v13, 8);
if ( sub_401460() )
{
strcpy((char *)&v23, "RGVidWdnaW5nISEh"); // debuging
prin1(&v23, &v19);
v1 = (void *)prin2(&off_4380C0, &v19);
prin3(v1, (int (__cdecl *)(void *))sub_402F00);
result = -1;
}
else
{
v3 = sub_40F3D0(input);
sub_401640(v13, (int)input, (int)v15, v3);
for ( j = 0; j < 13; ++j )
{
if ( v15[j] != byte_4370C8[j] )
{
strcpy((char *)&v22, "SW5jb3JyZWN0IGZsYWch");// incorrect flag
prin1(&v22, &v19);
v4 = (void *)prin2(&off_4380C0, &v19);
prin3(v4, (int (__cdecl *)(void *))sub_402F00);
return -1;
}
}
for ( k = 0; k < 6; ++k )
{
if ( v17[k] != byte_4370E8[k] )
{
strcpy((char *)&v21, "SW5jb3JyZWN0IGZsYWch");// incorrect flag
prin1(&v21, &v19);
v5 = (void *)prin2(&off_4380C0, &v19);
prin3(v5, (int (__cdecl *)(void *))sub_402F00);
return -1;
}
}
for ( l = 0; l < 13; ++l )
{
if ( v16[l] != byte_4370D8[l] )
{
strcpy((char *)&v20, "SW5jb3JyZWN0IGZsYWch");// incorrect flag
prin1(&v20, &v19);
v6 = (void *)prin2(&off_4380C0, &v19);
prin3(v6, (int (__cdecl *)(void *))sub_402F00);
return -1;
}
}
dword_437FA4 = 'abcd';
strcpy(&v18, "ZmxhZyBpcyAiZmxhZ3t5b3VyIGlucHV0fSIg");
prin1(&v18, &v19);
v7 = prin3(&off_4380C0, (int (__cdecl *)(void *))sub_402F00);
v8 = (void *)prin2(v7, &v19);
prin3(v8, (int (__cdecl *)(void *))sub_402F00);
sub_40F781(aPause);
result = 0;
}
稍微看了下,就一个rc4,没别的了。
解密脚本:
from Crypto.Cipher import ARC4
from binascii import unhexlify, hexlify
import struct
def l2b(l):
t = b''
for i in l:
t += struct.pack('B', i)
return t
def rc4_decrypt(cipher, key):
rc4 = ARC4.new(key)
return rc4.decrypt(cipher)
rc4_key = b'\x01\x23\x45\x67\x89\xab\xcd\xef'
cipher = [0x12, 0xA7, 0xF5, 0xDE, 0x75, 0x2A, 0x6E, 0x4A, 0x6E, 0x73, 0xE6, 0x62, 0x50] + [0xBF, 0x2A, 0x98, 0xFE, 0x2B, 0xDD, 0x7B, 0xBA, 0xB6, 0x05, 0x13, 0x63, 0x57] + [0x2D, 0xD4, 0x45, 0xB8, 0xFE, 0xBC]
cipher = l2b(cipher)
print(cipher)
result = rc4_decrypt(cipher, rc4_key)
print(result)