先用ida打开(这个是个64位的文件,需要用64位的ida打开,在main()
函数f5
,查看伪代码。
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+14h] [rbp-Ch]
unsigned __int64 v5; // [rsp+18h] [rbp-8h]
v5 = __readfsqword(0x28u);
welcome();
puts("_________________");
puts("try to patch me and find flag");
v4 = 0;
puts("please input a lucky number");
__isoc99_scanf("%d", &v4);
patch_me(v4);
puts("OK,see you again");
return 0;
}
我们转到关键函数patch_me(v4)
int __fastcall patch_me(int a1)
{
int result; // eax
if ( a1 % 2 == 1 ) // 输入的数字是偶数
result = puts("just finished");
else
result = get_flag();
return result;
}
没什么价值,直接查看get_flag()
函数,关键代码就是while()
里面的内容
switch ( rand() % 200 ) //随机数
{
case 1:
puts("OK, it's flag:");
memset(&s, 0, 0x28uLL); // &s 初始化
strcat((char *)&s, f1); // GXY{do_not_
strcat((char *)&s, &f2); // null
printf("%s", &s); // &s = f1 + f2
break;
case 2:
printf("Solar not like you");
break;
case 3:
printf("Solar want a girlfriend");
break;
case 4:
v6 = 0;
s = 0x7F666F6067756369LL; // icug`of
strcat(&f2, (const char *)&s); // &f2 = icug`of
break;
case 5:
for ( j = 0; j <= 7; ++j )
{
if ( j % 2 == 1 )
v1 = *(&f2 + j) - 2;
else
v1 = *(&f2 + j) - 1;
*(&f2 + j) = v1;
}
break;
default:
puts("emmm,you can't find flag 23333");
break;
}
这里的函数的意思就是随机进行排列组合,其中会有一个flag。我们通过观察这段代码
case 1
我们可以看到flag = f1 + f2
,f2
的值我们可以看到就是GXY{do_not_
,但是f2的值还是空的。
case 4
给f2
赋值0x7F666F6067756369LL
,这个数据我们要倒序取出来。(ps。这个涉及到计算机储存的端绪问题,windows通常就是小端绪的,储存和读取是倒着来的)
case 5
,对f2
进行了一个简单的替换处理。
这样我们就可以判断,我们要的flag顺序是:4->5->1。
编写脚本
flag = 'GXY{do_not_'
f2 = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69][::-1]
v1 = ''
for j in range(8):
if j % 2 == 1:
v1 = chr(int(f2[j]) - 2)![](https://img2018.cnblogs.com/blog/1447880/202002/1447880-20200212232228801-555097850.png)
else:
v1 = chr(int(f2[j]) - 1)
flag += v1
print(flag)
flag就是:flag{do_not_hate_me}