稍稍总结一下在Crack或Rervese中比较常见的一些反调试方法,实现起来也比较简单,之后有写的Demo源码参考,没有太大的难度。

①最简单也是最基础的,Windows提供的API接口:

IsDebuggerPresent(),这API实际上就是访问PEB的BeingDebugged标志来判断是否处于调试状态。

if (IsDebuggerPresent())    //API接口
{AfxMessageBox(L"检测到调试器");
}
else
{AfxMessageBox(L"没有检测到调试器");
}

②自己用汇编实现实现IsDebuggerPresent,

如何获得PEB呢?在应用层,fs寄存器是指向当前线程的TEB结构的,而在内核层,fs寄存器指向PCR(Processor Control Region)的内存,其数据类型是KPCR。所以可以通过当前线程的TEB获得PEB,再取出BeingDebugged的值。

mov   eax, fs:18h     // TEB Self指针
mov   eax, [eax+30h]  // PEB
movzx eax, [eax+2]    // PEB->BeingDebugge
_asm
{push eax;                 //TEBmov eax, fs:[0x30];         // PEBmovzx eax, byte ptr[eax + 2];  //BeingDebuggedmov dword ptr[Value], eax;   //取值pop eax;
}
if (Value)   //判断
{AfxMessageBox(L"检测到调试器");
}
else
{AfxMessageBox(L"没有检测到调试器");
}

讲个题外话,也是关于FS寄存器的前两天有人是问了我一个问题,说是怎么让dll只被特定的进程加载,了解fs寄存器之后就很简单了,在dll加载的DllMain()函数中对加载的当前进程进行判断,看是否是自己的目标进程,如果不是,就拒绝被加载。下面是一段测试代码,可以获得当前进程的进程名。

