Tulip 2021 Game Assistive Technology (Junior Class) (Part 1)

%p、size_t、%zd、%llu、FindWindow、GetWindowText、SetWindowText

HMODULE hModule = GetModuleHandle(nullptr);
// %p 表示格式化指针
printf("ddd %p\n", hModule);
// sizeof输出的类型为size_t,%zd 表示格式化size_t类型大小
// 在x64系统下sizeof运算符 返回值是size_t 占用空间8字节 要使用%llu格式化输出
printf("sizeof(HMODULE)=%zd 字节\n", sizeof(hModule));	// sizeof(HMODULE)
//HWND hWnd = reinterpret_cast<HWND>(0x001A03DE);
printf("sizeof(DWORD)=%zd sizeof(LONG)=%zd\n", sizeof(DWORD), sizeof(LONG));

	// char short int的表示范围
	// 头文件 #include<limits.h>
	printf("char类型表示范围 %d至%d\r\n", SCHAR_MIN, SCHAR_MAX);
	printf("unsigned char类型表示范围 %u至%u\r\n", 0, UCHAR_MAX); 
	// short 
	printf("short类型表示范围 %d至%d\r\n", SHRT_MIN, SHRT_MAX);
	printf("unsigned short类型表示范围 %u至%u\r\n", 0, USHRT_MAX);
	// int  -21亿 +21亿
	printf("int类型表示范围 %d至%d\r\n", INT_MIN, INT_MAX);
	printf("unsigned int类型表示范围 %u至%u\r\n", 0, UINT_MAX);

HWND calcHwnd = FindWindow(L"CalcFrame", nullptr);
printf("窗口句柄=%p\r\n", calcHwnd);
TCHAR buf[MAX_PATH] = {
    
     0 };
wchar_t outBuf[MAX_PATH] = {
    
     0 };
GetWindowText(calcHwnd, buf, MAX_PATH);
// %ws 表示格式化宽字符串
swprintf_s(outBuf, L"calc %ws\n", buf);	
// 宽字符串也可以使用大写的%S格式化输出
//_stprintf_s(outBuf, _T("calc caption %S\n"), buf);
MessageBox(nullptr, outBuf, buf, MB_OK);
SetWindowText(calcHwnd, L"我的计算器zzz");

GetWindowThreadProcessId、OpenProcess、ReadProcessMemory

GetWindowThreadProcessId //Return thread TID and process PID

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Insert image description here

#include <iostream>	// 包含了<stdio.h>头文件
#include<Windows.h>
int main()
{
    
    
     // 1 通过窗口标题或者类名 获取目标窗口句柄
	 // 2 通过窗口句柄获取进程的PID,TID
	HWND 窗口句柄 = FindWindowA("MainWindow", "植物大战僵尸中文版");
	printf("窗口句柄 h=%p\r\n", h);
	DWORD pid = 0, tid = 0;
	printf("&pid=%p\r\n", &pid);
	// int 和 long是等价
	// DWORD  等价于 unsigned long 
	// DWORD* 等价于 LPDWORD
	tid = GetWindowThreadProcessId(窗口句柄, &pid);
	printf("tid=%d pid=%d  16进制tid=%X 16进制pid=%X\r\n", tid, pid, tid, pid);

	// 获取 进程 权限 句柄
	// 通过pid获取进程句柄,同时要指定渴望得到的访问权限
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); // PROCESS_VM_READ
	printf("进程句柄=%p \r\n", 进程句柄);
	unsigned int 返回值 = 0;
	//跨进程读取目标进程指定地址处的4字节数据
	//ReadProcessMemory(进程句柄, (LPCVOID)0x0000000077B2C934/*要读取的地址*/, &返回值/*存放数据的地址*/, 4, 0);
	ReadProcessMemory(进程句柄, reinterpret_cast<LPCVOID>(0x77B2C934)/*要读取的地址*/, &返回值/*存放数据的地址*/, 4, 0);
	printf("返回值=%X 返回值=%d 返回值=%u\r\n", 返回值, 返回值, 返回值);// GetLastError();
}

Insert image description here


Sealing read memory interface function int R4(void* address)

Read the data in the base address offset formula through the interface function.

Insert image description here

DWORD R4(UINT_PTR 内存地址)
{
    
     
	HWND 窗口句柄 = FindWindowA("MainWindow", "植物大战僵尸中文版"); 
	DWORD pid = 0, tid = 0;  
	tid = GetWindowThreadProcessId(窗口句柄, &pid);
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);	// PROCESS_VM_READ
	DWORD 返回值 = 0;
	ReadProcessMemory(进程句柄, (LPCVOID)内存地址/*要读取的地址*/, &返回值/*存放数据的地址*/, 4, 0);
	return 返回值;
}

