原文地址 http://blog.csdn.net/evi10r/article/details/7349109
早些时间看郁金香的教程,写过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;
- }