参考:
https://www.52pojie.cn/thread-742361-1-1.html
一
flag only appears at a specific time, range [2018-05-19 09:00, 2018-05-21 09:00)
Better luck next time :)
二
使用IDA分析该二进制文件,在函数表中可以找到main函数,在main函数的头部打下断点并调试运行,这时能够发现在该断点命中的时候屏幕上已经有信息输出,说明在main函数之前还执行了大量的代码(MFC和win的onInitDialog之类)。如何寻找真正的入口函数呢?方法有如下:main函数栈回溯、puts栈回溯。
三
imports里有time64
四
__int64 __fastcall sub_402268(__time64_t *a1, __int64 a2)
{
__int64 result; // rax
unsigned int v3; // [rsp+20h] [rbp-10h]
int v4; // [rsp+24h] [rbp-Ch]
unsigned int v5; // [rsp+28h] [rbp-8h]
int i; // [rsp+2Ch] [rbp-4h]
v5 = time64(a1);
if ( v5 <= 0x5AFFE78F || v5 > 0x5B028A8F )
return 0LL;
srand((unsigned int)a1);
for ( i = 0; i <= 255; ++i )
byte_405020[i] ^= rand();
v4 = 0;
v3 = 0;
sub_4027ED((__int64)a1, a2, &v4, (__int64)byte_405020, &v3);
if ( v4 == 0x700 )
{
unk_4099D0 = v3;
result = v3;
}
else
{
unk_4099D0 = 0;
result = 0LL;
}
return result;
}
time64函数返回当前时间戳,根据这段代码,返回的时间戳应该在(0x5AFFE78F,0x5B028A8F]这个范围内程序才会继续执行。
其后以时间戳做为随机数种子,取随机数对E1表异或运算,再通过4027ED这个函数对byte_405020表进行一些变换,最终得到v4的值,并判断v4的值是否等于0x700.
在后面的代码中可知,如果unk_4099D0等于0,那么程序将直接退出。因此,必须要寻找一个值使得v4满足v4==0x700。
我们观察满足题意的time返回值,0x5B028A8F - 0x5AFFE78F = 0x2A300,可以说是非常小的数字了,只需要遍历测试(0x5AFFE78F,0x5B028A8F]区间的所有值即可寻找到正确的time值。
c语言解题脚本
添加对应函数头文件,照百度解决memcpy的aceess violation问题
改了工程设置里的,链接器,高级,数据执行保护为“否”
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int(*test)();
static UINT time = 0x5AFFE78F + 1; //起点
UINT myfun(int) { //通过这种形式遍历每一个time
return time++;
}
char e1_copy[256] = {0};
int main()
{
UINT64 * ptr1 = (UINT64 *)0x40A38C;//time64
UINT64 * ptr2 = (UINT64 *)0x40A414; //srand
UINT64 * ptr3 = (UINT64 *)0x40A3FC;//rand
UINT64 * ptr4 = (UINT64 *)0x40A3DC;//memset
HMODULE h = LoadLibraryA("C:\\Users\\lenovo\\Desktop\\fuxian\\magic\\magic.exe");
memcpy(e1_copy, (void *)0x405020, 256); //备份E1表,重新运算的时候需要还原E1表
test test1 = (test)0x402268;
*ptr1 = (UINT64)myfun;
*ptr2 = (UINT64)srand;
*ptr3 = (UINT64)rand;
*ptr4 = (UINT64)memset;
UINT val;
while (true)
{
memcpy((void *)0x405020, e1_copy, 256); // 重置E1表
val = test1();
if (val != 0)
{
printf("time:%x\nkey:%x", time -1 , val); //0x322ce7a4
//time:5b00e398
//key: 322ce7a4
break;
}
}
return 0;
}
Bypass ctypes
import ctypes
def h2f(s):
cp = ctypes.pointer(ctypes.c_int(s))
fp = ctypes.cast(cp, ctypes.POINTER(ctypes.c_float))
return fp.contents.value
def f2h(s):
fp = ctypes.pointer(ctypes.c_float(s))
cp = ctypes.cast(fp, ctypes.POINTER(ctypes.c_int))
return cp.contents.value
if __name__=='__main__':
X=0
score=0
while(int(((1.5-h2f(X)*h2f(X)*(score/2))*h2f(X)*100000000*10+5)/10)!=0x436AE):
score+=1
X=0x5F3759D8 - (f2h(score)>>1)
if X!=0:
X+=7
print score