Write a value across processes to the memory address of the target process WriteProcessMemory

Insert image description here

#include <iostream>
#include<Windows.h>

HWND 获取游戏窗口句柄()
{
    
    
	return FindWindowA("MainWindow", "植物大战僵尸中文版");
}

//unsigned
DWORD R4(UINT_PTR 内存地址)
{
    
    
	HWND 窗口句柄 = 获取游戏窗口句柄();	//FindWindowA("MainWindow", "植物大战僵尸中文版");
	DWORD pid = 0, tid = 0;
	tid = GetWindowThreadProcessId(窗口句柄, &pid);
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
	DWORD 返回值 = 0;
	ReadProcessMemory(进程句柄, (LPCVOID)内存地址/*要读取的地址*/, &返回值/*存放数据的地址*/, 4, nullptr);
	CloseHandle(进程句柄);//释放掉句柄资源
	return 返回值;
}

//写入成功 W4返回 非0的数值
//写入失败 W4返回 0
int W4(UINT_PTR 内存地址/*要写入目标进程的内存地址*/, DWORD 要写入的值)
{
    
    
	HWND 窗口句柄 = 获取游戏窗口句柄();	//FindWindowA("MainWindow", "植物大战僵尸中文版");
	DWORD pid = 0, tid = 0;
	tid = GetWindowThreadProcessId(窗口句柄, &pid); 
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
	unsigned int 返回值 = WriteProcessMemory(进程句柄, (LPCVOID)内存地址/*要写的目标进程地址*/, &要写入的值/*存放待写入数据的地址*/, 4, nullptr);
	CloseHandle(进程句柄);//释放掉句柄资源
	return 返回值;
}

int main()
{
    
    
	//[[6A9EC0]+768]+5560 =14F2A3D8
	// [[[6A9EC0]+768]+5560]=75
	int 阳光 = R4(R4(R4(0x6A9EC0) + 0x768) + 0x5560);
	UINT_PTR 阳光地址 = R4(R4(0x6A9EC0) + 0x768) + 0x5560;
	printf("阳光=%d\r\n", 阳光);
	printf("阳光地址=%X\r\n", 阳光地址);
	
	W4(阳光地址, 567);
	
	getchar();//等待键盘输入
}

int main_0()
{
    
    
	//[[6A9EC0]+768]+5560 =14F2A3D8
	// [[[6A9EC0]+768]+5560]=75
	int 阳光 = R4(R4(R4(0x6A9EC0) + 0x768) + 0x5560);
	UINT_PTR 阳光地址 = R4(R4(0x6A9EC0) + 0x768) + 0x5560;
	printf("阳光=%d\r\n", 阳光);
	printf("阳光地址=%X\r\n", 阳光地址);

	HWND 窗口句柄 = 获取游戏窗口句柄();	//FindWindowA("MainWindow", "植物大战僵尸中文版");
	DWORD pid = 0, tid = 0;
	tid = GetWindowThreadProcessId(窗口句柄, &pid);
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
	int 新阳光的值 = 66666;
	WriteProcessMemory(进程句柄, (LPVOID)阳光地址, &新阳光的值, 4, nullptr);
	CloseHandle(进程句柄);//释放掉句柄资源

	getchar();//等待键盘输入
}

C, C++ 32-bit and 64-bit process memory data reading and writing function interface, project management through header files

Insert image description here

// 内存读写.h
#pragma once
#include <iostream>
#include<Windows.h>

HWND 获取游戏窗口句柄();
DWORD R4(UINT_PTR 内存地址/*从这个地址开始读取4字节*/);
int W4(UINT_PTR 内存地址/*从这个地址开始写入4字节*/, DWORD 要写入的值);
// 内存读写.cpp
#include "内存读写.h"

HWND 获取游戏窗口句柄()
{
    
    
	return FindWindowA("MainWindow", "植物大战僵尸中文版");
}

// 读取4字节数据
DWORD R4(UINT_PTR 内存地址)
{
    
    
	HWND 窗口句柄 = 获取游戏窗口句柄();	//FindWindowA("MainWindow", "植物大战僵尸中文版");
	DWORD pid = 0, tid = 0;
	tid = GetWindowThreadProcessId(窗口句柄, &pid);
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
	DWORD 返回值 = 0;
	ReadProcessMemory(进程句柄, (LPCVOID)内存地址/*要读取的地址*/, &返回值/*存放数据的地址*/, 4, nullptr);
	CloseHandle(进程句柄);//释放掉句柄资源
	return 返回值;
}

