[网鼎杯 2020 青龙组]jocker
查壳无壳,直接进入IDA看,主函数如下

简而言之,就是输入24个字符,然后再进行下一步的比对,看看其他调用的函数
char *__cdecl wrong(char *Str)
{
char *result; // eax
int i; // [esp+Ch] [ebp-4h]
for ( i = 0; i <= 23; ++i )
{
result = &Str[i];
if ( (i & 1) != 0 )
Str[i] -= i;
else
Str[i] ^= i;
}
return result;
}
int __cdecl omg(char *Str)
{
_DWORD dst[24]; // [esp+18h] [ebp-80h] BYREF
int i; // [esp+78h] [ebp-20h]
int v4; // [esp+7Ch] [ebp-1Ch]
v4 = 1;
qmemcpy(dst, &src_, sizeof(dst));
for ( i = 0; i <= 23; ++i )
{
if ( Str[i] != dst[i] )
v4 = 0;
}
if ( v4 == 1 )
return puts("hahahaha_do_you_find_me?");
else
return puts("wrong ~~ But seems a little program");
}
此处的encrypt函数静态分析下是不可反编译的
if ( !VirtualProtect(encrypt, 0xC8u, 4u, &flOldProtect) )
exit(1);
VirtualProtect函数的作用就是暂时更改encrypt函数的权限,提升为可写权限,从而实现代码自修改

for ( i = 0; i <= 186; ++i )
*((_BYTE *)encrypt + i) ^= 0x41u;
encrypt(Destination);
finally(Destination);
这个亦或就是实现代码自修改的核心步骤
然后我们在IDA中动态调试起来,断点下在encrypt(Destination);

看到上面这个情况,直接选中encrypt函数的区域按U取消定义恢复成最原始的十六进制数据,再按C转化为代码,最后按P创建函数

修好后的代码如下
int __cdecl encrypt(char *Destination)
{
_DWORD dst[19]; // [esp+1Ch] [ebp-6Ch] BYREF
int v3; // [esp+68h] [ebp-20h]
int i; // [esp+6Ch] [ebp-1Ch]
v3 = 1;
qmemcpy(dst, &src__0, sizeof(dst));
for ( i = 0; i <= 18; ++i )
{
if ( (char)(Destination[i] ^ Buffer[i]) != dst[i] )
{
puts("wrong ~");
v3 = 0;
exit(0);
}
}
puts("come here");
return v3;
}
Buffer[] = "hahahaha_do_you_find_me?"
dst[] = [0xe, 0xd, 0x9, 0x6, 0x13, 0x5, 0x58, 0x56, 0x3e, 0x6, 0xc, 0x3c, 0x1f, 0x57, 0x14, 0x6b, 0x57, 0x59, 0xd]
得到一半flag:
flag{d07abccf8a410c
再找找另外一半flag
下面还有个finally函数,按照上面的步骤修复
修复后:
int __cdecl sub_40159A(char *Destination)
{
__time32_t Seed; // eax
char %tp&:[7]; // [esp+13h] [ebp-15h] BYREF
__int16 v4; // [esp+1Ah] [ebp-Eh]
int v5; // [esp+1Ch] [ebp-Ch]
strcpy(%tp&:, "%tp&:");
Seed = time(0);
srand(Seed);
v5 = rand() % 100;
%tp&:[6] = 0;
v4 = 0;
if ( (%tp&:[(unsigned __int8)%tp&:[5]] != Destination[(unsigned __int8)%tp&:[5]]) == v5 )
return puts("Really??? Did you find it?OMG!!!");
else
return puts("I hide the last part, you will not succeed!!!");
}
这函数多少有些离谱,于是开始猜谜时刻
由于 flag 结尾一定是 "}",所以盲猜 v3 与某个数异或得到剩下的 flag
然后 v3 最后一位是 ":" 也就是 58,58 ^ '}' = 71,大胆猜测每一位都与 71 异或
exp:
ls =[0xe, 0xd, 0x9, 0x6, 0x13, 0x5, 0x58, 0x56, 0x3e, 0x6, 0xc, 0x3c, 0x1f, 0x57, 0x14, 0x6b, 0x57, 0x59, 0xd]
str="hahahaha_do_you_find_me?"
for i in range(len(ls)):
print(chr(ls[i]^ord(str[i])),end='')
str2="%tp&:"
for i in range(len(str2)):
print(chr(ord(str2[i])^71),end='')
flag:
flag{d07abccf8a410cb37a}

浙公网安备 33010602011771号