欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[分享]发一份去年针对某游戏的R3特征封号的一个处理

[分享]发一份去年针对某游戏的R3特征封号的一个处理

简单来说就是处理ZwQueryVirtualMemory的,内存dll这种大家都懂的。代码丑...轻喷..

后来游戏增加了ShadowApi也一并处理了..

当时因为X3会检测syscall所以没有在入口直接写hook,能直接hook那里处理的也就不用写这么多了。

顺便问个事情,现在已经隐藏了进程的路径,xt里看进程也是伪造的进程的,但是查看模块的时候,还是能看到模块的路径,有什么方法可以连那里都抹掉吗?(R0处理)

void FuckSearchAPI()

{

	VMProtectBegin("SearchApi");

	DWORD dw_Sb = 0x30000;

	DWORD dw_ZwQSys = 0;

	DWORD dw_KernBase = 0;

	char ch_Checkzwqadd[20];

	int i_Check = 0;

	dw_Last4C += 0xFCC00;

	//1.搜索KernelBase中的zwq位置 2.在last4C中搜索

	//一切照旧

	dw_KernBase = (DWORD)GetModuleHandleA("KernelBase.dll");

	dw_ZwQSys = (DWORD)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwQueryVirtualMemory");

	unsigned char Uc_zwqSys[] = { 0xE0, 0xE0, 0xE0, 0xE0 };

	memcpy(Uc_zwqSys, &dw_ZwQSys, 4);

	dw_RighHookAdd = SUNDAY((unsigned char*)dw_KernBase, Uc_zwqSys, 4, 0x4000);

	_asm{

		mov eax, [dw_RighHookAdd]

		add eax,0x4

		mov eax, [eax]

		mov[dw_ZwQSys],eax

	}

	unsigned char Uc_zwqSys_last[] = { 0xE0, 0xE0, 0xE0, 0xE0 };

	memcpy(Uc_zwqSys_last, &dw_ZwQSys, 4);

	dw_RighHookAdd = SUNDAY((unsigned char*)dw_Last4C, Uc_zwqSys_last, 4, dw_Sb);

	if (dw_RighHookAdd == NULL)WritePrivateProfileStringA("c", "a", "1", "c:\\xxxx.ini");

	else WritePrivateProfileStringA("c", "a", "2", "c:\\xxxx.ini");

	dw_RighHookAdd -= 4;

	_asm{

		mov eax, [dw_RighHookAdd]

		mov ebx, [dw_ReallyZWQCheck]

		mov eax, [eax]

		mov eax, [eax]

		cmp eax,ebx

		je NotSome

		mov[i_Check],1

	NotSome:

	}

	if (i_Check == 1)WritePrivateProfileStringA("c", "a", "3", "c:\\xxxx.ini");

	VMProtectEnd();

}

void FuckFakeZw_F()

{

	VirtualProtect((LPVOID)dw_AnuFakeZwAdd, 10, 64, &dw_AnuOldPro);

}

void FuckZwHack()

{

	VMProtectBegin("fzwNl");

	int i = 0;

	if (dw_LastCheckbz == 1)i = 1;

	char ch_LastG[20];

	_ltoa(dw_LastCheck, ch_LastG, 16);

	if (i == 1)WritePrivateProfileStringA("c", "a", "3", "c:\\xxx.ini");

	else WritePrivateProfileStringA("c", "a", "4", "c:\\xxx.ini");

	VMProtectEnd();

}

void FuckFakeZw_NF()

{

	VirtualProtect((LPVOID)dw_AnuFakeZwAdd, 10, dw_AnuOldPro, &dw_AnuOldPro);

}

void _declspec(naked) FakeZwQuery_Ret()

{

	VMProtectBegin("FakeZwRet");

	__asm{

		push eax

		mov eax, [esp-0x8]

		mov dword ptr ds : [eax + 0x4], 0x0

		mov dword ptr ds : [eax + 0x8], 0x0

		mov dword ptr ds : [eax + 0xC], 0x328100

		mov dword ptr ds : [eax + 0x10], 0x10000

		mov dword ptr ds : [eax + 0x14], 0x1

		pop eax

		jmp[dw_CallZwAdd]                         //跳回调用地址

	}

	VMProtectEnd();

}

