main
cpp
int __cdecl main(int argc, const char **argv, const char **envp)
{
char *v3; // rdi
int v4; // r15d
unsigned __int64 i; // rbx
unsigned int *v6; // rbx
__int64 v7; // rdi
__int64 v8; // rsi
char *v9; // rax
int v10; // r12d
int v11; // r14d
char *v12; // r13
_QWORD *v13; // rsi
void *v14; // rax
void *v15; // rbx
int v16; // edi
void *Block; // [rsp+20h] [rbp-89h] BYREF
int v19; // [rsp+28h] [rbp-81h]
int v20; // [rsp+2Ch] [rbp-7Dh]
__int128 v21; // [rsp+30h] [rbp-79h] BYREF
__int128 v22; // [rsp+40h] [rbp-69h]
char Buffer[16]; // [rsp+50h] [rbp-59h] BYREF
__int128 v24; // [rsp+60h] [rbp-49h]
char v25; // [rsp+70h] [rbp-39h]
__int128 Src[4]; // [rsp+80h] [rbp-29h] BYREF
char v27; // [rsp+C0h] [rbp+17h]
memset(Src, 0, sizeof(Src));
v27 = 0;
v21 = 0i64;
v22 = 0i64;
sub_7FF601481010("flag:\r\n", argv, envp);
v25 = 0;
*Buffer = 0i64;
v24 = 0i64;
sub_7FF601481BA0("%32s");
v3 = Buffer;
v4 = 0;
for ( i = 0i64; i < 0x10; ++i )
{
sub_7FF601481C00(v3, "%02hhX"); // str-hex
v3 += 2;
}
rotate(Src); // 循环左移
v6 = &v21;
v21 = Src[0];
Block = 0x341200001212i64; // xtea的密钥
v7 = 2i64;
v19 = 0x5612; // xtea的密钥
v20 = 0x8923; // xtea的密钥
do
{
xtea(v6, &Block);
v6 += 2;
--v7;
}
while ( v7 );
v8 = -1i64;
Src[0] = v21;
do
++v8;
while ( *(Src + v8) );
LODWORD(v21) = 4;
*&v22 = aDfb8007c773561; // aes的密钥
*(&v21 + 4) = 0x100000004i64;
HIDWORD(v21) = 10;
v9 = sub_7FF601481070(&v21); // aes密钥扩展算法
v10 = v21;
Block = v9;
if ( v8 % (4 * v21) )
v11 = 4 * v21 * (v8 / (4 * v21) + 1);
else
v11 = v8;
v12 = operator new(v11);
memcpy(v12, Src, v8);
memset(&v12[v8], 0, v11 - v8);
v13 = operator new(v11);
if ( v11 / (4 * v10) > 0 )
{
do
{
v14 = sub_7FF6014813E0(&v21, &v12[4 * v10 * v4], Block);// aes加密,ecb
v10 = v21;
v15 = v14;
v16 = 4 * v21;
memcpy(v13 + 4 * v21 * v4, v14, 4 * v21);
j_j_free(v15);
++v4;
}
while ( v4 < v11 / v16 );
}
j_j_free(Block);
j_j_free(v12);
if ( *v13 == qword_7FF6014860A0 && v13[1] == qword_7FF6014860A8 )// 密文
puts("Congratulations!");
else
sub_7FF601481010("no!\n");
return 0;
}
流程是输入的字符每两个转为一个字节,单字节循环左移,xtea加密,aes加密。
注意最后密文显示是小端序模式,在脚本解密时,应按8字节逆转。xtea部分同理,按4字节逆转。
脚本内的xtea的key并未用到。可根据算法手动计算xtea内部异或用到的数(4字节无符号数)。
python
from ctypes import *
from Crypto.Cipher import AES
from Crypto.Util.number import *
def l_rotate(n, d):
return (n << d)|(n >> (8 - d))&1
def r_rotate(n, d):
return (n >> d)|(n << (8 - d))&0b10000000
def encrypt(v, key):
v0, v1 = c_uint32(v[0]), c_uint32(v[1])
# delta = 0x9E3779B9
#first round
v0.value+=(0x1212^(((v1.value << 5) ^ (v1.value >> 6))+ v0.value))
# total = c_uint32(delta * 32)
offset=[0xcbbdfd0f,0xcbbdfd0f,0x98a8c4ba,0x98a908ba,0x65942576,0x65942576,0x327edc10,0x327e9810,0xff69a3bb,0xff69a3bb,0xcc546b66,0xcc54e277,0x993fcc22,0x993f5511,0x662a82bc,0x662a60bc,0x33154a67,0x33156c67,][::-1]
for i in range(9):
# total.value -= delta
v1.value += (((v0.value << 4) ^ (v0.value >> 5)) + v0.value) ^ (offset[2*i] )
v0.value += (((v1.value << 5) ^ (v1.value >> 6)) + v1.value) ^ (offset[2*i+1])
#last round
v1.value+=(0xfed36875^(((v0.value << 4) ^ (v0.value >> 5)))+v0.value)
return [v0.value, v1.value]
def decrypt(v, key):
v0, v1 = c_uint32(v[0]), c_uint32(v[1])
# delta = 0x9E3779B9
#first round
v1.value-=0xfed36875^(v0.value+((v0.value << 4) ^ (v0.value >> 5)))
# total = c_uint32(delta * 32)
offset=[0xcbbdfd0f,0xcbbdfd0f,0x98a8c4ba,0x98a908ba,0x65942576,0x65942576,0x327edc10,0x327e9810,0xff69a3bb,0xff69a3bb,0xcc546b66,0xcc54e277,0x993fcc22,0x993f5511,0x662a82bc,0x662a60bc,0x33154a67,0x33156c67,]
for i in range(9):
# total.value -= delta
v0.value -= (((v1.value << 5) ^ (v1.value >> 6)) + v1.value) ^ (offset[2*i] )
v1.value -= (((v0.value << 4) ^ (v0.value >> 5)) + v0.value) ^ (offset[2*i+1] )
#last round
v0.value-=(0x1212^(((v1.value << 5) ^ (v1.value >> 6))+ v1.value))
return [v0.value, v1.value]
# test
if __name__ == "__main__":
cipher=long_to_bytes(0xd5913f4fa43609f541b139503107e67f)
key_aes=b'dfb8007c773561da'
aes=AES.new(key_aes,AES.MODE_ECB)
plain_aes=aes.decrypt(cipher)
print('AES decrypt:',hex(bytes_to_long(plain_aes)),len(plain_aes))
value = [[bytes_to_long(plain_aes[:4][::-1]),bytes_to_long(plain_aes[4:8][::-1])],[bytes_to_long(plain_aes[8:12][::-1]),bytes_to_long(plain_aes[12:][::-1])]]
print(value)
key_tea = [0x1212, 0x3412, 0x5612, 0x8923]
plain_tea0 = decrypt(value[0], key_tea)
print("XTEA Decrypted data is : ", hex(plain_tea0[0]), hex(plain_tea0[1]))
plain_tea1 = decrypt(value[1], key_tea)
print("XTEA Decrypted data is : ", hex(plain_tea1[0]), hex(plain_tea1[1]))
plain_bytes=long_to_bytes(plain_tea0[0])[::-1]+long_to_bytes(plain_tea0[1])[::-1]+long_to_bytes(plain_tea1[0])[::-1]+long_to_bytes(plain_tea1[1])[::-1]
l=[]
print('info: lens',len(plain_bytes),plain_bytes)
for each in plain_bytes:
origin=r_rotate(each,1)
l.append(long_to_bytes(origin))
print(l)
l=b''.join(l)
print(l,len(l))
print('%x'%(bytes_to_long(l)))
"""
decaec9d25889199865401fb84cd8a7c flag
"""
xtea做的不多第一眼看过去确实有点蒙。
aes如果ida有findcrypt插件能直接识别, 或者看到sbox,63,7c打头也能想到了。
还好只有一个分组,且并没用少见的加密模式。