静态分析
首先通过关键字符串 Wrong
进入 main
函数
void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
int i; // [rsp+8h] [rbp-48h]
char s[40]; // [rsp+20h] [rbp-30h] BYREF
unsigned __int64 v5; // [rsp+48h] [rbp-8h]
v5 = __readfsqword(0x28u);
__isoc99_scanf("%39s", s);
if ( (unsigned int)strlen(s) != 32 )
{
puts("Wrong!");
exit(0);
}
mprotect(&dword_400000, 0xF000uLL, 7);
for ( i = 0; i <= 223; ++i )
*((_BYTE *)sub_402219 + i) ^= 0x99u;
sub_40207B((__int64)&unk_603170);
sub_402219();
}
阅读一下代码,发现先是输入一个长度为32的字符串
随后对一个奇怪的地址执行了一个函数,但这个地址和输入应该没有关系,可以暂时不管
注意到有个 for
循环对某一个地址的值做了个异或,最后又调用了这个地址,这是简单且经典的 SMC
用 idapython patch 一下,用运行脚本功能,由于长度较短,直接在ida中手写了
start = 0x402219
end = start + 223
for i in range(start, end + 1):
patch_byte(i, get_wide_byte(i) ^ 0x99)
运行完后进入这个地址,好像不能在 402219
处新建函数,只能在 40221A
处按 p 键新建函数,F5 查看这个函数
__int64 __fastcall sub_40221A(__int64 a1)
{
unsigned int v2; // [rsp+18h] [rbp-D8h]
int i; // [rsp+1Ch] [rbp-D4h]
char v4[200]; // [rsp+20h] [rbp-D0h] BYREF
unsigned __int64 v5; // [rsp+E8h] [rbp-8h]
v5 = __readfsqword(0x28u);
sub_400A71((__int64)v4, (__int64)&unk_603170);// 经典密钥生成
sub_40196E((__int64)v4, a1); // 这tm是AES
sub_40196E((__int64)v4, a1 + 16);
v2 = 1;
for ( i = 0; i <= 31; ++i )
{
if ( *(_BYTE *)(i + a1) != byte_6030A0[i] )
v2 = 0;
}
return v2;
}
最后的 byte_6030A0
显然是加密结果的校验了
上面有两个函数 sub_400A71
和 sub_40196E
,400A71
调用了之前出现的 603170
猜测是一个密钥,40196E
使用了两次,且分别是对输入的前一半与后一半的操作,猜测是加密函数。密钥生成和输入无关,完全可以通过动态调试得到结果,所以查看加密函数。
__int64 __fastcall sub_401828(__int64 a1, __int64 a2)
{
unsigned __int8 i; // [rsp+1Fh] [rbp-1h]
sub_400B0A(0LL, a1, a2); // 这是aes哦
for ( i = 1; i <= 9u; ++i )
{
sub_400BAC(a1);
sub_400C1F(a1);
sub_400D27(a1);
sub_400B0A(i, a1, a2);
}
sub_400BAC(a1);
sub_400C1F(a1);
return sub_400B0A(10LL, a1, a2);
}
一开始被各个函数吓一跳,但点到某个函数里发现好像是 $4\times 4$ 的一个方阵,又发现某些函数重复出现的规则和 AES 很像,于是推测这个是 AES 加密算法,稍微看了下具体的函数实现,应该没有大问题,于是着手解密了。
解密
首先动态调试拿到密钥
直接步过这句代码: sub_40207B((__int64)&unk_603170);
gdb-peda$ b *0x4021e4
Breakpoint 2 at 0x4021e4
gdb-peda$ c
gdb-peda$ n
gdb-peda$ x/50x 0x603170
0x603170: 0xcb 0x8d 0x49 0x35 0x21 0xb4 0x7a 0x4c
0x603178: 0xc1 0xae 0x7e 0x62 0x22 0x92 0x66 0xce
0x603180: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
拿到密钥
随后直接到 ida 相应地址中取出密文
用之前写过的 AES 脚本解密
import my_aes
from libnum import n2s
key = 0xcb8d493521b47a4cc1ae7e62229266ce
cipher1 = 0xBC0AADC0147C5ECCE0B140BC9C51D52B
cipher2 = 0x46B2B9434DE5324BAD7FB4B39CDB4B5B
print(n2s(my_aes.aes_encrypt(cipher1, key)), end = '')
print(n2s(my_aes.aes_encrypt(cipher2, key)))
输出如下:
b'flag{924a9ab2163'b'd390410d0a1f670}'
得到 flag