【re】[CISCN 2022 东北]easycpp --ida动态调试,循环异或
拿到程序,我们先查一下有没有加壳,发现没有加壳,并且是64位程序,拖进ida分析其代码逻辑
int __cdecl main(int argc, const char **argv, const char **envp)
{
void **v3; // rcx
__int64 v4; // r8
size_t v5; // r10
void **v6; // rax
void **v7; // r8
void **v8; // rax
void **v9; // r8
void **v10; // rax
void **v11; // r8
void **v12; // rdx
int v13; // eax
const char *v14; // rdx
sub_7FF6E3862410(*(__int64 *)&argc, (__int64)"Input:", (__int64)envp);
sub_7FF6E3862B60((__int64)&qword_7FF6E3897590);
if ( Size != 38 )
goto LABEL_22;
v5 = 0i64;
v3 = &Src;
do
{
v6 = &Src;
v7 = &Src;
if ( (unsigned __int64)qword_7FF6E3896C68 >= 0x10 )
v6 = (void **)Src;
if ( (unsigned __int64)qword_7FF6E3896C68 >= 0x10 )
v7 = (void **)Src;
*((_BYTE *)v7 + v5) ^= *((_BYTE *)v6 + v5 + 1);// flag[i]^=flag[i+1]
v8 = &Src;
v9 = &Src;
if ( (unsigned __int64)qword_7FF6E3896C68 >= 0x10 )
v8 = (void **)Src;
if ( (unsigned __int64)qword_7FF6E3896C68 >= 0x10 )
v9 = (void **)Src;
*((_BYTE *)v9 + v5 + 1) ^= *((_BYTE *)v8 + v5 + 2);
v10 = &Src;
v11 = &Src;
if ( (unsigned __int64)qword_7FF6E3896C68 >= 0x10 )
v10 = (void **)Src;
if ( (unsigned __int64)qword_7FF6E3896C68 >= 0x10 )
v11 = (void **)Src;
*((_BYTE *)v11 + v5 + 2) ^= *((_BYTE *)v10 + v5 + 3);
++v5;
v4 = Size;
}
while ( v5 < Size - 3 ); // 35
v12 = &Buf2;
if ( (unsigned __int64)qword_7FF6E3896C48 >= 0x10 )
v12 = (void **)Buf2;
if ( (unsigned __int64)qword_7FF6E3896C68 >= 0x10 )
v3 = (void **)Src;
if ( Size != qword_7FF6E3896C40 || (v13 = memcmp(v3, v12, Size), v14 = "Right!", v13) )
LABEL_22:
v14 = "Wrong!";
sub_7FF6E3862410((__int64)v3, (__int64)v14, v4);
return 0;
}
虽然代码很长,其实我们只需要关注主要逻辑就行,首先输入字符串长度是38,然后就是四位一组不断循环异或下去,逆向时只需要从最后一个字符,根据上面的代码逆着写回去就行,不需要去特别注意ida的代码实现,其实很冗杂,知道代码在干嘛就行,但是这里有个问题,就是判断数据在那里?看这个代码v13 = memcmp(v3, v12, Size),这个v12是是前面buf2的地址v3是加密过后的字符串,所以buf应该就是判断数据,ida点进去,发现没有数据
那应该是程序运行时才生成的数据了,我们在判断这里下个断点,在ida进行动态调试,这里调试模式选择window remote debug,然后把ida文件夹对应的程序打开
然后远程调试地址选择127.0.0.1(本机回环地址),进行debug
可以得到buf2的内容,故exp如下: