【逆向】多种方法绕过某软件许可过期检测

起因

看到求助的一个软件试用期不能重置的问题:

有没有人知道为什么重装系统了软件试用期还是不能重置! – 『悬赏问答区』 – 吾爱破解 – LCG – LSG |安卓破解|病毒分析|www.52pojie.cn

求助软件解包问题 – 『脱壳破解讨论求助区』 – 吾爱破解 – LCG – LSG |安卓破解|病毒分析|www.52pojie.cn

简单分析

软件下载下来发现是一个安装包,通过Total Uninstall监控软件安装,发现软件在安装过程中向注册表项写入一段数据,猜测是安装时间

image
image

使用InnoExtractor(Inno解包工具-InnoExtractor_8.1.0.615 汉化优化单文件版 – 『逆向资源区』 – 吾爱破解 – LCG – LSG |安卓破解|病毒分析|www.52pojie.cn)对安装包解包,在安装脚本install_script.iss中发现有相关代码

image

导出注册表文件并往后修改系统时间使软件过期,软件弹出过期窗口,此时再将时间改回,软件也会弹出过期窗口。

image
image

将刚才导出的注册表文件重新导入,软件没有弹出过期窗口,看来它是通过注册表判断是否过期。到这里其实已经绕过许可过期检测了,只要更改系统时间就行了,但每次改时间也挺麻烦的,有没有一劳永逸的办法呢?

方法一:使用ida修改汇编代码,强制绕过许可检测

先将主程序SurrealCapture.exe丢到ida里,过期弹窗上有一个购买按钮,会打开某个网站,那么我们可以在ida搜索这个网站文本

image

image

每个都点进去,f5看看伪代码,发现第一个是正常窗口,第二个才是过期窗口

在这里按x看看交叉引用,找到是谁调用了这个函数

image

跳转到这,接下来就得分析伪代码了

image

