国际学院网站建设的意义专业seo培训
news/
2025/9/29 6:49:46/
文章来源:
国际学院网站建设的意义,专业seo培训,北京网站制作西安,ftp网站怎么看后台的代码郁金香2021年游戏辅助技术初级班#xff08;上#xff09; %p、size_t、%zd、%llu、FindWindow、GetWindowText、SetWindowTextGetWindowThreadProcessId、OpenProcess、ReadProcessMemory封接读内存接口函数 int R4(void* 地址)跨进程向目标进程内存地址写入数值 WriteProce… 郁金香2021年游戏辅助技术初级班上 %p、size_t、%zd、%llu、FindWindow、GetWindowText、SetWindowTextGetWindowThreadProcessId、OpenProcess、ReadProcessMemory封接读内存接口函数 int R4(void* 地址)跨进程向目标进程内存地址写入数值 WriteProcessMemoryC,C32位和64位进程内存数据读写函数接口、通过头文件进行项目管理X64环境masm汇编asm文件常见的六种参数调用约定传递与平栈x86环境x64环境 汇编条件转移指令与循环C,C用代码,跨进程调用CALL用代码注入器调用CALLCC创建远程线程调用CALL 常用软件游戏定位特征码PE查看分析工具驱动开发调试工具 DriverTool %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_castHWND(0x001A03DE);
printf(sizeof(DWORD)%zd sizeof(LONG)%zd\n, sizeof(DWORD), sizeof(LONG));// char short int的表示范围// 头文件 #includelimits.hprintf(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(LCalcFrame, 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, Lcalc %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 //返回线程TID和进程PID #include iostream // 包含了stdio.h头文件
#includeWindows.h
int main()
{// 1 通过窗口标题或者类名 获取目标窗口句柄// 2 通过窗口句柄获取进程的PID,TIDHWND 窗口句柄 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* 等价于 LPDWORDtid 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_READprintf(进程句柄%p \r\n, 进程句柄);unsigned int 返回值 0;//跨进程读取目标进程指定地址处的4字节数据//ReadProcessMemory(进程句柄, (LPCVOID)0x0000000077B2C934/*要读取的地址*/, 返回值/*存放数据的地址*/, 4, 0);ReadProcessMemory(进程句柄, reinterpret_castLPCVOID(0x77B2C934)/*要读取的地址*/, 返回值/*存放数据的地址*/, 4, 0);printf(返回值%X 返回值%d 返回值%u\r\n, 返回值, 返回值, 返回值);// GetLastError();
}封接读内存接口函数 int R4(void* 地址)
通过接口函数读取基址偏移公式里的数据。 DWORD R4(UINT_PTR 内存地址)
{ HWND 窗口句柄 FindWindowA(MainWindow, 植物大战僵尸中文版); DWORD pid 0, tid 0; tid GetWindowThreadProcessId(窗口句柄, pid);HANDLE 进程句柄 OpenProcess(PROCESS_ALL_ACCESS, 0, pid); // PROCESS_VM_READDWORD 返回值 0;ReadProcessMemory(进程句柄, (LPCVOID)内存地址/*要读取的地址*/, 返回值/*存放数据的地址*/, 4, 0);return 返回值;
}跨进程向目标进程内存地址写入数值 WriteProcessMemory #include iostream
#includeWindows.hHWND 获取游戏窗口句柄()
{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]75int 阳光 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]75int 阳光 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,C32位和64位进程内存数据读写函数接口、通过头文件进行项目管理 // 内存读写.h
#pragma once
#include iostream
#includeWindows.hHWND 获取游戏窗口句柄();
DWORD R4(UINT_PTR 内存地址/*从这个地址开始读取4字节*/);
int W4(UINT_PTR 内存地址/*从这个地址开始写入4字节*/, DWORD 要写入的值);// 内存读写.cpp
#include 内存读写.hHWND 获取游戏窗口句柄()
{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]75int 阳光 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环境masm汇编asm文件 当我们在x32dbg调试器中找不到main入口点的时候可以通过在main函数主体最开始位置那里添加MessageBoxA或者MessageBeep函数这种方法来定位入口点 如上图所示通过跳转到MessageBoxA函数这里并下断点运行到这里断下后在右下角栈那里可以看到_main返回地址。
在我们自己编写代码调试测试的时候最好把随机基址给禁用掉这样就可以变成固定地址方便我们测试 call指令77256C78 | E8 EF02FBFF | call ntdll.77206F6C EIP77206F6Cpush 77256C785 //espesp-4 //64 rsprsp-8ret指令77256CAF | C3 | ret 跳转到 [esp]espesp4 //64 rsprsp8常见的六种参数调用约定传递与平栈 x86环境
#includeiostream//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;
}可以按冒号给函数添加标签按分号添加注释。 在x86环境下_fastcall调用约定传递参数ecx参数1、edx参数2、剩下的参数通过堆栈push来传递并在函数内进行平栈ret n。 在x86环境下_vectorcall调用约定传递参数ecx参数1、edx参数2、剩下的参数通过堆栈push来传递也是在函数内进行平栈ret 数值。 由于现在传的参数都是整数所以_fastcall和_vectorcall我们通过反汇编看到参数传递、堆栈平衡都一样其实它们是有区别的区别应该就在于参数是浮点数的情况下。
在x86环境下_cdecl和_stacall调用约定全部是用push传递参数。
x64环境
#includeiostream//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 ba3a4a5a6;
}//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;
}在x64dbg调试器中转到main函数的话ctrlG输入main确定即可main前面不需要加下划线x86。 在x64环境下_cdecl、_stacall和_fastcall、_vectorcall这4种调用约定我们发现都一样都是用rcx、rdx、r8、r9来传递参数超出4个的参数用堆栈rsp20来传递。
我们看到第5个参数是rsp20前4个参数占0x20大小的空间但是在x64环境下前4个参数分别通过rcx、rdx、r8、r9来传递为了对齐也是为了兼容x86汇编第5个参数通过rsp20来传递第6个参数通过rsp28来传递 而且在函数内部最后一条指令就是一条ret后面不跟数值。
经过测试我们发现在x64环境下这4种调用约定是没有区别的参数传递和平栈方式都是相同的所以暂时可以认为这4种调用约定是相同的。 由于call该函数的指令执行后rsprsp-8所以上图mov ss:[rsp20],r9d并没有覆盖call指令执行前的第5个参数mov ss:[rsp20],r9d对于call指令执行前的环境来说相当于mov ss:[rsp18],r9d即第4个参数给了ss:[rsp18]在函数里面的这种堆栈传参方式也是为了兼容x86汇编。 即堆栈变化示意图如下 x64寄存器低4字节低2字节低1字节rcxecxcxclrdxedxdxdlr8r8dr8wr8br9r9dr9wr9b
再看一个函数堆栈变化同理 可以针对所有配置、所有平台进行设置 汇编条件转移指令与循环 int main_while01()
{/* 局部变量定义 */int a 10;/* while 循环执行 */// SF(符号标志位)// OF(溢出标志位)//cmp a-20 从而影响到 符号标志位while (a 20) // SFOF {printf(a 的值 %d 行号%d \n, a, __LINE__);a; //aa1; 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;
}我们看到上图OF不等于SFSF为1这是有符号跳转指令JL的条件所以jge条件不成立不跳转进入循环。 汇编指令cmp就是做了一个减法操作即a - 20从而影响到符号标志位SF 如上图所示当ss:[ebp-8]等于14的时候执行cmp指令可以看到ZF等于1OF等于SF都为0 当OF等于0SF等于0即OFSF那么有符号跳转指令jge跳转条件成立循环终止。
减法的话对SF和ZF标志位有影响 加法的话对CF和OF标志位有影响。
我们再来看看包含continue语句的while循环代码
int main_continue()
{/* 局部变量定义 */int a 0;/* while 循环执行 */while (a 10) //0x0A10{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;
}我们从上图可以看到判断小于的话用jge指令判断等于的话用jne指令。
C,C用代码,跨进程调用CALL
用代码注入器调用CALL
#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 b3;
}int main()
{
// MessageBoxA(0, 0, 0, 0);//ctrlG 转到 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;
}注意x64dbg标题栏上的线程号5236是十进制的左下角的1474是十六进制的这两个数是一样的。
CC创建远程线程调用CALL
远程调用CALL的流程 用spy获取目标窗口句柄,FindWindow有了窗口句柄的情况 用GetWindowThreadProcessID获取目标进程PID通过OpenProcess获取目标进程的线程创建权限 获取相应的句柄用CreateRemoteThread调用远程的CALL
#include iostream
#includeWindows.h
//unsigned
//int R4(UINT_PTR 内存地址)
//{
// HWND 窗口句柄 FindWindowA(MainWindow, 植物大战僵尸中文版);
// DWORD pid 0, tid 0;
// tid GetWindowThreadProcessId(窗口句柄, pid); // ab
// 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); // ab return pid;
}void 调用call01测试()
{DWORD pid 4180; //直接在任务管理器里 取得PIDHANDLE 进程句柄 OpenProcess(PROCESS_ALL_ACCESS, 0, pid);//HWND//1,4,5 重视这3个参数CreateRemoteThread(进程句柄,//10, //20, //3(LPTHREAD_START_ROUTINE)0x411370,//4 CALL地址(LPVOID)123,//5 CALL的参数0,0);
}void 调用call01测试2(int 参数1)
{DWORD pid 4180;//任务管理器取的pidHANDLE 进程句柄 OpenProcess(PROCESS_ALL_ACCESS, 0, pid);//HWND//1,4,5 重视这3个参数CreateRemoteThread(进程句柄,//10, //20, //3(LPTHREAD_START_ROUTINE)0x411370,//4 CALL地址(LPVOID)参数1,//5 CALL的参数0,0);CloseHandle(进程句柄);
}void 调用call01测试3(int 参数1)
{DWORD pid 获取PID();//任务管理器取的pidprintf(pid%d \r\n, pid);HANDLE 进程句柄 OpenProcess(PROCESS_ALL_ACCESS, 0, pid);//HWND//1,4,5 重视这3个参数CreateRemoteThread(进程句柄,//10, //20, //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;
}
常用软件游戏 这个代码注入器只能用于32位程序的测试64位进程能用的这类代码注入工具目前还没有发现免费的我们只能自己写代码来注入。 免签名加载驱动 https://github.com/TheCruZ/kdmapper
win10过签名 https://github.com/HyperSine/Windows10-CustomKernelSigners vs平台工具集如果装了Inter C Compiler编译器的话Intel的编译器是支持__asm int 3这些内联汇编的 定位特征码 编辑好特征码之后移动到函数开头、或者更上面一些CtrlB打开输入要查找的二进制字串对话框粘贴特征码搜索能找到的话说明我们编写的特征码没问题 还应该重启游戏打开OD附加游戏按照上面所述搜索特征码进行验证。 PE查看分析工具
PE查看器(PE_Study) https://www.cr173.com/soft/47081.html PE文件查看器(PETool) https://www.cr173.com/soft/89855.html 逆缘PE文件提取 https://www.cr173.com/soft/85171.html
PE分析工具(PE_Hacker) https://www.cr173.com/soft/1438600.html https://blog.csdn.net/PE_Hacker/article/details/115766034
PE-Analysis 驱动开发调试工具 DriverTool
驱动开发调试工具比如测试模式下的数字签名Windows 64Signer V1.2又比如DebugView等一些工具。 /
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/921494.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!