//写入成功 W4返回 非0的数值
//写入失败 W4返回 0
int W4(UINT_PTR 内存地址/*要写入目标进程的内存地址*/, DWORD 要写入的值)
{
    
    
	HWND 窗口句柄 = 获取游戏窗口句柄();	//FindWindowA("MainWindow", "植物大战僵尸中文版");
	DWORD pid = 0, tid = 0;
	tid = GetWindowThreadProcessId(窗口句柄, &pid); 
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
	unsigned int 返回值 = WriteProcessMemory(进程句柄, (LPCVOID)内存地址/*要写的目标进程地址*/, &要写入的值/*存放待写入数据的地址*/, 4, nullptr);
	CloseHandle(进程句柄);//释放掉句柄资源
	return 返回值;
}
// main程序入口点.cpp
#include "内存读写.h"

	//[[6A9EC0]+768]+5560 =14F2A3D8
	// [[[6A9EC0]+768]+5560]=75
	int 阳光 = R4(R4(R4(0x6A9EC0) + 0x768) + 0x5560);
	UINT_PTR 阳光地址 = R4(R4(0x6A9EC0) + 0x768) + 0x5560;
	printf("阳光=%d\r\n", 阳光);
	printf("阳光地址=%X\r\n", 阳光地址);
	
	DWORD 新的阳光值 = 5567;
	W4(阳光地址, 新的阳光值);
	
	getchar();//等待键盘输入

X64 environment masm assembly asm file

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Insert image description here

When we cannot find the main entry point in the x32dbg debugger, we can locate the entry point by adding a MessageBoxA or MessageBeep function at the beginning of the main function body:

Insert image description here

Insert image description here

As shown in the figure above, by jumping to the MessageBoxA function and setting a breakpoint, after running and breaking here, you can see the _main return address in the stack in the lower right corner.

When we write our own code for debugging and testing, it is best to disable the random base address so that it can be turned into a fixed address to facilitate our testing:

Insert image description here

  call指令
  77256C78 | E8 EF02FBFF    | call ntdll.77206F6C       
  EIP=77206F6C
  push 77256C78+5 //esp=esp-4	//64 rsp=rsp-8
  
  ret指令
  77256CAF | C3             | ret    
  跳转到 [esp]
  esp=esp+4  //64 rsp=rsp+8

Six common parameter calling conventions: passing and flat stack

Insert image description here


x86 environment

#include<iostream>

//VS环境默认的调用约定
//add esp,参数数量*4
//add rsp,参数数量*8
int _cdecl call_cdecl(int a, int b)
{
    
    
	return a + b;
}

//ret 参数数量*4  //x86   //ret 8
//ret 参数数量*8  //x64   //ret 10
int _stdcall call_std(int a, int b)
{
    
    
	return a + b;
}
//快速
int _fastcall call_fast(int a, int b)
{
    
    
	return a + b;
}
// thiscall 类成员函数独有
/*
int __thiscall call_vector(int a, int b)
{
	return a + b;
}
*/
// __vectorcall (/ Gv)
int __vectorcall call_vector(int a, int b)
{
    
    
	return a + b;
}

//int __clrcall test()
//{
    
    
//	return 1;
//}

int abc(int a, int b, int c)
{
    
    
	printf("技能释放 a=%d,b=%d c=%d\r\n", a, b, c);
	return a + b + c;
}
int main()
{
    
    
	int a = 333;
	int b = 123;
	printf(" call_cdecl()=%X行号=%d\r\n",  call_cdecl(0x11A, 0xA11), __LINE__);

	printf(" call_std()=%X行号=%d\r\n",    call_std(0x11B, 0xB11), __LINE__);

	printf(" call_fast()=%X行号=%d\r\n",   call_fast(0x11C, 0xC11), __LINE__);

	printf(" call_vector()=%X行号=%d\r\n", call_vector(0x11D, 0xD11), __LINE__);

	printf(" 释放技能 abc=%d\r\n", abc(0x123, 2, 6));
	getchar();
	return 1;
}

Insert image description here

Insert image description here

Functions can be labeled using colons and comments can be added using semicolons.

Insert image description here

In the x86 environment, the _fastcall calling convention passes parameters: ecx parameter 1, edx parameter 2, and the remaining parameters are passed through the stack (push), and the stack is flattened (ret n) within the function.

Insert image description here

In the x86 environment, the _vectorcall calling convention passes parameters: ecx parameter 1, edx parameter 2, and the remaining parameters are passed through the stack (push), which is also flattened within the function (< a i=1>). Since the parameters passed now are all integers, we can see through disassembly that parameter passing and stack balancing are the same for _fastcall and _vectorcall; in fact, there is a difference between them, and the difference should lie in the parameters. is a floating point number. ret 数值

In the x86 environment, the _cdecl and _stacall calling conventions all use push to pass parameters.


x64 environment

#include<iostream>

//VS环境默认的调用约定
//add esp,参数数量*4
//add rsp,参数数量*8
int _cdecl call_cdecl(int a, int b,int a3,int a4,int a5,int a6)
{
    
    
	return a + b+a3+a4+a5+a6;
}

//ret 参数数量*4  //x86   //ret 8
//ret 参数数量*8  //x64   //ret 10
int _stdcall call_std(int a, int b, int a3, int a4, int a5, int a6)
{
    
    
	return a + b + a3 + a4 + a5 + a6;
}
//快速
int _fastcall call_fast(int a, int b, int a3, int a4, int a5, int a6)
{
    
    
	return a + b + a3 + a4 + a5 + a6;
}
// thiscall 类成员函数独有
/*
int __thiscall call_vector(int a, int b)
{
	return a + b;
}
*/
// __vectorcall (/ Gv)
int __vectorcall call_vector(int a, int b, int a3, int a4, int a5, int a6)
{
    
    
	return a + b + a3 + a4 + a5 + a6;
}

//int __clrcall test()
//{
    
    
//	return 1;
//}

int abc(int a, int b, int c)
{
    
    
	printf("技能释放 a=%d,b=%d c=%d\r\n", a, b, c);
	return a + b + c;
}
int main()
{
    
    
	int a = 333;
	int b = 123;
	printf(" call_cdecl()=%X行号=%d\r\n", call_cdecl(0x11A, 0xA11,3,4,5,6), __LINE__);

	printf(" call_std()=%X行号=%d\r\n", call_std(0x11B, 0xB11,3,4,5,6), __LINE__);

	printf(" call_fast()=%X行号=%d\r\n", call_fast(0x11C, 0xC11,3,4,5,6), __LINE__);

	printf(" call_vector()=%X行号=%d\r\n", call_vector(0x11D, 0xD11,3,4,5,6), __LINE__);

	printf(" 释放技能 abc=%d\r\n", abc(0x123, 2, 6));
	getchar();
	return 1;
}

In the x64dbg debugger, if you want to go to the main function, press ctrl+G and enter main to confirm. There is no need to add an underline in front of main (x86).

Insert image description here

In the x64 environment, we found that the four calling conventions of _cdecl, _stacall, _fastcall, and _vectorcall are all the same. They all use rcx, rdx, r8, and r9 to pass parameters. If more than 4 parameters are used, the stack (rsp+20) is used. to pass.

We see that the fifth parameter is rsp+20, and the first four parameters occupy a space of 0x20 size. However, in the x64 environment, the first four parameters are passed through rcx, rdx, r8, and r9 respectively. In order Alignment (also for compatibility with x86 assembly), the fifth parameter is passed through rsp+20, and the sixth parameter is passed through rsp+28;
and the last instruction inside the function is a < /span>ret, not followed by a value.

After testing, we found that in the x64 environment, there is no difference between these four calling conventions. The parameter passing and flat stacking methods are the same, so for the time being, these four calling conventions can be considered to be the same.

Insert image description here

Since the call instruction of this function is executed, rsp=rsp-8, so the above picturemov ss:[rsp+20],r9d does not cover the fifth parameter before the call instruction is executed, mov ss:[rsp +20], r9d is equivalent to mov ss:[rsp+18],r9d for the environment before the call instruction is executed, that is, the fourth parameter is given to ss:[rsp+18], this kind of stack in the function The parameter passing method is also for compatibility with x86 assembly.
That is, the stack change diagram is as follows:

Insert image description here

Insert image description here

x64 register Lower 4 bytes Lower 2 bytes Lower 1 byte
rcx ecx cx cl
rdx edx dx dl
r8 r8d r8w r8b
r9 r9d r9w r9b

