【游戏逆向】常见锁定目标进程的方法分享

这篇具有很好参考价值的文章主要介绍了【游戏逆向】常见锁定目标进程的方法分享。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

当我们分析完游戏逻辑,收集了足够的游戏数据之后就可以动手开发一款专属于自己的辅助工具。而开发辅助的第一步就是先找到游戏进程,锁定游戏进程之后接下来才能在考虑辅助功能的实现是选择改数据、改代码还是CALL函数。锁定目标进程从实现上来讲可以分为三类:1、根据进程名或进程路径锁定目标进程;2、根据窗口名锁定目标进程;3、无脑全系统注入所有进程,在进程内在判断是否为目标进程。

所谓根据进程名锁定目标进程说的直白一些就是先枚举系统进程得到当前系统中运行的所有进程信息,然后对比进程名称或者进程路径来判断是不是目标进程。所以整个过程分为二步:1、枚举系统进程;2、根据进程名称或者进程路径信息判断是否为目标进程。这二个过程都有好几种实现方式,可以任意组合挑选其中一种组合即可达到目的。

在枚举系统进程的实现方式方面最主要有以下几种方式:1、使用Psapi 提供的API EnumProcesses;2、使用TlHelp32 提供的API Process32First&Process32Next;3、使用native API NtQuerySystemInformation。4、使用windows终端服务函数WTSEnumerateProcessesA。其中前2种方式是微软推荐的方式,随着操作系统不断更新这些API接口一般不会改变。而第三种则是native API,针对native API微软则不直接对外提供接口也不保证所有操作系统版本都会提供类似接口。在详细介绍前先针对重点函数使用进行介绍。

一、基于PSAPI 实现进程枚举查找目标进程

基于PSAPI实现进程查找主要是用EnumProcess来获取当前全系统的进程ID数组,然后通过进程ID或者进程路径或者进程名称信息,在通过进程路径或者名称信息与指定的目标进程的相关信息对比从而锁定目标进程。

关键函数介绍:

BOOL WINAPI EnumProcesses(

__out DWORD* pProcessIds,

__in DWORD cb,

__out DWORD* pBytesReturned

);

EnumProcesses用来一次性获取当前正在运行的进程ID数组。参数pProcessIds 是一个DWORD数组指针,指向一个用来存放进程ID的数据。cb用来告知操作系统前面传入的pProcessIds 进程ID数组buffer的内存大小。pBytesReturned用来返回存放进程数组需要的实际buffer大小。如果cb的值不足以存放所有进程ID信息则函数范围FALSE,然后实际需要内存通过pBytesReturned告知调用者。

HANDLE WINAPI OpenProcess(

__in DWORD dwDesiredAccess,

__in BOOL bInheritHandle,

__in DWORD dwProcessId

);

OpenProcess函数根据进程ID获取进程句柄。进程句柄是操作系统分配给进程对象的一个身份标识,是对进程进行操作的唯一方式,比如读写进程内存,获取进程信息等。dwDesiredAccess用来设定希望获取目标进程的哪些权限,这样返回的句柄信息就具有哪些操作权限,如果不清楚需要填写什么权限合适则可以申请所有权限PROCESS_ALL_ACCESS。bInheritHandle用来标识该句柄是否希望被子进程继承,不过不考虑子进程的继承权限则直接赋值为FALSE。dwProcessId则用来告知代打开进程的进程ID。

DWORD WINAPI GetProcessImageFileName(

__in HANDLE hProcess,

__out LPTSTR lpImageFileName,

__in DWORD nSize

);

GetProcessImageFileName函数用来获取hProcess进程的完整路径信息,存放在lpImageFileName指向的buffer中,nSize则是表明lpImageFileName的buffer大小。该函数在vista及以后的操作系统中已提供,XP系统及以前的系统则不支持该函数的调用。如果是需要在xp及以前的操作系统上使用则可用GetModuleFileNameEx函数代替。

DWORD WINAPI GetModuleFileNameEx(

__in HANDLE hProcess,

__in HMODULE hModule,

__out LPTSTR lpFilename,

__in DWORD nSize

);

