源程序程序破解之 API HOOK技术
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
在原程序运行之后,通过API CreateRemoteThread 把自己的DLL注入到另一个进程.使用DLL注入工具,这个工具是我多年前写的:
这种方式最大的好处是不需要对原程序进行修改,可以躲避程序CRC校验.
最后例举一些ຫໍສະໝຸດ Baidu用场景:
1.加密狗的通用破解方法,仅针对固定数据读取的有效(有算法的加密狗无效):
mov eax, pNewAddr[/size][size=3] jmp eax
读写进程内存方法:
1.读进程内存:
2.VirtualProtect(lpAddress, nSize, PAGE_READONLY, &dwOldProtect);
3.ReadProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwRead);
}
else
{
logOutput(formatString("ApiDebugger - hook sub_4026B0 failed.\r\n"));
}
4.函数首次HOOK是在DLL加载时完成的,DLL入口增加代码:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
// 开始HOOK所有的
gHooks.BeginAll();
}
break ;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break ;
case DLL_PROCESS_DETACH:
{
gHooks.EndAll();
}
break;
}
return TRUE;
4.VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
2.写进程内存:
VirtualProtect(lpAddress, nSize, PAGE_READWRITE, &dwOldProtect);
WriteProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwWrite);
#if 1
ret = DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize,
lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
if(ret)
{
// 带狗时记录数据
WriteDataToFile(formatstring(L"1\\%d.in", gCallCounter).c_str(), lpInBuffer, nInBufferSize);
gCallCounter ++;
}
#else
{
// 拔掉后狗直接从已保存的文件中返回数据,实现狗数据的模拟
int nRet = 0;
lpSystemTime->wMinute = 0;
lpSystemTime->wSecond = 0;
lpSystemTime->wMilliseconds = 0;
#endif
}
3.直接HOOK已知的函数地址:
如果已知函数地址和函数定义,可以直接对地址进行HOOK,在HOOK之前还可以先对内存数据进行检验,只有数据一致才HOOK.
BOOL Remove(HANDLE hHook);
BOOL Begin(HANDLE hHook);
BOOL End(HANDLE hHook);
BOOL Begin2(void *pNewAddr);
BOOL End2(void *pNewAddr);
int BeginAll();
int EndAll();
void WINAPI my_GetLocalTime(LPSYSTEMTIME lpSystemTime)
{
#if 1
// 执行缺省调用
CAdAutoHookApi autoHook(&gHooks, my_GetLocalTime);
GetLocalTime(lpSystemTime);
#else
}
这样就完成了,只要你的DLL加载到一个进程中,相应的函数就被你截获了.
下面谈一下如何让一个程序加载你的DLL,一般有两种方式:
1.修改原程序的Import Table,增加导入你的DLL(静态加载):
使用工具:CFF Explorer,是Explorer Suite(http://www.ntcore.com/)中的一个工具 用于PE文件的修改,下面这个操作就是notepad.exe加载rand.dll的操作:
logOutput(formatString("ApiDebugger - sub_4026B0(%s=>%s)",
hexData1.c_str(), hexData2.c_str()));
return ret;
}
const BYTE verifyData[] = { 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x2C, 0x01, 0x00, 0x00 };
string hexData1 = toHexString((const char *)pbData, strlen((const char *)pbData));
int ret = sub_4026B0(pbData);
string hexData2 = toHexString((const char *)pbData, strlen((const char *)pbData));
1)HOOK几个API,加密狗一般最终都是使用CreateFile打开设备,调用API DeviceIoControl与加密狗进行数据交互:
gHooks.Add(_T("KERNEL32.DLL"), "CreateFileA", my_CreateFileA);
gHooks.Add(_T("KERNEL32.DLL"), "CreateFileW", my_CreateFileW);
只要Rebuild Import Table,然后再Save/Save As就可以保存新的文件,这样你的dll就自动的被加载了,DLL加载的时候也就实现了API HOOK。
这种方式因为对原程序进行了修改,如果程序有CRC校验,运行肯定就不正确了,就需要通过破解去除CRC校验部分的判断.
2.动态DLL加载:
};
举例说明使用方法:
假设一个软件是试用软件,试用7天,最笨的办法就是改本机时间,但如果用API HOOK技术就可以很容易做到,可以先用CFF Explorer或者Dependency查看一下该软件是调用哪个函数来获取系统当前时间的,假如是GetLocalTime函数(当然获取时间的函数还有很多API),那么我就可以截获GetLocalTime,返回一个永不过期的时间.
*lpBytesReturned = ReadDataFromFile(formatstring(L"1\\%d.in", gCallCounter).c_str(), lpOutBuffer, nOutBufferSize);
gCallCounter ++;
}
#endif
return ret;
}
2)使用刚才提到的方法进行DLL导入
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped
)
{
BOOL ret = TRUE;
CAdAutoHookApi autoHook(&gHooks, my_DeviceIoControl);
void *addr = (void *)0x004026B0;
if(gHooks.Add(addr, my_sub_4026B0, verifyData, sizeof(verifyData), 0) != NULL)
{
logOutput(formatString("ApiDebugger - hook sub_4026B0 ok.\r\n"));
3)带狗保存数据,数据记录完成后,用保存的数据进行狗的模拟
2. 360 CrackMe加密API的截获,
下图是用给的提示用户名:360和正确的密码输入,返回API HOOK的Log output:
解密的结果:
5375636365737300000000000000000000000000000000000000000000000000
gHooks.Add(_T("KERNEL32.DLL"), "DeviceIoControl", my_DeviceIoControl);
static int gCallCounter = 0;
BOOL WINAPI my_DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
// 004026B0 ;
static int my_sub_4026B0(BYTE *pbData)
{
CAdAutoHookApi autoHook(&gHooks, my_sub_4026B0);
sub_4026B0_func sub_4026B0 = (sub_4026B0_func)(0x004026B0);
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
// 截获KERNEL32.DLL的API GetLocalTime到你的函数地址my_GetLocalTime
gHooks.Add(_T("KERNEL32.DLL"), "GetLocalTime", my_GetLocalTime);
// 指定DLL的某个函数进行HOOK
HANDLE Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData = 0);
// 给定一个函数地址进行HOOK
HANDLE Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData = NULL, DWORD verifySize = 0, DWORD dwData = 0);
【源程序】程序破解之 API HOOK技术
API HOOK,就是截获API调用的技术,在程序对一个API调用之前先执行你的函数,然后根据你的需要可以执行缺省的API调用或者进行其他处理,假设如果想截获一个进程对网络的访问,一般是几个socket API : recv,recvfrom, send, sendto等等,当然你可以用网络抓包工具,这里只介绍通过API HOOK的方式来实现, 主要原理是在程序运行中动态修改目标函数地址的内存数据,使用jmp语句跳转到你的函数地址,执行完后再恢复内存数据, 汇编代码是:
// 改变函数的行为,返回固定的时间
// 2012-12-28 10:00:00
lpSystemTime->wYear = 2012;
lpSystemTime->wMonth = 12;
lpSystemTime->wDayOfWeek = 0;
lpSystemTime->wDay = 28;
lpSystemTime->wHour = 10;
VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
在很多年前这种技术非常的流行,有各种各样的工具和SDK,我自己也实现了一个C++ class,名为 CAdHookApi, 主要几个函数是:
class CAdHookApi
{
public:
1.首先,声明一个全局变量:
static CAdHookApi gHooks;
2.确定要截获API的参数,API GetLocalTime对应的DLL是KERNEL32.DLL, API定义为:
void WINAPI GetLocalTime(LPSYSTEMTIME lpSystemTime);
写一个新的函数,定义和原函数保持一致:
这种方式最大的好处是不需要对原程序进行修改,可以躲避程序CRC校验.
最后例举一些ຫໍສະໝຸດ Baidu用场景:
1.加密狗的通用破解方法,仅针对固定数据读取的有效(有算法的加密狗无效):
mov eax, pNewAddr[/size][size=3] jmp eax
读写进程内存方法:
1.读进程内存:
2.VirtualProtect(lpAddress, nSize, PAGE_READONLY, &dwOldProtect);
3.ReadProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwRead);
}
else
{
logOutput(formatString("ApiDebugger - hook sub_4026B0 failed.\r\n"));
}
4.函数首次HOOK是在DLL加载时完成的,DLL入口增加代码:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
// 开始HOOK所有的
gHooks.BeginAll();
}
break ;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break ;
case DLL_PROCESS_DETACH:
{
gHooks.EndAll();
}
break;
}
return TRUE;
4.VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
2.写进程内存:
VirtualProtect(lpAddress, nSize, PAGE_READWRITE, &dwOldProtect);
WriteProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwWrite);
#if 1
ret = DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize,
lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
if(ret)
{
// 带狗时记录数据
WriteDataToFile(formatstring(L"1\\%d.in", gCallCounter).c_str(), lpInBuffer, nInBufferSize);
gCallCounter ++;
}
#else
{
// 拔掉后狗直接从已保存的文件中返回数据,实现狗数据的模拟
int nRet = 0;
lpSystemTime->wMinute = 0;
lpSystemTime->wSecond = 0;
lpSystemTime->wMilliseconds = 0;
#endif
}
3.直接HOOK已知的函数地址:
如果已知函数地址和函数定义,可以直接对地址进行HOOK,在HOOK之前还可以先对内存数据进行检验,只有数据一致才HOOK.
BOOL Remove(HANDLE hHook);
BOOL Begin(HANDLE hHook);
BOOL End(HANDLE hHook);
BOOL Begin2(void *pNewAddr);
BOOL End2(void *pNewAddr);
int BeginAll();
int EndAll();
void WINAPI my_GetLocalTime(LPSYSTEMTIME lpSystemTime)
{
#if 1
// 执行缺省调用
CAdAutoHookApi autoHook(&gHooks, my_GetLocalTime);
GetLocalTime(lpSystemTime);
#else
}
这样就完成了,只要你的DLL加载到一个进程中,相应的函数就被你截获了.
下面谈一下如何让一个程序加载你的DLL,一般有两种方式:
1.修改原程序的Import Table,增加导入你的DLL(静态加载):
使用工具:CFF Explorer,是Explorer Suite(http://www.ntcore.com/)中的一个工具 用于PE文件的修改,下面这个操作就是notepad.exe加载rand.dll的操作:
logOutput(formatString("ApiDebugger - sub_4026B0(%s=>%s)",
hexData1.c_str(), hexData2.c_str()));
return ret;
}
const BYTE verifyData[] = { 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x2C, 0x01, 0x00, 0x00 };
string hexData1 = toHexString((const char *)pbData, strlen((const char *)pbData));
int ret = sub_4026B0(pbData);
string hexData2 = toHexString((const char *)pbData, strlen((const char *)pbData));
1)HOOK几个API,加密狗一般最终都是使用CreateFile打开设备,调用API DeviceIoControl与加密狗进行数据交互:
gHooks.Add(_T("KERNEL32.DLL"), "CreateFileA", my_CreateFileA);
gHooks.Add(_T("KERNEL32.DLL"), "CreateFileW", my_CreateFileW);
只要Rebuild Import Table,然后再Save/Save As就可以保存新的文件,这样你的dll就自动的被加载了,DLL加载的时候也就实现了API HOOK。
这种方式因为对原程序进行了修改,如果程序有CRC校验,运行肯定就不正确了,就需要通过破解去除CRC校验部分的判断.
2.动态DLL加载:
};
举例说明使用方法:
假设一个软件是试用软件,试用7天,最笨的办法就是改本机时间,但如果用API HOOK技术就可以很容易做到,可以先用CFF Explorer或者Dependency查看一下该软件是调用哪个函数来获取系统当前时间的,假如是GetLocalTime函数(当然获取时间的函数还有很多API),那么我就可以截获GetLocalTime,返回一个永不过期的时间.
*lpBytesReturned = ReadDataFromFile(formatstring(L"1\\%d.in", gCallCounter).c_str(), lpOutBuffer, nOutBufferSize);
gCallCounter ++;
}
#endif
return ret;
}
2)使用刚才提到的方法进行DLL导入
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped
)
{
BOOL ret = TRUE;
CAdAutoHookApi autoHook(&gHooks, my_DeviceIoControl);
void *addr = (void *)0x004026B0;
if(gHooks.Add(addr, my_sub_4026B0, verifyData, sizeof(verifyData), 0) != NULL)
{
logOutput(formatString("ApiDebugger - hook sub_4026B0 ok.\r\n"));
3)带狗保存数据,数据记录完成后,用保存的数据进行狗的模拟
2. 360 CrackMe加密API的截获,
下图是用给的提示用户名:360和正确的密码输入,返回API HOOK的Log output:
解密的结果:
5375636365737300000000000000000000000000000000000000000000000000
gHooks.Add(_T("KERNEL32.DLL"), "DeviceIoControl", my_DeviceIoControl);
static int gCallCounter = 0;
BOOL WINAPI my_DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
// 004026B0 ;
static int my_sub_4026B0(BYTE *pbData)
{
CAdAutoHookApi autoHook(&gHooks, my_sub_4026B0);
sub_4026B0_func sub_4026B0 = (sub_4026B0_func)(0x004026B0);
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
// 截获KERNEL32.DLL的API GetLocalTime到你的函数地址my_GetLocalTime
gHooks.Add(_T("KERNEL32.DLL"), "GetLocalTime", my_GetLocalTime);
// 指定DLL的某个函数进行HOOK
HANDLE Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData = 0);
// 给定一个函数地址进行HOOK
HANDLE Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData = NULL, DWORD verifySize = 0, DWORD dwData = 0);
【源程序】程序破解之 API HOOK技术
API HOOK,就是截获API调用的技术,在程序对一个API调用之前先执行你的函数,然后根据你的需要可以执行缺省的API调用或者进行其他处理,假设如果想截获一个进程对网络的访问,一般是几个socket API : recv,recvfrom, send, sendto等等,当然你可以用网络抓包工具,这里只介绍通过API HOOK的方式来实现, 主要原理是在程序运行中动态修改目标函数地址的内存数据,使用jmp语句跳转到你的函数地址,执行完后再恢复内存数据, 汇编代码是:
// 改变函数的行为,返回固定的时间
// 2012-12-28 10:00:00
lpSystemTime->wYear = 2012;
lpSystemTime->wMonth = 12;
lpSystemTime->wDayOfWeek = 0;
lpSystemTime->wDay = 28;
lpSystemTime->wHour = 10;
VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect);
在很多年前这种技术非常的流行,有各种各样的工具和SDK,我自己也实现了一个C++ class,名为 CAdHookApi, 主要几个函数是:
class CAdHookApi
{
public:
1.首先,声明一个全局变量:
static CAdHookApi gHooks;
2.确定要截获API的参数,API GetLocalTime对应的DLL是KERNEL32.DLL, API定义为:
void WINAPI GetLocalTime(LPSYSTEMTIME lpSystemTime);
写一个新的函数,定义和原函数保持一致: