早些时间看郁金香的教程,写过qq游戏练练看的挂,那时候CE附加QQ游戏大厅的时候貌似是没有任何保护的,昨天舍友让做个斗地主的记牌器,但是,我用CE附加的时候,被检测到了,其实不附加也会被检测,所以猜测可能只是检测窗口进程或是模块名称啥的吧,被检测到的时候主程序会退出,但是那个对话框还在,就是那个SX什么什么的,所以如果是QQgame启动了某个线程来检测非法的话,在主程序退出其他线程对象都释放掉的时候,那个检测的线程对象还是存在的(提示SX非法的对话框别关掉!)。借助pt很容易就找到了这个线程。
未开CE前线程状态:
开了CE被检测到后的线程状态:
然后该怎么办就不用说了吧,干掉这个线程就OK了。
若是嫌麻烦每次都要开pt找线程的话,可以写个结束这个模块内线程的程序
- #include "stdafx.h"
- #include "windows.h"
- #include "TlHelp32.h"
- const TCHAR QQ_GAME[] = _T("QQGame.exe");
- const TCHAR QQ_THREAD_DLL[] = _T("TenSLX.dll");
- typedef enum _THREADINFOCLASS {
- ThreadBasicInformation,
- ThreadTimes,
- ThreadPriority,
- ThreadBasePriority,
- ThreadAffinityMask,
- ThreadImpersonationToken,
- ThreadDescriptorTableEntry,
- ThreadEnableAlignmentFaultFixup,
- ThreadEventPair_Reusable,
- ThreadQuerySetWin32StartAddress,
- ThreadZeroTlsCell,
- ThreadPerformanceCount,
- ThreadAmILastThread,
- ThreadIdealProcessor,
- ThreadPriorityBoost,
- ThreadSetTlsArrayAddress,
- ThreadIsIoPending,
- ThreadHideFromDebugger,
- ThreadBreakOnTermination,
- MaxThreadInfoClass
- } THREADINFOCLASS;
- typedef LONG (__stdcall *_pfnZwQueryInformationThread) (
- IN HANDLE ThreadHandle,
- IN THREADINFOCLASS ThreadInformationClass,
- OUT PVOID ThreadInformation,
- IN ULONG ThreadInformationLength,
- OUT PULONG ReturnLength OPTIONAL
- );
- HANDLE m_GameProcessHandle;
- //记录QQ_THREAD_DLL信息
- BYTE * m_pmodBaseAddr;
- DWORD m_dwmodBaseSize;
- _pfnZwQueryInformationThread m_pfnZwQueryInformationThread;
- BOOL StartPatch();//PATCHQQ主函数
- DWORD EnablePrivilege (LPCTSTR name);//提权函数
- BOOL ListProcessModules(DWORD dwPID);//枚举指定进程的模块
- BOOL ListProcessThreads( DWORD dwOwnerPID);//枚举指定进程创建的线程,并结束掉QQ保护线程
- PVOID ShowThreadInfo(DWORD tid);//获取线程的起始地址
- int _tmain(int argc, _TCHAR* argv[])
- {
- m_pfnZwQueryInformationThread =(_pfnZwQueryInformationThread)\
- GetProcAddress (LoadLibrary(_T("ntdll.dll")),"ZwQueryInformationThread");
- if (StartPatch())
- {
- printf("可以CE附加QQ游戏大厅了\n");
- }
- else
- printf("失败!\n");
- return 0;
- }
- BOOL StartPatch()
- {
- if(0!=EnablePrivilege (SE_DEBUG_NAME))
- {
- return FALSE;
- }
- HANDLE hProcessSnap;
- PROCESSENTRY32 pe32;
- hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
- if( hProcessSnap == INVALID_HANDLE_VALUE )
- {
- return FALSE;
- }
- pe32.dwSize = sizeof( PROCESSENTRY32 );
- if( !Process32First( hProcessSnap, &pe32 ) )
- {
- CloseHandle( hProcessSnap );
- return FALSE;
- }
- BOOL bStartGame = FALSE;
- do
- {
- if (_tcscmp(pe32.szExeFile, QQ_GAME) == 0)
- {
- bStartGame = TRUE;
- m_GameProcessHandle = OpenProcess(PROCESS_VM_WRITE|PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION,\
- FALSE, pe32.th32ProcessID);
- if (m_GameProcessHandle == NULL)
- {
- return FALSE;
- }
- for (int i=0; i<5;i++)
- {
- if (!ListProcessModules(pe32.th32ProcessID))
- {
- return FALSE;
- }
- }
- if (!ListProcessThreads(pe32.th32ProcessID))
- {
- return FALSE;
- }
- }
- } while( Process32Next( hProcessSnap, &pe32 ) );
- if (!bStartGame)
- {
- MessageBox(NULL,_T("运行QQ大厅后才能使用"),_T("提示"),MB_OK);
- return FALSE;
- }
- CloseHandle( hProcessSnap );
- return TRUE;
- }
- DWORD EnablePrivilege (LPCTSTR name)
- {
- HANDLE hToken;
- BOOL rv;
- //设置结构
- TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
- // 查找权限值
- LookupPrivilegeValue (
- 0,
- name,
- &priv.Privileges[0].Luid
- );
- // 打开本进程Token
- OpenProcessToken(
- GetCurrentProcess (),
- TOKEN_ADJUST_PRIVILEGES,
- &hToken
- );
- // 提权
- AdjustTokenPrivileges (
- hToken,
- FALSE,
- &priv,
- sizeof priv,
- 0,
- 0
- );
- // 返回值,错误信息,如果操作成功,则应为ERROR_SUCCESS,为O
- rv = GetLastError();
- // 关闭Token
- CloseHandle (hToken);
- return rv;
- }
- BOOL ListProcessModules(DWORD dwPID)
- {
- HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
- MODULEENTRY32 me32;
- hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
- if( hModuleSnap == INVALID_HANDLE_VALUE )
- {
- return( FALSE );
- }
- me32.dwSize = sizeof( MODULEENTRY32 );
- if( !Module32First( hModuleSnap, &me32 ) )
- {
- CloseHandle( hModuleSnap );
- return( FALSE );
- }
- do
- {
- if (_tcscmp(me32.szModule, QQ_THREAD_DLL) == 0)
- {
- m_pmodBaseAddr = me32.modBaseAddr;
- m_dwmodBaseSize = me32.modBaseSize;
- }
- }while( Module32Next( hModuleSnap, &me32 ));
- CloseHandle( hModuleSnap );
- return( TRUE );
- }
- BOOL ListProcessThreads( DWORD dwOwnerPID)
- {
- HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
- THREADENTRY32 te32;
- PVOID addr;
- hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
- if( hThreadSnap == INVALID_HANDLE_VALUE )
- return( FALSE );
- te32.dwSize = sizeof(THREADENTRY32 );
- if( !Thread32First( hThreadSnap, &te32 ) )
- {
- CloseHandle( hThreadSnap );
- return( FALSE );
- }
- do
- {
- if( te32.th32OwnerProcessID == dwOwnerPID )
- {
- addr = ShowThreadInfo(te32.th32ThreadID);
- if(((DWORD)addr>(DWORD)m_pmodBaseAddr)&&((DWORD)addr<\
- ((DWORD)m_pmodBaseAddr+(DWORD)m_dwmodBaseSize)))
- {
- HANDLE oth=OpenThread(THREAD_ALL_ACCESS,FALSE,te32.th32ThreadID);
- //关闭这个线程
- TerminateThread(oth, 0);
- }
- }
- } while( Thread32Next(hThreadSnap, &te32 ) );
- CloseHandle( hThreadSnap );
- return( TRUE );
- }
- PVOID ShowThreadInfo(DWORD tid)
- {
- PVOID startaddr;
- HANDLE thread;
- //thread = m_pfnOpenThread_ex(THREAD_ALL_ACCESS,FALSE,tid);
- thread=OpenThread(THREAD_ALL_ACCESS,FALSE,tid);
- if (thread == NULL)
- return FALSE;
- m_pfnZwQueryInformationThread(thread,
- ThreadQuerySetWin32StartAddress,
- &startaddr,
- sizeof(startaddr),
- NULL);
- CloseHandle (thread);
- return startaddr;
- }
#include "stdafx.h"
#include "windows.h"
#include "TlHelp32.h"
const TCHAR QQ_GAME[] = _T("QQGame.exe");
const TCHAR QQ_THREAD_DLL[] = _T("TenSLX.dll");
typedef enum _THREADINFOCLASS {
ThreadBasicInformation,
ThreadTimes,
ThreadPriority,
ThreadBasePriority,
ThreadAffinityMask,
ThreadImpersonationToken,
ThreadDescriptorTableEntry,
ThreadEnableAlignmentFaultFixup,
ThreadEventPair_Reusable,
ThreadQuerySetWin32StartAddress,
ThreadZeroTlsCell,
ThreadPerformanceCount,
ThreadAmILastThread,
ThreadIdealProcessor,
ThreadPriorityBoost,
ThreadSetTlsArrayAddress,
ThreadIsIoPending,
ThreadHideFromDebugger,
ThreadBreakOnTermination,
MaxThreadInfoClass
} THREADINFOCLASS;
typedef LONG (__stdcall *_pfnZwQueryInformationThread) (
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
HANDLE m_GameProcessHandle;
//记录QQ_THREAD_DLL信息
BYTE * m_pmodBaseAddr;
DWORD m_dwmodBaseSize;
_pfnZwQueryInformationThread m_pfnZwQueryInformationThread;
BOOL StartPatch();//PATCHQQ主函数
DWORD EnablePrivilege (LPCTSTR name);//提权函数
BOOL ListProcessModules(DWORD dwPID);//枚举指定进程的模块
BOOL ListProcessThreads( DWORD dwOwnerPID);//枚举指定进程创建的线程,并结束掉QQ保护线程
PVOID ShowThreadInfo(DWORD tid);//获取线程的起始地址
int _tmain(int argc, _TCHAR* argv[])
{
m_pfnZwQueryInformationThread =(_pfnZwQueryInformationThread)\
GetProcAddress (LoadLibrary(_T("ntdll.dll")),"ZwQueryInformationThread");
if (StartPatch())
{
printf("可以CE附加QQ游戏大厅了\n");
}
else
printf("失败!\n");
return 0;
}
BOOL StartPatch()
{
if(0!=EnablePrivilege (SE_DEBUG_NAME))
{
return FALSE;
}
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
return FALSE;
}
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hProcessSnap, &pe32 ) )
{
CloseHandle( hProcessSnap );
return FALSE;
}
BOOL bStartGame = FALSE;
do
{
if (_tcscmp(pe32.szExeFile, QQ_GAME) == 0)
{
bStartGame = TRUE;
m_GameProcessHandle = OpenProcess(PROCESS_VM_WRITE|PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION,\
FALSE, pe32.th32ProcessID);
if (m_GameProcessHandle == NULL)
{
return FALSE;
}
for (int i=0; i<5;i++)
{
if (!ListProcessModules(pe32.th32ProcessID))
{
return FALSE;
}
}
if (!ListProcessThreads(pe32.th32ProcessID))
{
return FALSE;
}
}
} while( Process32Next( hProcessSnap, &pe32 ) );
if (!bStartGame)
{
MessageBox(NULL,_T("运行QQ大厅后才能使用"),_T("提示"),MB_OK);
return FALSE;
}
CloseHandle( hProcessSnap );
return TRUE;
}
DWORD EnablePrivilege (LPCTSTR name)
{
HANDLE hToken;
BOOL rv;
//设置结构
TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
// 查找权限值
LookupPrivilegeValue (
0,
name,
&priv.Privileges[0].Luid
);
// 打开本进程Token
OpenProcessToken(
GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
&hToken
);
// 提权
AdjustTokenPrivileges (
hToken,
FALSE,
&priv,
sizeof priv,
0,
0
);
// 返回值,错误信息,如果操作成功,则应为ERROR_SUCCESS,为O
rv = GetLastError();
// 关闭Token
CloseHandle (hToken);
return rv;
}
BOOL ListProcessModules(DWORD dwPID)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
return( FALSE );
}
me32.dwSize = sizeof( MODULEENTRY32 );
if( !Module32First( hModuleSnap, &me32 ) )
{
CloseHandle( hModuleSnap );
return( FALSE );
}
do
{
if (_tcscmp(me32.szModule, QQ_THREAD_DLL) == 0)
{
m_pmodBaseAddr = me32.modBaseAddr;
m_dwmodBaseSize = me32.modBaseSize;
}
}while( Module32Next( hModuleSnap, &me32 ));
CloseHandle( hModuleSnap );
return( TRUE );
}
BOOL ListProcessThreads( DWORD dwOwnerPID)
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
PVOID addr;
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( FALSE );
te32.dwSize = sizeof(THREADENTRY32 );
if( !Thread32First( hThreadSnap, &te32 ) )
{
CloseHandle( hThreadSnap );
return( FALSE );
}
do
{
if( te32.th32OwnerProcessID == dwOwnerPID )
{
addr = ShowThreadInfo(te32.th32ThreadID);
if(((DWORD)addr>(DWORD)m_pmodBaseAddr)&&((DWORD)addr<\
((DWORD)m_pmodBaseAddr+(DWORD)m_dwmodBaseSize)))
{
HANDLE oth=OpenThread(THREAD_ALL_ACCESS,FALSE,te32.th32ThreadID);
//关闭这个线程
TerminateThread(oth, 0);
}
}
} while( Thread32Next(hThreadSnap, &te32 ) );
CloseHandle( hThreadSnap );
return( TRUE );
}
PVOID ShowThreadInfo(DWORD tid)
{
PVOID startaddr;
HANDLE thread;
//thread = m_pfnOpenThread_ex(THREAD_ALL_ACCESS,FALSE,tid);
thread=OpenThread(THREAD_ALL_ACCESS,FALSE,tid);
if (thread == NULL)
return FALSE;
m_pfnZwQueryInformationThread(thread,
ThreadQuerySetWin32StartAddress,
&startaddr,
sizeof(startaddr),
NULL);
CloseHandle (thread);
return startaddr;
}