GetModuleFileNameEx函数是用来获取指hProcess程hModule模块的一个完整路径,获取的路径放在lpFilename中,nSize表明lpFilename的buffer大小。如果hModule为NULL,则函数返回的是进程主模块的完整路径,这时候GetModuleFileNameEx函数和GetProcessImageFileName的作用完全一样了。

DWORD WINAPI GetModuleBaseName(

__in HANDLE hProcess,

__in HMODULE hModule,

__out LPTSTR lpBaseName,

__in DWORD nSize

);

GetModuleBaseName函数用来获取进程的基础名称,也就是短名称。其参数个数和用法基本和GetModuleFileNameEx一样这里不再赘述。

BOOL WINAPI CloseHandle(

__in HANDLE hObject

);

CloseHandle函数用来释放前面分配的各种句柄资源。一般我们使用api之前先查看MSDN里对api的描述。MSDN里一般会包含一下几项:Parameters\Return Value\Remarks\Example Code。以OpenProcess为例,在Remarks项里有这么一句话:When you are finished with the handle, be sure to close it using the CloseHandle function.这句话的意思就是说当不再使用该进程句柄时需要用CloseHandle来关闭该句柄。

相关源码分享:

//函数作用通过3中方式获取进程路径信息

VOID PrintProcessNameAndID(DWORD processID)

{

char szProcessName[1024] = { 0 };

char szOutputText[1024] = { 0 };

// Get a handle to the process.

HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,

FALSE, processID);

if (hProcess == NULL)

{

wsprintfA(szOutputText, “open process Id %d error, error id:%d”, processID, GetLastError());

OutputDebugStringA(szOutputText);

return;// open process error

}文章来源地址https://www.toymoban.com/news/detail-769750.html

// Get the process name.

GetProcessImageFileName(hProcess, szProcessName, 1024);

wsprintfA(szOutputText, “get path by GetProcessImageFileName %s”, szProcessName);

OutputDebugStringA(szOutputText);

GetModuleFileNameEx(hProcess, NULL, szProcessName, 1024);

wsprintfA(szOutputText, “get path by GetModuleFileNameEx %s”, szProcessName);

OutputDebugStringA(szOutputText);

GetModuleBaseName(hProcess, NULL, szProcessName, 1024);

wsprintfA(szOutputText, “get path by GetModuleBaseName %s”, szProcessName);

OutputDebugStringA(szOutputText);

CloseHandle(hProcess);

}

//函数作用 通过EnumProcess方式查找进程为szTargetProcess的进程

DWORD FindProcessByEnumProcess(char *szTargetProcess)

{

DWORD dwTargetProcessId = 0;

DWORD pdwProcesses[1024] = { 0 };

DWORD dwNeeded = 0;

if (!EnumProcesses(pdwProcesses, sizeof(pdwProcesses), &dwNeeded))

return dwTargetProcessId;//call EnumProcesses error

DWORD dwProcessNumber = dwNeeded / sizeof(DWORD);

for (unsigned int i = 0; i < dwProcessNumber; i++)

{

if (pdwProcesses[i] != 0)

{

HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,

FALSE, pdwProcesses[i]);

if (hProcess != NULL)

{

char szProcessName[1024] = { 0 };

GetModuleFileNameEx(hProcess, NULL, szProcessName, 1024);

_strlwr_s(szProcessName, sizeof(szProcessName));

if (strstr(szProcessName, szTargetProcess) != NULL)

{

dwTargetProcessId = pdwProcesses[i];

}

CloseHandle(hProcess);

hProcess = NULL;

}

}

}

return dwTargetProcessId;

}

二、使用Process32First&Process32Next枚举进程锁定目标进程

进程快照是在tlhelp32.h文件里声明的一系列api,主要是通过CreateToolhelp32Snapshot创建一个进程快照,然后通过Process32First和Process32Next配合遍历当前系统进程。进程信息保存在一个PROCESSENTRY32结构体中。PROCESSENTRY32结构体定义如下:

typedef struct tagPROCESSENTRY32 {

DWORD dwSize;

DWORD cntUsage;

DWORD th32ProcessID;

DWORD th32DefaultHeapID;

DWORD th32ModuleID;

DWORD cntThreads;

DWORD th32ParentProcessID;

LONG pcPriClassBase;

DWORD dwFlags;

TCHAR szExeFile[MAX_PATH];

DWORD th32MemoryBase;

DWORD th32AccessKey;

} PROCESSENTRY32;

th32ProcessID为进程ID信息,szExeFile为进程路径信息。与PSAPI系列API相比快照方式枚举的进程直接就能获取路径信息所以不需要再次调用其它API获取进程路径信息。需要注意的是在使用完快照句柄之后需要调用CloseToolhelp32Snapshot来关闭快照句柄而不是CloseHandle关闭快照句柄。

关键函数介绍:

HANDLE WINAPI CreateToolhelp32Snapshot(

DWORD dwFlags,

DWORD th32ProcessID

);

CreateToolhelp32Snapshot函数用来创建一个快照,dwFlags用来指明快照类型。当dwFlags的值等于TH32CS_SNAPPROCESS时就是用来创建一份进程快照,th32ProcessID的值在进程快照中会被忽略。

BOOL WINAPI Process32First(

HANDLE hSnapshot,

LPPROCESSENTRY32 lppe

);

BOOL WINAPI Process32Next(

HANDLE hSnapshot,

LPPROCESSENTRY32 lppe

);

Process32First和Process32Next配合使用。hSnapshot传入进程快照句柄,lppe里则返回进程的相关信息。快照里的第一个进程信息用Process32First获取,接下来的进程信息则用Process32Next获取。当快照遍历完成之后Process32Next函数返回FALSE。

相关源码分享:

//函数作用 通过快照方式查找进程为szTargetProcess的进程

DWORD FindProcessBySnapshot(char *szTargetProcess)

{

char szOutputText[1024] = { 0 };

DWORD dwTargetProcessId = 0;

HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

if (INVALID_HANDLE_VALUE == hProcessSnapshot)

{

wsprintfA(szOutputText, “call CreateToolhelp32Snapshot error, error id:%d”, GetLastError());

OutputDebugStringA(szOutputText);

return dwTargetProcessId;

}

PROCESSENTRY32 stProcessEntry = { 0 };

stProcessEntry.dwSize = sizeof(stProcessEntry);

if (Process32First(hProcessSnapshot, &stProcessEntry) == FALSE)

{

wsprintfA(szOutputText, “call Process32First error, error id:%d”, GetLastError());

OutputDebugStringA(szOutputText);

CloseHandle(hProcessSnapshot);

return dwTargetProcessId;

}

do

{

wsprintfA(szOutputText, “process id:%d %s”, stProcessEntry.th32ProcessID, stProcessEntry.szExeFile);

OutputDebugStringA(szOutputText);

if (_stricmp(stProcessEntry.szExeFile, szTargetProcess) == 0)

{

dwTargetProcessId = stProcessEntry.th32ProcessID;

}

memset(&stProcessEntry, 0, sizeof(stProcessEntry));

stProcessEntry.dwSize = sizeof(stProcessEntry);

} while (Process32Next(hProcessSnapshot, &stProcessEntry));

CloseHandle(hProcessSnapshot);

return dwTargetProcessId;

}

三、使用NtQuerySystemInformation枚举进程锁定目标进程

NtQuerySystemInformation(ZwQuerySystemInformation)函数主要功能是获取或者设置系统信息,声明如下:

typedef NTSTATUS (__stdcall *NTQUERYSYSTEMINFORMATION)
(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);

从声明中可以看出,参数SystemInformationClass是一个类型信息,可以对50多种系统信息进行查看或者设置。参数SystemInformation为接收信息的缓冲区。可以通过设置SystemInformationClass值为NT_PROCESSTHREAD_INFO来获取进程信息,获取到的进程结构体如下:

typedef struct _SYSTEM_PROCESSES

{

ULONG NextEntryDelta;

ULONG ThreadCount;

ULONG Reserved1[6];

LARGE_INTEGER CreateTime;

LARGE_INTEGER UserTime;

LARGE_INTEGER KernelTime;

UNICODE_STRING ProcessName;

KPRIORITY BasePriority;

ULONG ProcessId;

ULONG InheritedFromProcessId;

ULONG HandleCount;

ULONG Reserved2[2];

VM_COUNTERS VmCounters;

IO_COUNTERS IoCounters;

SYSTEM_THREADS Threads[1];

}SYSTEM_PROCESSES,*PSYSTEM_PROCESSES;

这里需要注意获取到的进程名为UNICODE_STRING,其结构体定义如下:

typedef struct _LSA_UNICODE_STRING

{

USHORT Length;

USHORT MaximumLength;

PWSTR Buffer;

}LSA_UNICODE_STRING,*PLSA_UNICODE_STRING;

typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING;

需要将其转换为ASCII字符串,使用WideCharToMultiByte函数。

相关源码分享:

//函数作用 通过NtQuerySytemInfo方法查找进程名称为szTargetProcess的进程

int FindProcessByNtQuery(char *szTargetProcess)

{

HINSTANCE hModule = NULL;

DWORD dwTotalProcess = 0;

DWORD dwReturnLength = 0;

NTSTATUS Status = 0;

PSYSTEM_PROCESSES pstSystemProc = NULL;

pNtQuerySystemInformation pfNtQuerySystemInformation = NULL;

DWORD dwNumberBytes = MAX_INFO_BUF_LEN;

hModule = GetModuleHandleA(“ntdll.dll”);

if (NULL == hModule)

{

return -1;

}

pfNtQuerySystemInformation = (pNtQuerySystemInformation)GetProcAddress(hModule, (LPCSTR)“ZwQuerySystemInformation”);

if (NULL == pfNtQuerySystemInformation)

{

return -1;

}

void *lpSystemInfo = (LPVOID)malloc(dwNumberBytes);

if (!lpSystemInfo)

{

return -1;

}

Status = pfNtQuerySystemInformation(NT_PROCESSTHREAD_INFO, lpSystemInfo, dwNumberBytes, &dwReturnLength);

if (Status == STATUS_INFO_LENGTH_MISMATCH)

{

printf(“STATUS_INFO_LENGTH_MISMATCH\n”);

return -1;

}

else if (Status != STATUS_SUCCESS)

{

printf(“NtQuerySystemInformation Error: %d\n”, GetLastError());

return -1;

}

pstSystemProc = (PSYSTEM_PROCESSES)lpSystemInfo;

while (pstSystemProc->NextEntryDelta != 0)

{

char pszProcessName = (char)malloc(pstSystemProc->ProcessName.Length + 1);

if (!pszProcessName)

{

return -1;

}

WideCharToMultiByte(CP_ACP,

0,

pstSystemProc->ProcessName.Buffer,

pstSystemProc->ProcessName.Length + 1,

pszProcessName,

pstSystemProc->ProcessName.Length + 1,

NULL,

NULL);

if (!strcmp(pszProcessName, szTargetProcess))

{

return pstSystemProc->ProcessId;

}

pstSystemProc = (PSYSTEM_PROCESSES)((char *)pstSystemProc + pstSystemProc->NextEntryDelta);

}

return -1;

}

四、使用windows终端服务函数WTSEnumerateProcessesA枚举进程锁定目标进程

Windows终端服务相关的函数都是以WTS开头。WTSOpenServer函数可以打开一台远程机器的访问链接,WTSEnumerateProcesses函数可以枚举指定Server上的所有进程,函数声明如下:

typedef BOOL (_stdcall WTSENUMERATEPROCESSES)(
HANDLE hServer, //WTSOpenServer返回的句柄
DWORD Reserved, //保留值, 0
DWORD Version, //指定枚举要求的版本, 必须为1
PWTS_PROCESS_INFO
ppProcessInfo, //这个参数是关键,存放我们要的进程名和进程id
DWORD* pCount //用来存放ppProcessInfo里WTS_PROCESS_INFO结构的数量指针);

当函数第一个参数hServer值指定为WTS_CURRENT_SERVER_HANDLE时,代表枚举本地机器上的进程。

相关源码分享:

int FindProcessByWtsEnumerate(char *szTargetProcess)

{

HINSTANCE hWtsApi32 = LoadLibraryA(“wtsapi32.dll”);

if (NULL == hWtsApi32)

{

return -1;

}

WTSENUMERATEPROCESSES pWtsEnumerateProcesses = (WTSENUMERATEPROCESSES)GetProcAddress(hWtsApi32, “WTSEnumerateProcessesA”);

if (NULL == pWtsEnumerateProcesses)

{

return -1;

}

PWTS_PROCESS_INFOA pWtspi = {0};

DWORD dwCount = 0;

if (!pWtsEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pWtspi, &dwCount))

{

return -1;

}

for (int i = 0; i < dwCount; i++)

{

if (!strcmp(pWtspi[i].pProcessName, szTargetProcess))

{

return pWtspi[i].ProcessId;

}

}

return -1;

}

五、使用FindWindow\EnumWindow查找目标进程

操作系统提供了一个api GetWindowThreadProcessId,使用该api可以获得窗口所在线程与所在进程信息,所以如果目标进程有窗口那么就可以使用窗口的方式来查找目标进程。获得窗口句柄的方式一般用FindWindow和EnumWindows。

关键函数介绍:

HWND FindWindow(

LPCTSTR lpClassName,

LPCTSTR lpWindowName

);

FindWindow函数用来查找一个类名等于lpClassName,窗口名等于lpWindowName的特定窗口。如果类名和窗口名等于NULL则该项过滤条件忽略,类名和窗口名不能同时等于NULL,也就是说至少需要一个参数有效。如果找到复合条件的窗口则返回窗口句柄,否则返回NULL。

BOOL EnumWindows(

WNDENUMPROC lpEnumFunc,

LPARAM lParam

);

EnumWindows函数用来枚举当前系统内的所有窗口,lParam 是一个开发者自定义的数值,lpEnumFunc则是一个找到窗口的回调函数。当系统发现一个窗口则调用一次回调函数lpEnumFunc,参数为找到的窗口句柄和调用EnumWindows时传入的lParam值。回调函数原型如下:

BOOL CALLBACK EnumWindowsProc(

HWND hwnd,

LPARAM lParam

);

EnumWindows函数只能用来找顶层窗口,如果要找指窗口则需要调用函数EnumChildWindows。

BOOL EnumChildWindows(

HWND hWndParent,

WNDENUMPROC lpEnumFunc,

LPARAM lParam

);

EnumChildWindows函数与EnumWindows参数相似,作用也相似。参数上多了一个hWndParent,用来表明要找的窗口为hWndParent窗口的子窗口。如果用EnumWindows和EnumChildWindows函数查找窗口,则需要在lpEnumFunc回调函数内调用GetWindowText来获取窗口名,调用GetClassName来获取窗口的类名。然后在通过窗口名和类名对比来确认目标窗口。

一般窗口名在窗口上可以直接看到,但是类名是隐藏的,需要用一些特定工具才可以看到,比如Spy ++等。

DWORD GetWindowThreadProcessId(

HWND hWnd,

LPDWORD lpdwProcessId

);

GetWindowThreadProcessId函数用来获得指定窗口hWnd所在的进程和线程信息,线程ID用返回值来传递,而进程ID信息则通过lpdwProcessId 来传递。

关键代码分享:

//函数作用 通过FindWindows方式查找窗口szWindowTitle所在的进程

DWORD FindProcessByFindWindow(char *szWindowTitle)

{

DWORD dwTargetProcessId = 0;

HWND hTargetWindow = FindWindow(NULL, szWindowTitle);

if (hTargetWindow == NULL)

{

return dwTargetProcessId;

}

GetWindowThreadProcessId(hTargetWindow, &dwTargetProcessId);

return dwTargetProcessId;

}

/**************************************************************/

typedef struct tagWINDOWPROCESSINFO32 {

DWORD dwWindowProcessId;

char szWindowTitle[256];

} WINDOWPROCESSINFO32;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)

{

WINDOWPROCESSINFO32 *pstWindowProcessInfo = (WINDOWPROCESSINFO32 *)lParam;

char szWindowText[1024] = { 0 };

GetWindowText(hwnd, szWindowText, 1024);

if (_stricmp(szWindowText, pstWindowProcessInfo->szWindowTitle) == 0)

{

DWORD dwProcessId = 0;

GetWindowThreadProcessId(hwnd, &dwProcessId);

pstWindowProcessInfo->dwWindowProcessId = dwProcessId;

return FALSE;

}

else

{

return TRUE;

}

}

//函数作用 通过EnumWindows方式查找窗口szWindowTitle所在的进程

DWORD FindProcessByEnumWindow(char *szWindowTitle)

{

WINDOWPROCESSINFO32 stWindowProcessInfo = { 0 };

strncpy_s(stWindowProcessInfo.szWindowTitle, szWindowTitle, sizeof(stWindowProcessInfo.szWindowTitle) - 1);

EnumWindows(EnumWindowsProc, (LPARAM)&stWindowProcessInfo);

return stWindowProcessInfo.dwWindowProcessId;

}

六、全系统注入模块后判断目标进程

在众多注入方式中,有一些注入方式在注入过程中是不知道所注入的目标进程的,只要复合条件的进程都会注入。比如采用钩子注入那么自要有消息队列的线程所在进程都会注入。这种情况下我们可以通过模块信息来判定是否是目标进程,如果是目标进程则执行相应操作(例如改游戏代码,CALL游戏函数等等)。关于注入方式我们在后面的章节在详细介绍,现在主要介绍集中简单的判定目标进程的3种方式。GetModuleFileName\GetModuleFileNameEx\GetModuleHandle。其中GetModuleFileName使用方式和GetModuleFileNameEx这个函数类似,使用说明在前面已经有介绍过这里不再重复,都是先过去当前进程EXE路径然后判断是否 为指定进程的EXE。

HMODULE GetModuleHandle(

LPCTSTR lpModuleName

);

GetModuleHandle函数则是用来获的名字为lpModuleName的模块的句柄。如果找到了复合条件的模块则返回模块句柄,没找到模块则返回NULL。

关键代码分享:

//以下函数作用都是用来判断当前进程是否是进程名为szTargetProcess的进程,如果是则返回真,否则返回假。

BOOL IsTargetProcessByGetModuleHandle(char *szTargetProcess)

{

BOOL bFindProcess = FALSE;

if (GetModuleHandle(szTargetProcess) != NULL)

bFindProcess = TRUE;

return bFindProcess;

}

BOOL IsTargetProcessByGetModuleFileName(char *szTargetProcess)

{

BOOL bFindProcess = FALSE;

char szProcessPath[1024] = { 0 };

GetModuleFileName(NULL, szProcessPath, 1024);

if (strstr(szProcessPath, szTargetProcess) != NULL)

bFindProcess = TRUE;

return bFindProcess;

}

BOOL IsTargetProcessByGetModuleFileNameEx(char *szTargetProcess)

{

BOOL bFindProcess = FALSE;

char szProcessPath[1024] = { 0 };

GetModuleFileNameEx(GetCurrentProcess(), NULL, szProcessPath, 1024);

if (strstr(szProcessPath, szTargetProcess) != NULL)

bFindProcess = TRUE;

return bFindProcess;

}

BOOL IsTargetProcessByGetModuleBaseName(char *szTargetProcess)

{

BOOL bFindProcess = FALSE;

char szProcessPath[1024] = { 0 };

GetModuleBaseName(GetCurrentProcess(), NULL, szProcessPath, 1024);

if (strstr(szProcessPath, szTargetProcess) != NULL)

bFindProcess = TRUE;

return bFindProcess;

}

