上次发的帖子觉得里面的hook方式不稳定,这次自己写一个,测试beta5版qq的时候可以使用了,上次发的bin在beta5版里会挂。
看到有不妥的地方,请告诉我,发帖的目的就是这个!
InterlockedExchange64这个函数在XP里不能用(ring3下),其实是使用lock cmpxchg8b指令,从ring0的bin里抠出来一个,组织成函数方便使用。
码如下:(dll工程,编译要去掉gs开关,还有一处需要注意的地方,见注释)
#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32")
#pragma pack(1)
typedef struct
{
BYTE jmp;
int address;
BYTE byte_3[3];
} JUMPCODE, *PJUMPCODE;
BYTE characteristic[8] = {0x8b, 0xff, 0x55, 0x8b, 0xec, 0, 0, 0};
DWORD pOrigFunc;
DWORD RetAddr = 0;
LONGLONG _declspec(naked) _cdecl InlockExchange64 ( IN OUT LONGLONG volatile *Destination, IN LONGLONG ExChange)
{
_asm
{
push ebp
mov ebp, esp
push edi
push ebx
push edx
mov edi, [ebp+8]
mov eax, [edi]
mov edx, [edi+4]
mov ebx, dword ptr [ebp+0Ch]
mov ecx, dword ptr [ebp+0Ch+4]
lock cmpxchg8b qword ptr [edi]
pop edx
pop ebx
pop edi
mov ebp, esp
pop ebp
retn
}
}
int __stdcall my_sendto(
SOCKET s,
const char FAR *buf,
int len,
int flags,
const struct sockaddr FAR *to,
int tolen
);
DWORD WINAPI my_thread(LPVOID lp);
int hook(PCSTR pszDllName, PCSTR pszFunctionName, DWORD hackfunc);
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
DWORD dwOldProtect;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
OutputDebugString("-->[hook_sendto]\n");
CreateThread(0, 0, my_thread, 0, 0, 0);
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
{
OutputDebugString("<--[hook_sendto]\n");
if (RetAddr)
{
VirtualProtect((PVOID)pOrigFunc, 8, PAGE_EXECUTE_READWRITE, &dwOldProtect);
InlockExchange64((PLONGLONG)pOrigFunc, *(PLONGLONG)&characteristic[0]);
VirtualProtect((PVOID)pOrigFunc, 8, dwOldProtect, &dwOldProtect);
}
break;
}
}
return TRUE;
}
DWORD WINAPI my_thread(LPVOID lp)
{
hook("ws2_32.dll", "sendto", (DWORD)my_sendto);
return 0;
}
int hook(PCSTR pszDllName, PCSTR pszFunctionName, DWORD hackfunc)
{
HMODULE hDll;
JUMPCODE jmpcode;
DWORD dwOldProtect;
hDll = GetModuleHandle(pszDllName);
if(hDll == NULL)
{
OutputDebugString("GetModuleHandle()");
return 0;
}
pOrigFunc = (DWORD)GetProcAddress(hDll, pszFunctionName);
if(pOrigFunc == NULL)
{
OutputDebugString("GetProcAddress()");
return 0;
}
if (memcmp((PVOID)pOrigFunc, characteristic, 5))
{
OutputDebugString("memcmp()不相等");
return 0;
}
jmpcode.jmp = 0xe9;
jmpcode.address = hackfunc - pOrigFunc - 5;
jmpcode.byte_3[0] = *(PCHAR)(pOrigFunc + 5);
jmpcode.byte_3[1] = *(PCHAR)(pOrigFunc + 6);
jmpcode.byte_3[2] = *(PCHAR)(pOrigFunc + 7);
characteristic[5] = *(PCHAR)(pOrigFunc + 5);
characteristic[6] = *(PCHAR)(pOrigFunc + 6);
characteristic[7] = *(PCHAR)(pOrigFunc + 7);
VirtualProtect((PVOID)pOrigFunc, 8, PAGE_EXECUTE_READWRITE, &dwOldProtect);
InlockExchange64((PLONGLONG)pOrigFunc, *(PLONGLONG)&jmpcode);
VirtualProtect((PVOID)pOrigFunc, 8, dwOldProtect, &dwOldProtect);
RetAddr = pOrigFunc + 5;
return 1;
}
int __stdcall my_sendto(
SOCKET s,
const char FAR *buf,
int len,
int flags,
const struct sockaddr FAR *to,
int tolen
)
{
char buff[22];
if(len >= 27)
{
if (*(DWORD*)buf == 0x10003)
{
memset(buff, 0, sizeof(buff));
sprintf(&buff[strlen(buff)], "=IP: %s\n", inet_ntoa(((struct sockaddr_in *)to)->sin_addr));
OutputDebugString(buff);
}
}
__asm
{
pop esi // 反编译后看到我的编译器会push esi
add esp, 18h // 反编译后看到我的编译器会sub esp, 18h
mov eax, RetAddr
jmp eax
}
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课