void _declspec(naked) FakeZwQuery_X32()

{

	VMProtectBegin("FakeX32");

	__asm{

		mov eax, [esp - 0xC]

		mov[dw_esp3], eax

		mov eax, [esp - 0x10]

		mov[dw_esp4], eax

		mov eax, [esp - 0x14]

		mov[dw_esp1], eax

		mov eax, [esp - 0x18]

		mov[dw_esp2], eax

		push eax

		push ebx

		pushfd

		cmp[dw_Last4Cbz],1

		je X64_PreCheck_1_2

		mov eax, [esp + 0x18]                        //BaseAdd

		mov ebx, [esp + 0x24]

		cmp eax, 0x1F0000                             //如果大于游戏基地址 就不做检查 因为封号检查是从0开始的

		jg X64_PreCheck_1_2

		mov eax, [esp+0x5C]

		cmp eax, 0xCDD000

		jl X64_PreCheck_1_2

		cmp eax, 0x70000000

		jg X64_PreCheck_1_2

		mov ebx, [eax]                             //把eax的值放进去

		cmp ebx, [dw_ReallyQuery]

		jne X64_PreCheck_1_2

		cmp eax, [dw_Last4C]

		mov [dw_Last4C], eax

		je SameLast_2

		mov [dw_Last4Cindex],0

		jmp X64_PreCheck_1_2

	SameLast_2:

		mov eax, [dw_Last4Cindex]

		inc eax

		mov [dw_Last4Cindex],eax

		cmp eax,2

		jg HackZwqbyGame_2

		jmp X64_PreCheck_1_2

	HackZwqbyGame_2:

		mov [dw_Last4Cbz],1

		pushad

		call FuckSearchAPI

		popad

	FuckTheFakeZwq_2:

		mov eax, [dw_RighHookAdd]

		mov ebx, [eax]

		mov[dw_AnuFakeZwAdd],eax

		mov eax, [ebx]

		push ecx

		mov ecx, [dw_AnuFakeZwKick]

		inc ecx

		mov [dw_AnuFakeZwKick],ecx

		pop ecx

		pushad

		call FuckFakeZw_F

		popad

		mov eax, [dw_AnuFakeZwAdd]

		mov ebx, [dw_ZwQadd]

		mov [eax],ebx

		pushad

		call FuckFakeZw_NF

		popad

		jmp X64_PreCheck_1_2

	X64_PreCheck_1_2:

		mov eax, [dw_RighHookAdd]

		cmp eax, 0

		je X64_PreCheck_1_ok_2

		mov eax, [eax]

		mov ebx, [dw_ZwQadd]

		cmp eax, ebx

		jne FuckTheFakeZwq_2

	X64_PreCheck_1_ok_2 :

		mov eax, [esp + 0x18]                        //BaseAdd

		mov ebx, [esp + 0x24]

		add eax, ebx

		cmp eax, [dw_MydllH_Beg]

		jl nothingFake_2

		sub eax, ebx

		cmp eax, [dw_MydllH_End]

		jg nothingFake_2                               

		mov eax, [esp + 0x10]                         

		mov [dw_CallZwAdd], eax                      //取出原调用地址并放入变量

		mov eax, FakeZwQuery_Ret                     //更改返回值

		mov[esp + 0x10], eax

	nothingFake_2 :

		popfd

		pop ebx

		pop eax

		mov[esp - 0x8], 1

		mov eax, [dw_esp3]

		mov[esp - 0xC], eax

		mov eax, [dw_esp4]  //这样子写 再加pushfd就ok了

		mov[esp - 0x10], eax   //尝试还原堆栈

		mov eax, [dw_esp1]

		mov[esp - 0x14], eax

		mov eax, [dw_esp2]

		mov[esp - 0x18], eax

		mov eax, [i_ZwQueryv]

		jmp [dw_A]

	}

	VMProtectEnd();

}

void _declspec(naked) FakeZwQuery_NoWin7x64()