int __thiscall sub_401350(const WCHAR *this) 
{ 
__int64 v2; // kr00_8 
DWORD (__stdcall *v3)(); // esi 
HANDLE v4; // eax 
char *v5; // edi 
__int16 v6; // ax 
char *v7; // edi 
__int16 v8; // ax 
HWND v9; // eax 
HANDLE v10; // ecx 
HANDLE v11; // eax 
BOOL Wow64Process; // [esp+10h] [ebp-3D8h] BYREF 
LPCWSTR lpParameters; // [esp+14h] [ebp-3D4h] 
__int64 v14; // [esp+18h] [ebp-3D0h] BYREF 
struct _NOTIFYICONDATAW Filename; // [esp+20h] [ebp-3C8h] BYREF 

lpParameters = this; 
if ( !sub_409180() ) 
{ 
sub_402810( 
&off_430C48, 
4, 
L"d:\\project\\surrealcapture\\surrealcapture\\surrealcapture\\360gamecapture.cpp", 
78, 
L"ASSERT"); 
return 0; 
} 
v2 = qword_431D58; 
sub_40E084(&v14); 
if ( (v14 - v2) / 86400 >= 15 || v14 <= v2 ) // 计算当前时间与安装日期的时间差,如果超过15天或者当前时间早于安装时间,则提示试用期已过期 
{ 
sub_408BC0(1u); 
sub_402810( 
&off_430C48, 
3, 
L"d:\\project\\surrealcapture\\surrealcapture\\surrealcapture\\360gamecapture.cpp", 
84, 
L"Surreal Capture trial period has expired."); 
goto LABEL_42; 
} 
if ( !sub_409180() ) // 再次许可检查,如果 sub_409180() 再次返回 false,则显示一个错误消息 
{ 
sub_402810( 
&off_430C48, 
4, 
L"d:\\project\\surrealcapture\\surrealcapture\\surrealcapture\\360gamecapture.cpp", 
101, 
L"ASSERT"); 
MessageBoxW( 
0, 
L"The data for install date was corrupted. Please purchase Windows 10 Movies & TV Codec Pack.", 
L"Surreal Capture", 
0x10u); 
return 0; 
} 
if ( sub_409240() ) // 如果 sub_409240() 返回 true,则表示试用期已过期 
{ 
sub_402810( 
&off_430C48, 
3, 
L"d:\\project\\surrealcapture\\surrealcapture\\surrealcapture\\360gamecapture.cpp", 
108, 
L"Surreal Capture trial period has expired."); 
...

通过伪代码,我们可以得知软件会进行3次许可检查,那么我们可以修改这三次判断,跳过许可检查。

右键同步到ida窗口

image

ctrl+alt+k修改汇编代码,nop掉跳转

image

这里我们需要让它能够往下运行,所以改成jmp

image
image

保存修改

image

打开看看,已经跳过过期检查了,这下不用修改系统时间也能打开了

image

方法二:Hook GetSystemTimeAsFileTime

深入分析sub_40E084,我们可以发现软件调用了GetSystemTimeAsFileTime计算时间戳

__int64 __cdecl sub_40E084(__int64 *a1) 
{ 
__int64 result; // rax 
struct _FILETIME SystemTimeAsFileTime; // [esp+0h] [ebp-8h] BYREF 

SystemTimeAsFileTime = 0i64; 
GetSystemTimeAsFileTime(&SystemTimeAsFileTime);// 调用GetSystemTimeAsFileTime 
if ( *(_QWORD *)&SystemTimeAsFileTime - 116444736000000000i64 >= 325368000000000000i64 ) 
result = -1i64; 
else 
result = (*(_QWORD *)&SystemTimeAsFileTime - 116444736000000000i64) / 10000000; 
if ( a1 ) 
*a1 = result; 
return result; 
}

那么,我们可以尝试hook GetSystemTimeAsFileTime,让它返回特定的值

(这里使用了Detours 库)

#include <windows.h> 
#include <detours.h> 
#include <iostream> 

static void (WINAPI* Real_GetSystemTimeAsFileTime)(LPFILETIME) = GetSystemTimeAsFileTime; 

void WINAPI My_GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { 
SYSTEMTIME st; 
// 2024年9月14日20:00:00 
st.wYear = 2024; 
st.wMonth = 9; 
st.wDay = 14; 
st.wHour = 20; 
st.wMinute = 0; 
st.wSecond = 0; 
st.wMilliseconds = 0; 

SystemTimeToFileTime(&st, lpSystemTimeAsFileTime); 
} 

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { 
switch (ul_reason_for_call) { 
case DLL_PROCESS_ATTACH: 
case DLL_THREAD_ATTACH: 
case DLL_THREAD_DETACH: 
case DLL_PROCESS_DETACH: 
break; 
} 
return TRUE; 
} 

// 安装 Hook 
extern "C" __declspec(dllexport) void hooknew() { 
DetourTransactionBegin(); 
DetourUpdateThread(GetCurrentThread()); 
if (DetourAttach(&(PVOID&)Real_GetSystemTimeAsFileTime, My_GetSystemTimeAsFileTime) == NO_ERROR) { 
std::cout << "Hook attached successfully." << std::endl; 
} 
else { 
std::cerr << "Failed to attach hook." << std::endl; 
} 

if (DetourTransactionCommit() == NO_ERROR) { 
std::cout << "Hook successfully installed.\n" << std::endl; 
} 
else { 
std::cerr << "Hook installation failed.\n" << std::endl; 
} 
} 

// 卸载 Hook 
extern "C" __declspec(dllexport) void unhooknew() { 
DetourTransactionBegin(); 
DetourUpdateThread(GetCurrentThread()); 
if (DetourDetach(&(PVOID&)Real_GetSystemTimeAsFileTime, My_GetSystemTimeAsFileTime) == NO_ERROR) { 
std::cout << "Hook detached successfully." << std::endl; 
} 
else { 
std::cerr << "Failed to detach hook." << std::endl; 
} 
DetourTransactionCommit(); 
}

编译为32位dll,使用studype+添加并保存

PixPin_2024-09-15_13-03-19
PixPin_2024-09-15_13-05-53

测试通过,这种方法可行

PixPin_2024-09-15_13-11-34

非常感谢大家能看到这里,再见!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