Looking at another function, the stack changes in the same way:

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Can be set for all configurations, all platforms:

Insert image description here


Assembly conditional transfer instructions and loops

Insert image description here

Insert image description here

int main_while01()
{
    
    
	/* 局部变量定义 */
	int a = 10;

	/* while 循环执行 */
	// SF(符号标志位)
	// OF(溢出标志位)
	//cmp a-20 从而影响到 符号标志位
	while (a < 20) // SF=OF  
	{
    
    
		printf("a 的值: %d  行号=%d \n", a, __LINE__);
		a++; //a=a+1; add [esp+??],1// inc [esp+??]
	}
	return 0;
}

int main()
{
    
    
	printf("main start 行号=%d \n", __LINE__);
	main_while01();
	printf("main end   行号=%d \n", __LINE__);
	return 1;
}

Insert image description here

Insert image description here

Insert image description here

We see that OF is not equal to SF in the above picture, and SF is 1. This is the condition of the signed jump instructionJL, so the conditionjge is not true. , does not jump, enters the loop.
(The assembly instruction cmp performs a subtraction operation, that is, a - 20, thus affecting the sign flag SF)

Insert image description here

As shown in the figure above, when ss:[ebp-8] is equal to 14, execute the cmp instruction, you can see that ZF is equal to 1, OF is equal to SF, both are 0:

Insert image description here

When OF equals 0 and SF equals 0, that is, OF==SF, then the signed jump instructionjgeThe jump condition is established and the loop terminates.

Subtraction affects the SF and ZF flags;
Addition affects the CF and OF flags.

Let's take a look at the while loop code containing the continue statement:

int main_continue()
{
    
    
	/* 局部变量定义 */
	int a = 0;

	/* while 循环执行 */
	while (a < 10) //0x0A=10
	{
    
    
		a++;
		if (a == 5)
		{
    
    
			/* 使用 continue 进入下一次循环 */
			continue;
		}
		printf("for循环测试:a 的值: %d 行号=%d \n", a, __LINE__);
	}
	return 0;
}

int main()
{
    
    
	printf("main start 行号=%d \n", __LINE__);
	main_continue();
	printf("main end   行号=%d \n", __LINE__);
	return 1;
}

Insert image description here

We can see from the above figure that if it is less than, use the jge command, and if it is equal to, use the jne command.


C, C++ uses code to call CALL across processes

Call CALL with code injector

#include <iostream>
#include <Windows.h>
int call00()
{
    
    
	printf("call00 无参数 call0_test  行号=%d\r\n",  __LINE__);
	return 0x123;
}

int call01(int a)
{
    
    
	printf("call01 参数1=%d   行号=%d\r\n", a,  __LINE__);
	return a + 2;
}

int call02(int a, int b)
{
    
    
	printf("call02 参数1=%d 参数2=%d 行号=%d\r\n", a, b,__LINE__);
	return a + b+3;
}

int main()
{
    
    
//	MessageBoxA(0, 0, 0, 0);//ctrl+G 转到 MessageBoxA 下断
	printf("MessageBoxA=%p 行号=%d \r\n", MessageBoxA, __LINE__);
	int 计数 = 1;
	while (1)
	{
    
    
		printf("call00=%p call01=%p,call02=%p \n", call00, call01, call02);
		getchar();
		printf("计数=%d,行号=%d \r\n", 计数++, __LINE__);
	}
	return 1;
}

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Note,The thread number 5236 on the title bar of x64dbg is in decimal, and the 1474 in the lower left corner is in hexadecimal. These two numbers are the same .


C, C++ creates a remote thread and calls CALL

  • Remote CALL process
    1. Use spy++ to get the target window handle, FindWindow
    2. With a window handle, use GetWindowThreadProcessID to obtain the target process PID.
    3. Obtain the thread creation permission of the target process through OpenProcess and obtain the corresponding handle.
    4. Use CreateRemoteThread to call remote CALL
#include <iostream>
#include<Windows.h>
//unsigned
//int R4(UINT_PTR 内存地址)
//{
    
    
//	HWND 窗口句柄 = FindWindowA("MainWindow", "植物大战僵尸中文版");
//	DWORD pid = 0, tid = 0;
//	tid = GetWindowThreadProcessId(窗口句柄, &pid); // a&b 
//	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);//HWND
//	unsigned int 返回值 = 0;
//	ReadProcessMemory(进程句柄, (LPCVOID)内存地址/*要读取的地址*/, &返回值/*存放数据的地址*/, 4, 0);
//	return 返回值;
//}