{

	VMProtectBegin("FakeX64");

	__asm{

		mov eax, [esp - 0xC]

		mov[dw_esp3], eax

		mov eax, [esp - 0x10]

		mov[dw_esp4], eax

		mov eax, [esp-0x14]

		mov[dw_esp1],eax

		mov eax, [esp-0x18]

		mov[dw_esp2],eax

		push eax

		push ebx

		pushfd

		cmp [dw_Last4Cbz],1

		je X64_PreCheck_1_1

		mov eax, [esp + 0x18]                        //BaseAdd

		mov ebx, [esp + 0x24]

		cmp eax, 0x1F0000                             //如果大于游戏基地址 就不做检查 因为封号检查是从0开始的

		jg X64_PreCheck_1_1

		mov eax, [esp+0x5C]

		cmp eax, 0xCDD000

		jl X64_PreCheck_1_1

		cmp eax, 0x70000000

		jg X64_PreCheck_1_1

		mov ebx, [eax]                             //把eax的值放进去

		cmp ebx, [dw_ReallyQuery]

		jne X64_PreCheck_1_1

		cmp eax, [dw_Last4C]

		mov [dw_Last4C], eax

		je SameLast_1

		mov [dw_Last4Cindex],0

		jmp X64_PreCheck_1_1

	SameLast_1:

		mov eax, [dw_Last4Cindex]

		inc eax

		mov [dw_Last4Cindex],eax

		cmp eax,2

		jg HackZwqbyGame_1

		jmp X64_PreCheck_1_1

	HackZwqbyGame_1:

		mov [dw_Last4Cbz],1

		pushad

		call FuckSearchAPI

		popad

	FuckTheFakeZwq_1:

		mov eax, [dw_RighHookAdd]

		mov ebx, [eax]

		mov[dw_AnuFakeZwAdd],eax

		mov eax, [ebx]

		push ecx

		mov ecx, [dw_AnuFakeZwKick]

		inc ecx

		mov [dw_AnuFakeZwKick],ecx

		pop ecx

		pushad

		call FuckFakeZw_F

		popad

		mov eax, [dw_AnuFakeZwAdd]

		mov ebx, [dw_ZwQadd]

		mov [eax],ebx

		pushad

		call FuckFakeZw_NF

		popad

		jmp X64_PreCheck_1_1

	X64_PreCheck_1_1:

		mov eax, [dw_RighHookAdd]

		cmp eax, 0

		je X64_PreCheck_1_ok_1

		mov eax, [eax]

		mov ebx, [dw_ZwQadd]

		cmp eax, ebx

		jne FuckTheFakeZwq_1

	X64_PreCheck_1_ok_1:

		mov eax, [esp + 0x18]                        //BaseAdd

		mov ebx, [esp + 0x24]

		add eax, ebx

		cmp eax, [dw_MydllH_Beg]

		jl nothingFake_1

		sub eax, ebx

		cmp eax, [dw_MydllH_End]

		jg nothingFake_1                               

		mov eax, [esp + 0x10]                         

		mov [dw_CallZwAdd], eax                      //取出原调用地址并放入变量

		mov eax, FakeZwQuery_Ret                     //更改返回值

		mov[esp + 0x10], eax

	nothingFake_1 :

		popfd

		pop ebx

		pop eax

		mov[esp - 0x8], 1

		mov eax, [dw_esp3]

		mov[esp - 0xC], eax

		mov eax, [dw_esp4]  //这样子写 再加pushfd就ok了

		mov[esp - 0x10], eax   //尝试还原堆栈

		mov eax, [dw_esp1]

		mov[esp - 0x14], eax

		mov eax, [dw_esp2]

		mov[esp - 0x18], eax

		mov eax, [i_ZwQueryv]

		jmp [dw_A]

	}

	VMProtectEnd();

}

void _declspec(naked) FakeZw_Win7x64()

{

	VMProtectBegin("Win764zwq");

	__asm{

		    //在这里保存原来的堆栈

			mov eax, [esp - 0xC]

			mov[dw_esp3], eax

			mov eax, [esp - 0x10]

			mov[dw_esp4], eax

			mov eax, [esp-0x14]

			mov[dw_esp1],eax

			mov eax, [esp-0x18]

			mov[dw_esp2],eax

		    push eax

			push ebx

			push ecx

			pushfd

			cmp[dw_Last4Cbz],1

			je X64_PreCheck_1

			mov eax, [esp + 0x18]                          //BaseAdd

			mov ebx, [esp + 0x24]

			cmp eax, 0x1F0000                              //如果大于游戏基地址 就不做检查 因为封号检查是从0开始的

			jg X64_PreCheck_1

			mov eax, [esp+0x5C]

			cmp eax,0xCDD000

			jl X64_PreCheck_1

			cmp eax,0x70000000

			jg X64_PreCheck_1

			mov ebx, [eax]                             //把eax的值放进去

			cmp ebx, [dw_ReallyQuery]

			jne X64_PreCheck_1

			cmp eax, [dw_Last4C]

			mov [dw_Last4C], eax

			jmp SameLast

			mov [dw_Last4Cindex],0

			jmp X64_PreCheck_1

		SameLast:

			mov eax, [dw_Last4Cindex]

			inc eax

			mov [dw_Last4Cindex],eax

			cmp eax,0

			jg HackZwqbyGame                           //找到一次直接就动手 果断

			jmp X64_PreCheck_1

		HackZwqbyGame:

			mov [dw_Last4Cbz],1

			pushad

			call FuckSearchAPI

			popad

		FuckTheFakeZwq:

			mov eax, [dw_RighHookAdd]

			mov[dw_AnuFakeZwAdd],eax

			pushad

			call FuckFakeZw_F

			popad

			mov eax, [dw_AnuFakeZwAdd]

			mov ebx, [dw_ZwQadd]

			mov [eax],ebx

			pushad

			call FuckFakeZw_NF

			popad

			jmp X64_PreCheck_1

		X64_PreCheck_1:

			mov eax, [dw_RighHookAdd]

			cmp eax,0

			je X64_PreCheck_1_ok

			mov eax, [eax]

			mov ebx, [dw_ZwQadd]

			cmp eax, ebx

			jne FuckTheFakeZwq                        //这里改掉了

		X64_PreCheck_1_ok:

			mov eax, [esp + 0x18]                        //BaseAdd

			mov ebx, [esp + 0x24]

			add eax, ebx

			cmp eax, [dw_MydllH_Beg]

			jl nothingFake

			sub eax, ebx

			cmp eax, [dw_MydllH_End]

			jg nothingFake                               

			mov eax, [esp + 0x10]                         

			mov [dw_CallZwAdd], eax                      //取出原调用地址并放入变量

			mov eax, FakeZwQuery_Ret                     //更改返回值

			mov[esp + 0x10], eax

		nothingFake :

			popfd

		    pop ecx

			pop ebx

			pop eax

			mov[esp-0x8],1

			mov eax, [dw_esp3]

			mov[esp-0xC],eax

			mov eax, [dw_esp4]  //这样子写 再加pushfd就ok了

			mov[esp-0x10],eax   //尝试还原堆栈

			mov eax, [dw_esp1]

			mov[esp-0x14],eax

			mov eax, [dw_esp2]

			mov[esp-0x18],eax

			mov eax, [i_ZwQueryv]

			jmp [dw_ZwQuery_Ret]

	}

	VMProtectEnd();

}

DWORD dw_f1 = (DWORD)FakeZwQuery_X32;

DWORD* dw_f2 = 0;

DWORD* dw_f3 = 0;

DWORD WINAPI FuckAnubis(LPVOID lpParam)