到了这里,关于【游戏逆向】常见锁定目标进程的方法分享的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 系统登录失败次数超过限定次数,则根据IP或用户名锁定,需要过了锁定时间才可以继续登录

    之前做的项目都有用户名锁定机制,即:用户名失败次数超过多少次,就锁定这个用户不可以再登录,需要等过了锁定时间才可以继续登录。 然后最近的一个项目中,有个漏洞整改措施中,提到了这个锁定机制不能只根据用户名锁定,还要根据IP锁定。 根据用户名锁定的前提

    2024年02月12日
    浏览(46)
  • 传奇引擎知识分享 传奇HeroM2游戏引擎介绍与常见问题解答

    HeroM2游戏引擎是一款有一定历史的老引擎,的来更新为:新HeroM2引擎。 HeroM2引擎是目前市面上对游戏外挂及加速最有效的游戏引擎,在针对外挂方面HEROM2做了大量工作,同时HeroM2引擎针对CC攻击有一定防护作用,这也是这款引擎的特色之处。因为有一定的开发历史,所以Her

    2024年04月25日
    浏览(45)
  • 【技术分享】SSH 爆破锁定

    实现原理 通过 PAM 模块的\\\"pam_faillock\\\" 实现; 作用是防止SSH被爆破登录,当密码输入错误次数超过阈值时,账户会被锁定,在锁定期间,即使输入正确的密码也会被拒绝登录 注意,该方式不仅作用于SSH,还会作用于控制台登录 操作步骤 1.编辑 /etc/pam.d/password-auth 和 /etc/pam.d/system-auth 文件

    2024年02月15日
    浏览(42)
  • 电源模块常见温升测试方法分享 -纳米软件

    温升测试是电器产品安规测试项目之一,是为了检测电器产品及部件的温度变化情况,判断是否符合要求。在设备运行过程中会释放一定的热量,如果内部温度过高会影响产品的性能和稳定性,导致绝缘性能下降,因此温升测试是确保产品稳定运行的重要步骤。那么如何进行

    2024年01月24日
    浏览(46)
  • 分享几个Ecshop中二次开发的常见方法

    收货人信息的省市区设成非必选项 一般面向国外用户的ECSHOP商城,可能会有这方面的需求:【将Ecshop中收货人信息的省市区设成非必选项】,其实也就是只留一个“请选择国家”的下拉选择框。 修改相关JS文件 打开 /js/shopping_flow.js 文件,将下面JS代码删除掉 JavaScript Code 复制

    2023年04月16日
    浏览(34)
  • [架构之路-245]:目标系统 - 设计方法 - 软件工程 - 软件开发模型(流程):瀑布模型、V模型、原型模型、增量模型、迭代模型、螺旋模型、敏捷模型、DevOps、AI辅助、逆向工程、净室工程

    目录 前言: 一、软件开发模型概览 1.1 概述 1.2 软件开发方法与软件开发模型的区别 二、软件开发模型详解 2.1 瀑布模型:串行线性开发 2.2 V模型:测试驱动开发(需求明确、提前测试、验证) 2.3 原型模型(Prototype Model):向用户提前展示 2.4 增量模型:按功能分块开发(

    2024年04月28日
    浏览(58)
  • Unity 之 转微信小游戏本地数据存储方法分享

    近期在将Unity转换为小游戏的时候发现在读写本地文件的时候,使用 Application.persistentDataPath 缓存路径来保存文件失败,原因是WebGL的平台限制。所以导致了原有读写本地文件的代码需要根据平台进行修改。 一种最简单的方式就是将原来存储到文件中的内容,在WebGL平台使用

    2024年02月05日
    浏览(61)
  • Unity 之 抖音小游戏本地数据最新存储方法分享

    抖音小游戏是一种基于抖音平台开发的小型游戏,与传统的 APP 不同,抖音小游戏运行在抖音客户端内部,可以通过抖音的分享、推荐等功能进行传播。在抖音小游戏开发过程中,文件存储系统是一个非常重要的组成部分,本文将详细介绍抖音小游戏文件存储系统的实现原理

    2024年02月11日
    浏览(54)
  • 游戏《泰坦陨落2》msvcr120.dll丢失的多种解决方法分享

    在Windows 11操作系统环境下,众多玩家在体验《泰坦陨落2》这款备受瞩目的射击游戏时,遭遇了一个令人困扰的技术问题:系统提示缺失msvcr120.dll文件。这一关键的动态链接库文件对于游戏的正常运行至关重要,它的缺失直接导致了《泰坦陨落2》无法启动或在运行过程中出现

    2024年01月19日
    浏览(55)
  • VMware虚拟机启动Ubuntu时报错:“另一个程序已锁定文件的一部分,进程无法访问”该怎样解决呢?

    宝子们有木有遇到这样的问题呀“另一个程序已锁定文件的一部分,进程无法访问”,跟着辣面子来解决这个问题吧 按照自己路径寻找 放心将它们删除 出现此文件是因为虚拟机在运行的时候,会锁定文件,防止被修改,如果系统突然崩溃、异常关机等,虚拟机尚未把已经锁

    2024年02月11日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包