// \n
// \ \\
// 窗口标题= "C:\\Users\\Administrator\\source\\repos\\A001\\Debug\\A023_测试CALL.exe"
//#define 窗口标题 "C:/moshou/A001-游戏辅助技术(初级班)/代码\A001-024/Debug"
//#define 窗口标题 "C:\moshou\A001-游戏辅助技术(初级班)\代码\A001-024\Debug"
#define 窗口标题 R"(C:\moshou\A001-游戏辅助技术(初级班)\代码\A001-024\Debug\A023_测试CALL.exe)"

DWORD 获取PID()
{
    
    
 	HWND 窗口句柄 = FindWindowA(0, 窗口标题);
 	DWORD pid = 0, tid = 0;
 	tid = GetWindowThreadProcessId(窗口句柄, &pid); // a&b 
	return pid;
}

void 调用call01测试()
{
    
    
	DWORD pid = 4180; //直接在任务管理器里 取得PID
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);//HWND
	//1,4,5 重视这3个参数
	CreateRemoteThread(
		进程句柄,//1
		0, //2
		0, //3
		(LPTHREAD_START_ROUTINE)0x411370,//4 CALL地址
		(LPVOID)123,//5 CALL的参数
		0,
		0);
}

void 调用call01测试2(int 参数1)
{
    
    
	DWORD pid = 4180;//任务管理器取的pid
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);//HWND
	//1,4,5 重视这3个参数
	CreateRemoteThread(
		进程句柄,//1
		0, //2
		0, //3
		(LPTHREAD_START_ROUTINE)0x411370,//4 CALL地址
		(LPVOID)参数1,//5 CALL的参数
		0,
		0);
	CloseHandle(进程句柄);
}

void 调用call01测试3(int 参数1)
{
    
    
	DWORD pid = 获取PID();//任务管理器取的pid
	printf("pid=%d \r\n", pid);
	HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);//HWND
	//1,4,5 重视这3个参数
	CreateRemoteThread(
		进程句柄,//1
		0, //2
		0, //3
		(LPTHREAD_START_ROUTINE)0x4113CA,//4 call01地址
		(LPVOID)参数1,//5 CALL的参数
		0,
		0);
	CloseHandle(进程句柄);
}

int main()
{
    
    
	调用call01测试3(12666);
	调用call01测试3(12667);
	调用call01测试3(12668);
	//R忽略 转义字符
	char test[]= R"(C:\Users\Administrator\source\repos\A001\Debug\A023_测试CALL.exe)";
	//char test2[] = "C:\Users\Administrator\source\repos\A001\Debug\A023_测试CALL.exe";
	printf("%s\r\n",test);
    std::cout << "Hello World!\n";
}
 

Miscellaneous

Commonly used software games

Insert image description here

This code injector can only be used for testing 32-bit programs. There is no free code injection tool that can be used by 64-bit processes. We can only write our own code to inject it.

Insert image description here

Insert image description here
Insert image description here
Insert image description here
Insert image description here

Signature-free loading driver:
https://github.com/TheCruZ/kdmapper

win10 signature:
https://github.com/HyperSine/Windows10-CustomKernelSigners

Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here
If the Inter C++ Compiler compiler is installed in the vs platform tool set, Intel's compiler supports __asm int 3these inline assembly:

Insert image description here

Insert image description here

Insert image description here


Locating pattern

Insert image description here
After editing the feature code, move to the beginning of the function or above, Ctrl+B to open the输入要查找的二进制字串 dialog box, paste the feature code search, if it can be found, it means the feature we wrote There is no problem with the code;
You should also restart the game, open the OD add-on game, and search for the feature code as described above for verification.


d3d8thk hijack injection

Insert image description here

Insert image description here


PE View Analysis Tools

PE Viewer (PE_Study) https://www.cr173.com/soft/47081.html
PE File Viewer (PETool) https://www.cr173. com/soft/89855.html
Niyuan PE file extraction https://www.cr173.com/soft/85171.html

PE analysis tool (PE_Hacker) https://www.cr173.com/soft/1438600.html
https://blog.csdn.net/PE_Hacker/article/details /115766034

PE-Analysis:

Insert image description here


Driver development and debugging tool DriverTool

Driver development and debugging tools, such as digital signature Windows 64Signer V1.2 in test mode, and tools such as DebugView.

Insert image description here

/

Insert image description here

Guess you like

Origin blog.csdn.net/zhaopeng01zp/article/details/128086031