{

	VMProtectBegin("FuckAnubis");

	//判断游戏是否已经开始了

	//Sleep(15000);

	WritePrivateProfileStringA("z", "a", "0", "c:\\xxxx.ini");

	DWORD dw_readprocess;

	dw_readprocess = (DWORD)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "ReadProcessMemory");

	while (dw_readprocess == NULL)

	{

		dw_readprocess = (DWORD)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "ReadProcessMemory");

		Sleep(1000);

	}

	dw_ZwQuery = (DWORD)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwQueryVirtualMemory");

	while (dw_ZwQuery == NULL)

	{

		dw_ZwQuery = (DWORD)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwQueryVirtualMemory");

		Sleep(1000);

	}

	dw_ReallyZWQCheck = (DWORD)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwQueryVirtualMemory");

	dw_ReallyQuery = (DWORD)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "VirtualQuery");

	dw_Userdll = (DWORD)GetModuleHandleA("user32.dll");

	__asm{

		mov eax, [dw_ReallyQuery]           //值放进去

		mov eax, [eax]                      //头四个字节放进去

		mov [dw_ReallyQuery],eax            //四个字节放到变量里

		mov eax, [dw_ReallyZWQCheck]

		mov eax, [eax]

		mov [dw_ReallyZWQCheck],eax

		mov eax, [dw_readprocess]

		add eax, 0x5

		mov[dw_ReadRet], eax

		sub eax, 0x5

	GetReadHook:

		mov eax, [dw_readprocess]

		mov eax, [eax]

		cmp al, 0xE8

		je  EXITREAD

		cmp al, 0xE9

		je EXITREAD

		jmp GetReadHook

	EXITREAD :

		mov eax, [dw_ZwQuery]

		mov eax, [eax]

		mov[dw_ZwHeadFour],eax

	}

	dw_ZwQadd = dw_ZwQuery;

	dw_FakeCheckAdd = 0x10000;

	GetPrivateProfileStringA("c", "d", "", ch_ZwQueryv, 4, "c:\\xxxx.ini");

	i_ZwQueryv = atoi(ch_ZwQueryv);

	i_ZwQueryv -= 12;

	                                                                                               //我们需要先获取自身Dll的地址与大小

	dw_MydllH_Beg = (DWORD)RetMydllH();                                                            //VMP之后的大小 0x2D7000

	dw_MydllH_End = dw_MydllH_Beg + 0x328000;

	                                                                                               //初始化参数

	byte b_ba = { 0xBA };

	DWORD dw_Fake_Zw64 = (DWORD)FakeZwQuery_NoWin7x64;

	DWORD dw_OldProtect = 0;

	char ch_Sys_1[3];

	int i_Sys_1 = 0;

	GetPrivateProfileStringA("c", "e", "", ch_Sys_1, 2, "c:\\xxxx.ini");

	GetPrivateProfileStringA("c", "ee", "", ch_sTen, 2, "c:\\xxxx.ini");

	i_sTen = atoi(ch_sTen);

	i_Sys_1 = atoi(ch_Sys_1);

	switch (i_Sys_1)

	{

	case 1:                                                //无CRC的平台

		dw_ZwQuery_Ret = dw_ZwQuery + 0x5;

		WriteJump(dw_ZwQuery, (DWORD)FakeZw_Win7x64);

		break;

	case 2:                                                //CRC call edx mov edx,xxxx <-HOOK

		dw_ZwQuery = dw_ZwQuery + 0x5;

		__asm{

			mov eax, [dw_ZwQuery]

			add eax,1

			mov eax, [eax]

			mov [dw_A],eax

		}

		FullAccess(dw_ZwQuery, 5);

		memcpy((LPVOID)dw_ZwQuery, &b_ba, 1);

		dw_ZwQuery += 1;

		memcpy((LPVOID)dw_ZwQuery, &dw_Fake_Zw64, 4);

		break;

	case 3:

		dw_ZwQuery = dw_ZwQuery + 0x5;

		__asm{

			mov eax, [dw_ZwQuery]

			add eax,1

			mov eax, [eax]

			mov eax, [eax]

			mov [dw_A],eax

		}

		dw_f2 = &dw_f1;

		dw_f3 = dw_f2;

		FullAccess(dw_ZwQuery, 5);

		memcpy((LPVOID)dw_ZwQuery, &b_ba, 1);

		dw_ZwQuery += 1;

		memcpy((LPVOID)dw_ZwQuery, &dw_f3, 4);

		break;

	default:

		break;

	}

	VMProtectEnd();

	return 1;

}


注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功