利用TitanEngine简单制作补丁
本帖最后由 A-new 于 2019-1-10 18:04 编辑这个源于@mohao 的一个求助帖https://www.52pojie.cn/thread-649625-1-1.html
mohao想做一下它的内存注册机,不过网上常用的几款内存注册机工具都有局限性,不能在特定模块下断点读取注册码,也就是只能在主程序exe中读取注册码(也可能是我能力有限不会用),而帖子中提到的软件注册码出现在regcode.dll中,所以就有了此文,在此先感谢一下@Kido 牛,早些时候指导偶学会使用TitanEngine,扯多了开始正题吧
求助帖中软件获取注册码步骤仅需三步
1、主程序加了UPX,下断点到OEP
01BCCECC FFD5 call ebp
01BCCECE 58 pop eax
01BCCECF 61 popad
01BCCED0 8D4424 80 lea eax, dword ptr
01BCCED4 6A 00 push 0x0
01BCCED6 39C4 cmp esp, eax
01BCCED8^ 75 FA jnz short 01BCCED4
01BCCEDA 83EC 80 sub esp, -0x80
01BCCEDD- E9 78B8E0FE jmp 009D875A ; 跳到OEP此处下断
01BCCEE2 0000 add byte ptr , al
2、加载regcode.dll处下断点
010F5FA2 89A5 E4FEFFFF mov dword ptr , esp
010F5FA8 68 30C75D01 push 015DC730 ; \RegCode.dll
010F5FAD 68 A4FB7D01 push 017DFBA4
010F5FB2 51 push ecx
010F5FB3 E8 A8D532FF call 00423560
010F5FB8 83C4 0C add esp, 0xC
010F5FBB E8 50A50C00 call 011C0510
010F5FC0 83C4 04 add esp, 0x4
010F5FC3 84C0 test al, al
010F5FC5 0F84 92020000 je 010F625D
010F5FCB 68 30C75D01 push 015DC730 ; \RegCode.dll
010F5FD0 8D95 E0FEFFFF lea edx, dword ptr
010F5FD6 68 A4FB7D01 push 017DFBA4
010F5FDB 52 push edx
010F5FDC E8 7FD532FF call 00423560
010F5FE1 8B00 mov eax, dword ptr
010F5FE3 83C4 0C add esp, 0xC
010F5FE6 50 push eax
010F5FE7 FF15 94254A01 call dword ptr ; kernel32.LoadLibraryW
010F5FED 8BF0 mov esi, eax ; 加载RegCode.dll完毕,此处下断点
3、RegCode.dll出现注册码的地方下断点
6F831281 85C9 test ecx, ecx
6F831283 75 0A jnz short 6F83128F
6F831285 68 05400080 push 0x80004005
6F83128A E8 910A0000 call 6F831D20
6F83128F 8B5D E4 mov ebx, dword ptr
6F831292 50 push eax
6F831293 53 push ebx
6F831294 E8 885D0F00 call 6F927021
6F831299 83C4 08 add esp, 0x8 ; 注册码出现在ebx,此处下断点
具体如何找到此处自己慢慢找,不是本文讨论重点
关键部分
写注册机
TitanEngine的基本流程
初始化InitDebug
The InitDebug function is used to initialize the debugging process. This function is always used first and
it is creating a process which will be debugged.
然后开始调试流程DebugLoop
DebugLoop starts the debugging process. Always call this function or DebugLoopEx after initializing the
debugger with one of the initialization functions. Set at least one breakpoint before running the
debugged or the application whose process is being debugged will run. DebugLoop will not return until
the debugger is finished and the debugged application has been terminated.
初始化一般用InitDebugEx
void* __stdcall InitDebug(
char* szFileName,//调试文件
char* szCommandLine,//启动参数
char* szCurrentFolder,//调试进程工作路径
LPVOID EntryCallBack //回调函数
);
Return value
If it succeeds, InitDebugEx returns a pointer to a PROCESS_INFORMATION structure, otherwise
it returns NULL.
详细的自己查阅TitanEngine的SDK,这里就不一个一个复制粘贴了
这里就不多介绍了就几行代码注释也算比较详细了
#include <Windows.h>
#include "direct.h"
#include "TitanEngine.h"
#pragma comment (lib, "TitanEngine.lib")
////////////////////////////////////////////////////////
///////////////////全局变量/////////////////////////////
char *FileName,*CmdLine,*CurrentPath,*RegCode;
PE32Struct peInfo;
LPPROCESS_INFORMATION pInfo;
DWORD Upxbrk;
DWORD LoadDllbrk;
DWORD Dllbrk;
////////////////////////////////////////////////////////
////////////////////函数定义////////////////////////////
void init(); //初始化
void GetRegCode();
void SetupDebug();
void cbSetupDebug(); //初始化回调函数设置0x01BCCEDD处断点
void cbLoadDll(); //UPX跳转OEP处回调函数设置0x010F5FED 处加载RegCode.dll断点
void cbDllbrk(); //设置RegCode.dll 0x6F831299 处注册码出现处断点
void cbGetRegCode(); //读取注册码
int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd )
{
GetRegCode();
return 0;
}
void GetRegCode()
{
init();
SetupDebug();
}
void SetupDebug()
{
pInfo = (LPPROCESS_INFORMATION)InitDebugEx(FileName,CmdLine,CurrentPath,cbSetupDebug);
DebugLoop();
}
void init()
{
FileName = (char *)malloc(MAX_PATH);
CmdLine = (char *)malloc(MAX_PATH);
CurrentPath = (char *)malloc(MAX_PATH);
memset(FileName,0,MAX_PATH);
memset(CmdLine,0,MAX_PATH);
memset(CurrentPath,0,MAX_PATH);
CurrentPath = _getcwd(NULL,0);
strcpy_s(FileName,MAX_PATH,CurrentPath);
strcat(FileName,"\\SjmsCAD.exe");
}
void cbLoadDll()
{
LoadDllbrk = (DWORD)GetDebuggedFileBaseAddress(); //基址
LoadDllbrk += 0x00CF5FED;
SetBPX(LoadDllbrk,UE_BREAKPOINT_TYPE_INT3,cbDllbrk);
}
void cbDllbrk()
{
Dllbrk = GetContextData(UE_EAX);//基址
Dllbrk += 0x1299;
SetBPX(Dllbrk,UE_BREAKPOINT_TYPE_INT3,cbGetRegCode);
}
void cbGetRegCode()
{
RegCode = (char *)malloc(MAX_PATH);
memset(RegCode,0,MAX_PATH);
GetRemoteString(pInfo->hProcess,(LPVOID)GetContextData(UE_EBX),RegCode,256); //读取注册码
RemoveAllBreakPoints(UE_OPTION_REMOVEALL); //清除所有断点
DetachDebuggerEx(pInfo->dwProcessId); //剥离进程
StopDebug(); //结束调试
MessageBoxA(NULL,RegCode,"SN",MB_OK);
}
void cbSetupDebug()
{
Upxbrk += (DWORD)GetDebuggedFileBaseAddress(); //基址
Upxbrk += 0x017CCEDD;
SetBPX(Upxbrk,UE_BREAKPOINT_TYPE_INT3,cbLoadDll); //设置断点
}
代码比较挫,能用就好
TitanEngine建议用x64dbg的pluginsdk中的
TitanEngine SDK文档在原版:TitanEngine v. 2.0.3
link:https://www.reversinglabs.com/open-source/titanengine
x64dbg用的版本修正了原版的一些bug等,其实可以直接使用x64dbg里的X64dbg\pluginsdk\TitanEngine就好了
https://bitbucket.org/titanengineupdate/titanengine-update
源码打包
six six six springwillow 发表于 2019-1-10 08:02
loadlibrary
菜鸟而已,如果要对系统函数下断点,应该有两种方法
方法一:
是断在引用处比如00403E50|.E8 AFFCFFFF CALL <JMP.&kernel32.LoadLibraryW> ; \LoadLibraryW
或者
00403B04 $- FF25 74714000 JMP NEAR DWORD PTR DS:[<&kernel32.Lo>;kernel32.LoadLibraryW
00407174 >754E481Bkernel32.LoadLibraryW
这种的话你可以先获取LoadLibraryW的函数地址(754E481B)然后搜索这个地址找到(00407174 )再根据(00407174 )找到call或者jmp引用的地址下断,这种的话需要输入表中有这个函数才有用。
方法二:
直接获取LoadLibraryW的函数地址(754E481B),然后直接对这个地址下断点。这种方法未测试过。
方法一,根据之前的代码,方法一麻烦点,如果他是导入函数,应该是可用的,你可以测试反馈一下,偶很少写代码,只做原理性研究 前排沙发第一位,支持楼主 感谢分享 谢谢分享{:1_893:} 支持下A牛大神,以前我用过这种方法 看不懂,但是支持 前排膜拜A牛 谢谢版主,但那个内存补丁怎么用的啊? 感谢分享 论坛里的大神真多,学习中