#include "windows.h"        //这段测试代码可以获得当前进程名
#include "stdio.h"
int main(void)
{LPSTR name;__asm{mov eax,fs:[0x18]    //得到Teb  当线程运行于用户空间时段寄存器FS指向当前线程的TEB,FS:[0x18] 就是指在                                //Self,其内容就是TEB的起点mov eax,[eax+0x30]    //Teb偏移0x30处指向Pebmov eax,[eax+0xc]    //Peb偏移 0xc 处指向 进程加载的模块的信息 _PEB_LDR_DATA结构mov eax,[eax+0xc]mov eax,[eax+0x30]mov name,eax}wprintf(L"%s\n",name);return 0;
}

③NtGlobalFlag 也是类似于BeingDebugged的一个标志

在Peb中取出。如果是调试状态下,NtGlobalFlag的值会是0x70,正常情况下不是。之前是利用fs寄存器获得的Peb基地址,这里使用Native API 的方法。

HANDLE hProcess = NULL;
DWORD ProcessId = 0;
PROCESS_BASIC_INFORMATION Pbi;
PFNZwQueryInformationProcess pfunc_ZwQueryInformationProcess = NULL;
ProcessId = GetCurrentProcessId();
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId);
if (hProcess != NULL)
{HMODULE hModule = LoadLibrary(L"ntdll.dll");pfunc_ZwQueryInformationProcess = (PFNZwQueryInformationProcess)GetProcAddress(hModule, "ZwQueryInformationProcess");NTSTATUS Status = pfunc_ZwQueryInformationProcess(hProcess,ProcessBasicInformation,&Pbi,sizeof(PROCESS_BASIC_INFORMATION),NULL);if (NT_SUCCESS(Status)){DWORD ByteRead = 0;WORD NtGlobalFlag = 0;bool bIsDebug = false;ULONG PebBase = (ULONG)Pbi.PebBaseAddress;if (ReadProcessMemory(hProcess, (LPCVOID)(PebBase + 0x68), &NtGlobalFlag, 2, &ByteRead) && ByteRead == 2){// PEB.NtGlobalFlag// +0x068 NtGlobalFlag     : Uint4Bif (NtGlobalFlag == 0x70)  //判断是否处于调试状态{bIsDebug = true;}}if (bIsDebug){AfxMessageBox(L"检测到调试器");}else{AfxMessageBox(L"没有检测到调试器");}}CloseHandle(hProcess);

④PEB.ProcessHeap.Flags 和ForceFlags

进程堆标志,系统创建进程时会将Flags置为0x02(HEAP_GROWABLE),将ForceFlags置为0。但是进程被调试时,这两个标志通常被设置为0x50000062h和0x40000060h。下面是检测代码

HANDLE hProcess = NULL;DWORD ProcessId = 0;PROCESS_BASIC_INFORMATION Pbi;PFNZwQueryInformationProcess pfunc_pZwQueryInformationProcess = NULL;ULONG Flags = 0;ULONG ForceFlags = 0;switch (g_WinVersion){case WINDOWS_VERSION_XP:Flags = 0xC;ForceFlags = 0x10;break;case WINDOWS_VERSION_2K3_SP1_SP2:Flags = 0xC;ForceFlags = 0x10;break;case WINDOWS_VERSION_7:Flags = 0x40;ForceFlags = 0x44;break;}ProcessId = GetCurrentProcessId();hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId);if (hProcess != NULL){HMODULE hModule = LoadLibrary(L"ntdll.dll");pfunc_pZwQueryInformationProcess = (PFNZwQueryInformationProcess)GetProcAddress(hModule, "ZwQueryInformationProcess");NTSTATUS Status = pfunc_pZwQueryInformationProcess(hProcess,ProcessBasicInformation,&Pbi,sizeof(PROCESS_BASIC_INFORMATION),NULL);if (NT_SUCCESS(Status)){DWORD ByteRead = 0;ULONG ProcessHeap = 0;DWORD HeapFlags = 0;DWORD ForceFlagsValue = 1;bool bIsDebug = false;ULONG PebBase = (ULONG)Pbi.PebBaseAddress;if (ReadProcessMemory(hProcess, (LPCVOID)(PebBase + 0x18), &ProcessHeap, 4, &ByteRead)){if (ReadProcessMemory(hProcess, (LPCVOID)(ProcessHeap + Flags), &HeapFlags, 4, &ByteRead)){// PEB.ProcessHeap.Flags// nt!_PEB// +0x018 ProcessHeap      : Ptr32 Void _HEAP// nt!_HEAP// WIN7 ProcessHeap 还有一个 Heap// +0x018 Heap : Ptr32 _HEAP// WIN7// +0x040 Flags            : Uint4B// +0x044 ForceFlags       : Uint4B// WIN2K3// +0x00C Flags            : Uint4B// +0x010 ForceFlags       : Uint4B// WINXP// +0x00C Flags            : Uint4B// +0x010 ForceFlags       : Uint4Bif (HeapFlags != 2) //系统创建进程时会将其设置为HEAP_GROEABLE(0x2){bIsDebug = true;}else{ReadProcessMemory(hProcess,(LPCVOID)(PebBase+ForceFlags),&ForceFlagsValue,4,&ByteRead);if (ForceFlagsValue != 0){bIsDebug = true;}}}}if (bIsDebug){AfxMessageBox(L"检测到调试器");}else{AfxMessageBox(L"没有检测到调试器");}}CloseHandle(hProcess);}

⑤检测父进程

一般双击运行的进程的父进程都是explorer.exe,但是如果进程被调试,父进程则是调试器进程,也就是说如果父进程不是explorer.exe,就可以认为有调试器存在。

DWORD ExplorerId = 0;PROCESSENTRY32 pe32 = {0};CString str;BOOL bIsDebug = FALSE;DWORD ProcessId = GetCurrentProcessId();// 获取 Explorer 进程ID::GetWindowThreadProcessId(::FindWindow(L"Progman", NULL), &ExplorerId);HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);if (hProcessSnap != INVALID_HANDLE_VALUE){pe32.dwSize = sizeof(PROCESSENTRY32);if (Process32First(hProcessSnap, &pe32)){do{if (ProcessId == pe32.th32ProcessID){str.Format(L"进程ID:%d 父进程ID:%d Explorer进程ID:%d", ProcessId, pe32.th32ParentProcessID, ExplorerId);if (pe32.th32ParentProcessID != ExplorerId){bIsDebug = TRUE;break;}}}while (Process32Next(hProcessSnap, &pe32));}AfxMessageBox(str);}if (bIsDebug){AfxMessageBox(L"检测到调试器");}else{AfxMessageBox(L"没有检测到调试器");}CloseHandle (hProcessSnap);

⑥SeDebugPrivilege权限判断

默认情况下进程是没有SeDebugPrivilege权限的,但是当进程通过OD或者xdbg等调试器启动时,由于调试器本身启动了SeDebugPrivilege权限,当调试进程被加载时SeDebugPrivilege也就被继承了。所以我们可以检测进程的SeDebugPrivilege权限来间接判断是否存在调试器,而对SeDebugPrivilege权限的判断可以用能否打开csrss.exe进程来判断

HANDLE hProcess = NULL;PROCESSENTRY32 Pe32 = {0};HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (hProcessSnap == INVALID_HANDLE_VALUE){return;}Pe32.dwSize = sizeof(PROCESSENTRY32);if (Process32First(hProcessSnap, &Pe32)){do{if (_wcsicmp(L"csrss.exe", Pe32.szExeFile) == 0){HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,Pe32.th32ProcessID);if (hProcess){AfxMessageBox(L"检测到调试器");}else{AfxMessageBox(L"没有检测到调试器");}CloseHandle(hProcess);}}while (Process32Next(hProcessSnap, &Pe32));}CloseHandle(hProcessSnap);

⑦检测硬件断点

其实也不能算是完完全全对调试器的检测,只能说是检测硬件断点,通过设置SHE处理例程,然后自己手动触发异常来检测硬件断点。

#pragma data_seg(".Hardware")
BOOL Hardwarei = FALSE;
DWORD addr = 0;
#pragma data_seg()
#pragma comment(linker, "/section:.Hardware,RWS")LONG WINAPI HardwareExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo)
{if (ExceptionInfo->ContextRecord->Dr0 != 0|| ExceptionInfo->ContextRecord->Dr1 != 0|| ExceptionInfo->ContextRecord->Dr2 != 0|| ExceptionInfo->ContextRecord->Dr3 != 0){Hardwarei = TRUE;ExceptionInfo->ContextRecord->Dr0 = 0;ExceptionInfo->ContextRecord->Dr1 = 0;ExceptionInfo->ContextRecord->Dr2 = 0;ExceptionInfo->ContextRecord->Dr3 = 0;}// 设置新的eip 让程序调转到safe执行ExceptionInfo->ContextRecord->Eip = addr;return EXCEPTION_CONTINUE_EXECUTION;
}BOOL IsHardware()
{LPTOP_LEVEL_EXCEPTION_FILTER lpsetun;lpsetun = ::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)HardwareExceptionFilter);_asm{mov addr, offset safe;int 3;}
safe:::SetUnhandledExceptionFilter(lpsetun);return Hardwarei;
}void CAntiDebugDlg::OnBnClickedButton12()
{char *p = "aaaaaaaaaaaaaaddddddddddddddbbbbbbbbbbbb";if (IsHardware()){AfxMessageBox(L"检测到硬件执行断点");}else{AfxMessageBox(L"没有检测到硬件执行断点");}
}

⑧上面是通过SHE来检测硬件断点,当然还可以通过VEH来检测

思路是一样的,差别就是SHE与VEH,一个是针对线程的,一个是针对进程的。

/************************************************************************/
/* 硬件执行断点,VEH                                                    */
/************************************************************************/
#pragma data_seg(".VehHardware")
BOOL VehHardwarei = FALSE;
DWORD Vehaddr;
#pragma data_seg()
#pragma comment(linker, "/section:.VehHardware,RWS")LONG NTAPI VehHardwareExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo)
{if (ExceptionInfo->ContextRecord->Dr0 != 0|| ExceptionInfo->ContextRecord->Dr1 != 0|| ExceptionInfo->ContextRecord->Dr2 != 0|| ExceptionInfo->ContextRecord->Dr3 != 0){VehHardwarei = TRUE;ExceptionInfo->ContextRecord->Dr0 = 0;ExceptionInfo->ContextRecord->Dr1 = 0;ExceptionInfo->ContextRecord->Dr2 = 0;ExceptionInfo->ContextRecord->Dr3 = 0;}// 设置新的eip 让程序调转到safe执行ExceptionInfo->ContextRecord->Eip = Vehaddr;return EXCEPTION_CONTINUE_EXECUTION;
}BOOL IsVehHardware()
{PVOID VEHandle = ::AddVectoredExceptionHandler(1, VehHardwareExceptionFilter);_asm{mov Vehaddr, offset vehsafe;int 3;}
vehsafe:if (VEHandle != NULL){RemoveVectoredExceptionHandler(VEHandle);}return VehHardwarei;
}void CAntiDebugDlg::OnBnClickedButton16()
{// TODO: 在此添加控件通知处理程序代码char *p = "aaaaaaaaaaaaaaddddddddddddddbbbbbbbbbbbb";if (IsVehHardware()){AfxMessageBox(L"检测到硬件执行断点");}else{AfxMessageBox(L"没有检测到硬件执行断点");}
}

⑨利用异常处理

通过我们自己安装异常处理例程,然后手动触发异常,如果存在OD则不会走异常处理

/************************************************************************/
/* 异常处理判断是否存在OD                                                */
/************************************************************************/
#pragma data_seg(".excep")
BOOL Exceptioni = FALSE;
#pragma data_seg()
#pragma comment(linker, "/section:.excep,RWS")LONG WINAPI ExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo)
{Exceptioni = TRUE;  //进行异常处理,则不存在ODreturn EXCEPTION_CONTINUE_EXECUTION;
}
BOOL IsException()
{ULONG OldProtect = 0;LPTOP_LEVEL_EXCEPTION_FILTER lpsetun;lpsetun = ::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ExceptionFilter);  //安装自己的异常处理LPVOID pBuff = ::VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE);*((PWORD)pBuff) = 0xc3;::VirtualProtect(pBuff, 0x1000, PAGE_EXECUTE_READ | PAGE_GUARD, &OldProtect);_asm{call pBuff;  //如果存在OD,会把这里的call 当成中断处理,不会进行异常处理}::SetUnhandledExceptionFilter(lpsetun);  //将原来的异常处理恢复顶层return Exceptioni;
}
void CAntiDebugDlg::OnBnClickedButton13()
{// TODO: 在此添加控件通知处理程序代码if (IsException()){AfxMessageBox(L"没有检测到调试器");}else{AfxMessageBox(L"检测到调试器");}
}

⑩单步异常检测

单步异常是调试器用来单步调试时使用,我们也可以用来检测调试器的存在,由我们自己设置标志寄存器的值,触发单步异常。如果存在调试器,这里的单步异常会由调试器进行处理,而不会走__except()异常处理,但这种检测方法的局限性就在于检测代码需要被调试器单步调试的时候才有效。扯个题外话,这里我还打算尝试一下C++11新支持的异常处理try{} /catch(){},没想到一弄直接就崩溃了,还是老老实实用__try/__except吧!

/************************************************************************/
/* 单步异常检测                                                         */
/************************************************************************/
//这种方法需要下面的汇编代码在单步跟中的时候才有效
void CAntiDebugDlg::OnBnClickedButton14()
{// TODO: 在此添加控件通知处理程序代码__try{// 触发单步异常_asm{pushfd;     //标志寄存器入栈or dword ptr [esp], 100h; // 将 TF =1  单步popfd;  }AfxMessageBox(L"检测到调试器");  //如果不触发异常,说明有调试器}//catch(...)  用C++ 11的catch()还是没有原生__except强大,用catch(...)这里会崩溃__except(EXCEPTION_EXECUTE_HANDLER){AfxMessageBox(L"没有检测到调试器");}
}

11.into使调试器一直循环。

使用溢出中断,在没有调试器的情况下会走异常处理,然后正常的执行下去,如果存在OD则会自己处理中断,导致一直在这里循环。其实这里用into的溢出中断和int 3的中断效果是一样的,这里采用的是平时使用较少的into溢出中断。

#pragma data_seg(".VehInto")
DWORD VehintoAddr = 0;
#pragma data_seg()
#pragma comment(linker, "/section:.VehInto,RWS")
LONG NTAPI VehIntoExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo)
{// 设置新的eip 让程序调转到safe执行ExceptionInfo->ContextRecord->Eip = VehintoAddr;return EXCEPTION_CONTINUE_EXECUTION;
}
void IsVehIntoBreak()
{PVOID VEHandle = ::AddVectoredExceptionHandler(1, VehIntoExceptionFilter);_asm{// 存放异常处理之后的偏移地址mov VehintoAddr, offset Intosafe;mov ecx, 1;}
here:_asm{/*如果存在OD调试器,这里会一直循环下去。*/rol ecx, 1;  //不停的循环左移,直至产生溢出,OF位为1into;        //溢出中断 ,会调用异常处理jmp here;}
Intosafe:if (VEHandle != NULL){RemoveVectoredExceptionHandler(VEHandle);}
}
void CAntiDebugDlg::OnBnClickedButton15()
{// TODO: 在此添加控件通知处理程序代码IsVehIntoBreak();
}

12 . int 2d

/************************************************************************/
/* INT 2D                                                              */
/************************************************************************/
BOOL IsInt2d()
{__try{__asm{int 2dh;inc eax;//any opcode of singlebyte.如果开启VT会崩溃//;or u can put some junkcode,"0xc8"..."0xc2"..."0xe8"..."0xe9"}return TRUE;}__except(EXCEPTION_EXECUTE_HANDLER){return FALSE;}
}
void CAntiDebugDlg::OnBnClickedButton21()
{// TODO: 在此添加控件通知处理程序代码if (IsInt2d()){AfxMessageBox(L"检测到调试器");}else{AfxMessageBox(L"没有检测到调试器");}
}

13. 检验内存校验和

调试器(OD)在设置断点会改变内存属性,改写为0xCC,我们需要检验自身的某一个段内存的校验和就可以判断是否有调试器的存在

/************************************************************************/
/* CheckSum                                                             */
/************************************************************************/
BOOL CheckSum()
{BOOL bFoundOD;bFoundOD = FALSE;DWORD CHECK_SUM = 5555; //正确校验值DWORD dwAddr;dwAddr = (DWORD)CheckSum;__asm{; 检测代码开始mov     esi, dwAddr;mov     ecx, 100;xor     eax, eax;
checksum_loop:movzx     ebx, byte ptr [esi];add     eax, ebx;rol     eax, 1;inc     esi;loop     checksum_loop;cmp     eax, CHECK_SUM;jz      ODNotFound;mov     bFoundOD, 1;
ODNotFound:}return bFoundOD;
}
void CAntiDebugDlg::OnBnClickedButton27()
{// TODO: 在此添加控件通知处理程序代码if (CheckSum()){AfxMessageBox(L"检测到调试器");}else{AfxMessageBox(L"没有检测到调试器");}
}

14. 保护页异常

当执行一个属性为PAGE_GUARD的页面时,触发EXCEPTION_GUARD_PAGE的异常,如果存在调试器一般都是由调试器处理了。

/************************************************************************/
/* “保护页异常”                                                         */
/************************************************************************/
//当应用程序尝试执行保护页内的代码时,将会产生一个EXCEPTION_GUARD_PAGE(0x80000001)异常BOOL IsGuardPages()
{SYSTEM_INFO sSysInfo;DWORD dwPageSize = 0;DWORD OldProtect = 0;GetSystemInfo(&sSysInfo);dwPageSize = sSysInfo.dwPageSize;LPVOID lpvBase = VirtualAlloc(NULL, dwPageSize, MEM_COMMIT, PAGE_READWRITE);if (lpvBase == NULL){return FALSE;}PBYTE lptmpB = (PBYTE)lpvBase;*lptmpB = 0xc3; //retnVirtualProtect(lpvBase, dwPageSize, PAGE_EXECUTE_READ | PAGE_GUARD, &OldProtect);__try{__asm  call dword ptr[lpvBase];VirtualFree(lpvBase, 0, MEM_RELEASE);return TRUE;}__except(EXCEPTION_EXECUTE_HANDLER){VirtualFree(lpvBase, 0, MEM_RELEASE);return FALSE;}
}void CAntiDebugDlg::OnBnClickedButton25()
{// TODO: 在此添加控件通知处理程序代码if (IsGuardPages()){AfxMessageBox(L"检测到调试器");}else{AfxMessageBox(L"没有检测到调试器");}
}

14. 还有就是关于调试对象的检测

这里就牵扯到内核层的问题,一些基础内容就不进行赘述了。如果往深了研究可以学习系统的内核调试引擎,折腾TX的游戏TP反双机调试。这里只给出一些在应用层利用的比较简单的检测方法。这里就牵扯到内核层的问题,一些基础内容就不进行赘述了。如果往深了研究可以学习系统的内核调试引擎,折腾TX的游戏TP反双机调试。这里只给出一些在应用层利用的比较简单的检测方法。

检测调试对象DebugObject

/************************************************************************/
/* ZwQueryObject                                                        */
/************************************************************************/#ifndef STATUS_INFO_LENGTH_MISMATCH
#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)
#endif
void CAntiDebugDlg::OnBnClickedButton24()
{POBJECT_TYPES_INFORMATION pTypesInfo = NULL;ULONG dwSize = 0;PFNZwQueryObject pfunc_ZwQueryObject;HMODULE hModule = LoadLibrary(L"ntdll.dll");pfunc_ZwQueryObject = (PFNZwQueryObject)GetProcAddress(hModule, "ZwQueryObject");if (pfunc_ZwQueryObject){NTSTATUS Status = pfunc_ZwQueryObject(NULL,ObjectAllTypesInformation,NULL,0,&dwSize);if (Status == STATUS_INFO_LENGTH_MISMATCH){pTypesInfo = (POBJECT_TYPES_INFORMATION)VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);if (pTypesInfo == NULL) return;Status = pfunc_ZwQueryObject(NULL,ObjectAllTypesInformation,pTypesInfo,dwSize,&dwSize);if (!NT_SUCCESS(Status)){AfxMessageBox(L"查询错误");VirtualFree (pTypesInfo, 0, MEM_RELEASE);return;}for (UINT i = 0; i < pTypesInfo->NumberOfTypes; i++){if (pTypesInfo->TypeInformation[i].TypeName.Buffer != NULL){if (_wcsicmp(pTypesInfo->TypeInformation[i].TypeName.Buffer, L"DebugObject") == 0){AfxMessageBox(L"发现OD");VirtualFree (pTypesInfo, 0, MEM_RELEASE);return;}}}AfxMessageBox(L"没有OD!");VirtualFree (pTypesInfo, 0, MEM_RELEASE);}}
}

DebugObjectHandle

/************************************************************************/
/* ProcessDebugObjectHandle                                             */
/************************************************************************/
void CAntiDebugDlg::OnBnClickedButton22()
{// TODO: 在此添加控件通知处理程序代码HANDLE hProcess = NULL;DWORD dwResult;PFNZwQueryInformationProcess pfunc_ZwQueryInformationProcess;HMODULE hModule = LoadLibrary(L"ntdll.dll");pfunc_ZwQueryInformationProcess = (PFNZwQueryInformationProcess)GetProcAddress(hModule, "ZwQueryInformationProcess");pfunc_ZwQueryInformationProcess(GetCurrentProcess(),ProcessDebugObjectHandle,&dwResult,4,NULL);if (dwResult != 0){AfxMessageBox(L"检测到调试器");}else{AfxMessageBox(L"没有检测到调试器");}
}

一篇关于Anti不错的文章,不过是英文的,可以参考:anti-unpackers.pdf

http://www.openrce.org/reference_library/anti_reversing_view/34/INT 2D Debugger Detection/

原文作者:_懒人
原文连接:https://www.cnblogs.com/lanrenxinxin/p/5193920.html

Windows 下常见的反调试方法相关推荐

  1. android的反调试方法,Android平台融合多特征的APP反调试方法与流程

    本发明涉及Android平台融合多特征的APP反调试方法,属于计算机与信息科学技术领域. 背景技术: 应用程序本身并不具备反调试的功能,但是动态调试是动态分析应用逻辑.动态脱壳等攻击方式所采取的必要手 ...

  2. c语言程序中的错误可分为,C语言程序常见错误与调试方法(1)

    <C语言程序常见错误与调试方法(1)>由会员分享,可在线阅读,更多相关<C语言程序常见错误与调试方法(1)(17页珍藏版)>请在人人文库网上搜索. 1.C语言程序常见错误与调试 ...

  3. Linux下常见文件解压方法及命令

    Linux下常见文件解压方法及命令时间:2007-01-08 18:34来源:CSDN作者:bitsCN编辑字体:[大 中 小]1.以.a为扩展名的文件: #tar xv file.a 2.以.z为扩 ...

  4. cygwin学习linux命令,cygwin 在windows下使用linux命令的方法

    cygwin 在windows下使用linux命令的方法以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 但是cygwin ...

  5. iis怎么更换php版本,Windows 下PHP+IIS的安装方法(PHP版本为5.0)

    Windows 下PHP+IIS的安装方法(PHP版本为5.0) 最近需要使用下PHP相关的东西,查找了一些资料,现将PHP配置方法记录一下,以免以后忘记,呵呵,初学者,各位同学不要拍砖,开始正题,主 ...

  6. [转]cscope在windows下使用mingw编译的方法

    cscope在windows下使用mingw编译的方法      http://blog.csdn.net/mslk/archive/2007/05/06/1598513.aspx cscope在wi ...

  7. windows 下的CACTI的安装方法

    windows 下的CACTI的安装方法 记得第一次工作的时候,主管非得让我学在windows 下的CACTI的安装,把我急的,明明是Linux下的东东,硬让我在windows下面装,不过有不敢不听话 ...

  8. 5.7.24mysql 配置安卓,安卓按键精灵连接MySQL全面解析Windows下安装 mysql5.7的方法

    关于在windows下安装mysql 5.7 •要注意的新坑: 5.7版本安装后ROOT账号是有默认的密码的,这个密码在windows下可以在mysql.ini配置文件指定的data文件夹下面,那个为 ...

  9. Windows下opencc安装及使用方法

    Windows下opencc安装及使用方法 安装方法 1.获取opencc安装包 获取链接https://github.com/BYVoid/OpenCC/wiki/Download 2.选择适合自己 ...

最新文章

  1. android消息池,回转寿司你一定吃过!——Android消息机制(构造)
  2. 个人博客 SEO 优化(2):站内优化
  3. 打工人一次性考过高项的备考指南(52.50.50)
  4. opencv进阶学习笔记3:像素运算和图像亮度对比度调节
  5. web.xml中相关标签的加载顺序
  6. codeblock在linux中安装 出错
  7. python getopt.getopt_python 参数格式化getopt
  8. SetProcessWorkingSetSize减少内存占用
  9. python的pass在函数中的作用_Pass Share:Python / Julia 中函数变量的传递机制
  10. 算法同学从学校到实习,需要改变什么
  11. 【收藏】这些Python代码技巧,你肯定还不知道
  12. php用redis保存session
  13. 一张表实现固定表头和锁定列
  14. 计算机快捷键换行,excel换行快捷键 excel中自动换行的快捷键是什么
  15. SQL语句----CASE WHEN 的用法简介
  16. php相亲段子,个个都是老司机!NPC段子手们经典语录
  17. mysql事物sql语句死锁,定时任务启动失败Lock wait timeout exceeded;try restarting transaction
  18. 2016年的不正式总结
  19. 天才与成功—华人教育VS老美教育
  20. 阿里云不限速网盘,开始内测

热门文章

  1. 输电线路杆塔倾斜在线监测系统
  2. 网络安全培训课程自学
  3. 五分钟教你学会FineReport销售财务报表制作
  4. 《PostgreSQL修炼之道-从小工到专家》读书笔记
  5. Win端Unity 打包XCode项目导入虚拟机Mac系统使用XCode编译出现Unity-iPhone.xcodeproj cannot be opened
  6. Tomcat启动闪退解决方法
  7. SDL Trados 2019 和 SDL Trados 2021 二零二一五月更新
  8. Ajax基础知识 · 上
  9. 可视化图表组件体系的构建(内附全套开源文件)
  10. Confluence 6 自定义空间布局