欢迎光临
我们一直在努力

记录一个与时间有关的crackme

记录一个与时间有关的crackme

题目链接:https://crackmes.one/crackme/5ab77f5633c5d40ad448c28b

PE文件分析

在这里插入图片描述

算法逆向

这个程序的serial生成逻辑是与时间有关的:

在这里插入图片描述

在main函数的其实部分,先调用time(0)获取一个seed,将该seed传递给srand,再调用rand获取一个随机数rand_no。得到rand_no之后,对其执行rand_letter = rand_no % 0x1A + 0x61的操作,这是为什么呢?其实crackme做多之后,就会对ASCII码表的范围有一定的敏感性,上面计算得到的范围就是小写字母的编码值的范围。

接着:

在这里插入图片描述

对abcdef-goodx与random_letter做拼接操作,结合题目提示的serial格式,得到的字符串就是正确的serial。

注册机编写

程序的serial生成逻辑很简单,现在需要考虑的是如何获取crackme中的时间种子。如果通过调试器,这很简单,但是这里最锻炼人的还是编写一个注册机。

由于crackme是在main函数一运行就生成了时间种子,我们可以近似地认为时间种子等于程序的起始运行时间。

对于time(0),返回的是UTC时间:

在这里插入图片描述

在这里插入图片描述

下面是注册机的代码:

#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <stdlib.h>

char GetRandomLetter(unsigned int seed)
{
srand(seed);
int random_letter = rand() % 26 + 97; // 全小写字母
return random_letter;
}

int main(int argc, char const *argv[])
{
const wchar_t *fileName = L"conflux1.1.exe";
HANDLE hSnapAll = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnapAll, &pe);
bool bFinded = false;
do
{
if (!wcscmp(fileName, pe.szExeFile))
{
std::cout << "find the process: " << pe.th32ProcessID << std::endl;
bFinded = true;
break;
}

} while (Process32Next(hSnapAll, &pe));

if (bFinded)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);
if (hProcess == NULL)
{
std::cout << "OpenProcess Failed" << std::endl;
}
else
{
FILETIME creationTime, exitTime, kernelTime, userTime;
if (GetProcessTimes(hProcess, &creationTime, &exitTime, &kernelTime, &userTime))
{
ULARGE_INTEGER uli;
uli.LowPart = creationTime.dwLowDateTime;
uli.HighPart = creationTime.dwHighDateTime;

// 1. 定义 Windows 时间起点 (1601-01-01) 到 Unix 时间起点 (1970-01-01) 的差值
const ULONGLONG EPOCH_DIFF = 116444736000000000ULL;
// ↑
// 这个数值的单位是 100 纳秒 (100ns)

// 2. 计算 Unix 时间戳(秒)
time_t unixTime = (time_t)((uli.QuadPart EPOCH_DIFF) / 10000000);
// ①减去起点差值 ②除以转换系数
std::cout << GetRandomLetter(unixTime) << std::endl;
}

CloseHandle(hProcess);
}
}
else
{
std::cout << "can't find the process" << std::endl;
}

return 0;
}

使用die分析PE文件得到的是32位程序,而我的电脑使用的是64位的编译器,所以我们的GetRandomLetter函数的参数是unsigned int,如果填写long long 或者time_t,就得不到正确的随机字母。

在这里插入图片描述

赞(0)
未经允许不得转载:171主机测评 » 记录一个与时间有关的crackme
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址