L3HCTF 2025
TemporalParadox(350Pt 38/167)
Solve
- 去花后,f5即可反汇编

- 可以看到在特定的时间戳会输出不同的内容,patch一下运行就去,会的得到quary与其hash值,其中salt不变,t为当前时间戳


- 动调分析一下,得知sub_140001963()为makequary函数,进入分析r,a,b...的值如何计算,发现与sub_1400014D5()函数相关,该函数中的dword_14000B040变量动调可知为t.

__int64 sub_1400014D5() { unsigned int v1; // [rsp+Ch] [rbp-4h] v1 = (((dword_14000B040 << 13) ^ (unsigned int)dword_14000B040) >> 17) ^ (dword_14000B040 << 13) ^ dword_14000B040; dword_14000B040 = (32 * v1) ^ v1; return dword_14000B040 & 0x7FFFFFFF; } - 根据makequary函数,爆破2中时间戳即可
#include <iostream> #include <cstdint> #include "md5.h" #include <cstring> using namespace std; //n1751990400 > 1751990400 && n1751990400 <= 1752052051 uint32_t t; int __cdecl userrand() { unsigned int v1; // [rsp+Ch] [rbp-4h] v1 = (((t << 13) ^ (unsigned int) t) >> 17) ^ (t << 13) ^ t; t = (32 * v1) ^ v1; return t & 0x7FFFFFFF; } void makeQuery(char *query, uint32_t t) { uint32_t a = 0; uint32_t b = 0; uint32_t x = 0; uint32_t y = 0; for (int i = 0; i < userrand(); ++i) { a = userrand(); b = userrand(); x = userrand(); y = userrand(); } uint32_t r = userrand(); sprintf(query, "salt=tlkyeueq7fej8vtzitt26yl24kswrgm5&t=%d&r=%d&a=%d&b=%d&x=%d&y=%d", t, r, a, b, x, y); } int main() { string target = "8a2fc1e9e2830c37f8a7f51572a640aa"; for (int i = 1751990400; i < 1752052051; ++i) { t = i; char query[120]; string hash; makeQuery(query, i); MD5 md5(query); md5.getDigest(); hash = md5.toStr(); if (hash == target) { cout <<"Find "<< query; } } } // Find salt=tlkyeueq7fej8vtzitt26yl24kswrgm5&t=1751994277&r=101356418&a=1388848462&b=441975230&x=1469980073&y=290308156 //sha1 5cbbe37231ca99bd009f7eb67f49a98caae2bb0f - 故flag为:
L3HCTF{5cbbe37231ca99bd009f7eb67f49a98caae2bb0f}
What I have learned
-
ida中x64的_fastcall调用约定

在实际调用时,貌似没有用到rdi与esi,例如下图是求rdi的size但实际返回值确实rcx的size

实际上在windows文档中
整数参数在寄存器 RCX、RDX、R8 和 R9 中传递。 浮点数参数在 XMM0L、XMM1L、XMM2L 和 XMM3L 中传递。

而 x86 模式下__fastcall调用约定指定尽可能在寄存器中传递函数的自变量。此调用约定仅适用于 x86 体系结构。以下列表显示此调用约定的实现。元素 实现 参数传递顺序 在自变量列表中按从左到右的顺序找到的前两个 DWORD或更小自变量将在 ECX 和 EDX 寄存器中传递;所有其他自变量在栈上从右向左传递。x86存在多种调用约定,常见的有cdecl (C规范) / stdcall(WinAPI默认) / fastcall 函数调用约定。
x64的调用约定只有一种fastcall,windows与linux略有不同
详细见 https://www.cnblogs.com/shines77/p/3788514.html -
windows中c调用md5加密:https://github.com/JieweiWei/md5
CMakeLists中add_executable()中添加MD5.cpp

-
md5加密的标志
v250[23] = 0; v250[19] = 0x67452301; v250[20] = 0xEFCDAB89; v250[21] = 0x98BADCFE; v250[22] = 0x10325476;

浙公网安备 33010602011771号