死了活
Simple File System
Simple File System程序挂载flag文件加密,需要找到加密函数进行解密。
找到加密函数sub_21B2((__int64)ptr, v8);,下图地址不同是因为动调
进行动调,得到v4 = 0xDEEDBEEF,
并且在该处sub_1e16中 a3=1为上述的加密函数,而为2时是随机值
所以只有一组正确的数据存于image.flag ,其余均为随机值,并且每个数据间隔0x1000h,
使用加密函数得到*CTF{加密后的值
data[] = {0x2a, 0x43, 0x54, 0x46, 0x7b};
搜索找到加密后的值
脚本
然后直接爆破
#include <stdio.h>
int main()
{
unsigned char v5 = 0;
unsigned char data[32] = {
0x00, 0xd2, 0xFC, 0xD8, 0xA2, 0xDA, 0xBA, 0x9E, 0x9C, 0x26, 0xF8, 0xF6, 0xB4, 0xCE, 0x3C, 0xCC, 0x96, 0x88, 0x98, 0x34, 0x82, 0xDE, 0x80, 0x36, 0x8A, 0xD8, 0xC0, 0xF0, 0x38, 0xAE, 0x40, 0};
for (int n = 0; n < 31; n++)
{
for (int i = 0; i < 0xff; i++)
{
v5 = i;
v5 = (v5 >> 1) | (v5 << 7);
v5 ^= 0xef;
v5 = (v5 >> 2) | (v5 << 6);
v5 ^= 0xbe;
v5 = (v5 >> 3) | (32 * v5);
v5 ^= 0xed;
v5 = (v5 >> 4) | (16 * v5);
v5 ^= 0xde;
v5 = (v5 >> 5) | (8 * v5);
if (v5 == data[n])
{
printf("%c", i);
break;
}
}
}
return 0;
}
// *CTF{Gwed9VQpM4Lanf0kEj1oFJR6}
NaCl
找到主函数
__int64 __fastcall sub_8001775(__int64 a1, char a2)
{
int v2; // edx
int v3; // ecx
int v4; // r8d
int v5; // r9d
__int64 result; // rax
char v7[40]; // [rsp+20h] [rbp-30h] BYREF
unsigned __int64 v8; // [rsp+48h] [rbp-8h]
v8 = __readfsqword(0x28u);
sub_8010B50("input:");
sub_8001940(0LL, v7, 32LL);
sub_8080900(v7);
if ( (unsigned int)v7 == 1 )
sub_800A380((unsigned int)"*CTF{%s}\n", (unsigned int)v7, v2, v3, v4, v5, a2);
else
sub_8010B50("failed\n");
result = 0LL;
if ( __readfsqword(0x28u) != v8 )
sub_8047FA0();
return result;
}
动调了好久,花指令
nop指令不知道是啥,去掉。
然后 r15寄存器实现了类似堆栈的作用。
将返回地址(sub_8080760)压入r15-8中,然后jmp跳转,可以直接nop掉这三个指令,然后将jmp改为call
有好几处,都改一下,IDC脚本不太会。。。
将r15-8的值给edi,然后跳转,类似pop操作,直接改为retn
xtea ,
__int64 __fastcall sub_8080100(int a1, __int64 a2)
{
__int64 v2; // r13
__int64 v3; // r15
__int64 result; // rax
*(_DWORD *)(v3 - 36) = a1;
*(_QWORD *)(v3 - 48) = a2;
*(_QWORD *)(v3 - 24) = &unk_80AFB40;
*(_DWORD *)(v3 - 8) = *(_DWORD *)(v2 + (unsigned int)*(_QWORD *)(v3 - 48));
*(_DWORD *)(v3 - 12) = *(_DWORD *)(v2 + (unsigned int)*(_QWORD *)(v3 - 48) + 4);
*(_DWORD *)(v3 - 16) = 0;
*(_DWORD *)(v3 - 28) = 0x10325476;
for ( *(_DWORD *)(v3 - 4) = 0; *(_DWORD *)(v3 - 4) < *(_DWORD *)(v3 - 36); ++*(_DWORD *)(v3 - 4) )
{
*(_DWORD *)(v3 - 8) += (((*(_DWORD *)(v3 - 12) >> 5) ^ (16 * *(_DWORD *)(v3 - 12))) + *(_DWORD *)(v3 - 12)) ^ (*(_DWORD *)(v2 + 4 * (*(_DWORD *)(v3 - 16) & 3) + (unsigned int)*(_QWORD *)(v3 - 24)) + *(_DWORD *)(v3 - 16));
*(_DWORD *)(v3 - 16) += *(_DWORD *)(v3 - 28);
*(_DWORD *)(v3 - 12) += (((*(_DWORD *)(v3 - 8) >> 5) ^ (16 * *(_DWORD *)(v3 - 8))) + *(_DWORD *)(v3 - 8)) ^ (*(_DWORD *)(v2 + 4 * ((*(_DWORD *)(v3 - 16) >> 11) & 3) + (unsigned int)*(_QWORD *)(v3 - 24)) + *(_DWORD *)(v3 - 16));
}
*(_DWORD *)(v2 + (unsigned int)*(_QWORD *)(v3 - 48)) = *(_DWORD *)(v3 - 8);
result = *(unsigned int *)(v3 - 12);
*(_DWORD *)(v2 + (unsigned int)*(_QWORD *)(v3 - 48) + 4) = result;
return result;
}
还有费斯托加密,动调可以得到需要的key
unsigned int dword_80AFB60[44] = {
0x04050607, 0x00010203, 0x0C0D0E0F, 0x08090A0B, 0xCD3FE81B, 0xD7C45477, 0x9F3E9236, 0x0107F187,
0xF993CB81, 0xBF74166C, 0xDA198427, 0x1A05ABFF, 0x9307E5E4, 0xCB8B0E45, 0x306DF7F5, 0xAD300197,
0xAA86B056, 0x449263BA, 0x3FA4401B, 0x1E41F917, 0xC6CB1E7D, 0x18EB0D7A, 0xD4EC4800, 0xB486F92B,
0x8737F9F3, 0x765E3D25, 0xDB3D3537, 0xEE44552B, 0x11D0C94C, 0x9B605BCB, 0x903B98B3, 0x24C2EEA3,
0x896E10A2, 0x2247F0C0, 0xB84E5CAA, 0x8D2C04F0, 0x3BC7842C, 0x1A50D606, 0x49A1917C, 0x7E1CB50C,
0xFC27B826, 0x5FDDDFBC, 0xDE0FC404, 0xB2B30907
};
脚本
最后是小端序
unsigned int dword_80AFB60[44] = {
0x04050607, 0x00010203, 0x0C0D0E0F, 0x08090A0B, 0xCD3FE81B, 0xD7C45477, 0x9F3E9236, 0x0107F187,
0xF993CB81, 0xBF74166C, 0xDA198427, 0x1A05ABFF, 0x9307E5E4, 0xCB8B0E45, 0x306DF7F5, 0xAD300197,
0xAA86B056, 0x449263BA, 0x3FA4401B, 0x1E41F917, 0xC6CB1E7D, 0x18EB0D7A, 0xD4EC4800, 0xB486F92B,
0x8737F9F3, 0x765E3D25, 0xDB3D3537, 0xEE44552B, 0x11D0C94C, 0x9B605BCB, 0x903B98B3, 0x24C2EEA3,
0x896E10A2, 0x2247F0C0, 0xB84E5CAA, 0x8D2C04F0, 0x3BC7842C, 0x1A50D606, 0x49A1917C, 0x7E1CB50C,
0xFC27B826, 0x5FDDDFBC, 0xDE0FC404, 0xB2B30907
};
DWORD xtea_key[4] = { 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C };
void decipher(unsigned int num_rounds, DWORD v[2], DWORD key[4]) {
unsigned int i;
DWORD v0 = v[0], v1 = v[1], delta = 0x10325476, sum = delta * num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}
void enc11(DWORD* v)
{
for (int i = 0; i < 44; i++)
{
DWORD tmp = v[0];
v[0] = (LeftRotate(v[0], 1) & LeftRotate(v[0], 8)) ^ LeftRotate(v[0], 2) ^ v[1] ^ dword_80AFB60[i];
v[1] = tmp;
}
DWORD tmp = v[0];
v[0] = v[1];
v[1] = tmp;
}
void dec11(DWORD* v)
{
DWORD tmp = v[0];
v[0] = v[1];
v[1] = tmp;
for (int i = 0; i < 44; i++)
{
tmp = v[0];
v[0] = v[1];
v[1] = (LeftRotate(v[0], 1) & LeftRotate(v[0], 8)) ^ LeftRotate(v[0], 2) ^ tmp ^ dword_80AFB60[43-i];
}
}
int main()
{
DWORD enc[] = { 0xFDF5C266, 0x7A328286, 0xCE944004, 0x5DE08ADC, 0xA6E4BD0A, 0x16CAADDC, 0x13CD6F0C, 0x1A75D936 };
//input = "1234567890abcdefghijklmn12366666"
//DWORD enc[] = { 0x4A16D2F5, 0x3995DF74, 0xC0B2BC9A, 0x313495AC, 0x207EAA57, 0x5C46F1CB, 0x9AB2B6D3, 0xF0E536C3 };
DWORD rounds[] = { 2, 4, 8, 16 };
for (int i = 0; i < 8; i += 2)
{
decipher(rounds[i / 2], &enc[i], xtea_key);
dec11(&enc[i]);
}
char* flag = (char*)enc;
for (int i = 0; i < 32; i += 4)
{
printf("%c", flag[i+3]);
printf("%c", flag[i + 2]);
printf("%c", flag[i + 1]);
printf("%c", flag[i]);
}
return 0;
}
// mM7pJIobsCTQPO6R0g-L8kFExhYuivBN