好友
阅读权限25
听众
最后登录1970-1-1
|
本帖最后由 Yifan2007 于 2024-6-28 20:08 编辑
涉及对于程序的读写,汇编的基础知识
Day1读取数值,写入数值
#include<Windows.h>
#include<stdio.h>
#define 读写权限 0x10
int main()
{
读飞机数量();
return 1;
}
void 读()
{
//1-根据游戏的窗口标题和类名 取得窗口句柄
HWND 窗口句柄 = FindWindowA("GameClass1", "DemonStar v3.01 汉化终结版");
DWORD pid = 0;
GetWindowThreadProcessId(窗口句柄, &pid);//2-通过窗口句柄取得关联进程的 PID
HANDLE 进程权限句柄 = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
pid);
int 飞机数量 = 0;
BOOL 返回值=ReadProcessMemory(
进程权限句柄,
(LPCVOID)0x5CD7C0, //要读取的地址 游戏进程的地址
&飞机数量,
4,
0);}
void 写()
{
//1-根据游戏的窗口标题和类名 取得窗口句柄
HWND 窗口句柄 = FindWindowA("GameClass1", "DemonStar v3.01 汉化终结版");
DWORD pid = 0;//scanf_s 变量地址
//2-通过窗口句柄取得关联进程的 PID
GetWindowThreadProcessId(窗口句柄, &pid);
//3-根据PID 获取进程读写权限句柄
HANDLE 进程权限句柄 = OpenProcess(
PROCESS_ALL_ACCESS,//所有权限都包含了
FALSE,
pid);
// 有了进程权限句柄 就可以读写内存
int 飞机数量 = 3; //0xCC //0xCCCCCCCC
DWORD 实际写入字节数量 = 0;
WriteProcessMemory(
进程权限句柄,
(LPVOID)0x5CD7C0,//要写入的目标进程地址 //此地址是游戏的 是目标进程
&飞机数量, //待写入数值的地址 //当前进程的地址
4,// 写入4个字节 DWORD 无符号整数 sizeof(int)=4 sizeof(飞机数量)=4
&实际写入字节数量);//实际写入的字节数量 保存的地址 LPDWORD //DWORD*
}
#include<Windows.h>
#include<stdio.h>
#define 读写权限 0x10
HANDLE 取游戏权限句柄()
{
//1-根据游戏的窗口标题和类名 取得窗口句柄
HWND 窗口句柄 = FindWindowA("MainWindow", "植物大战僵尸中文版");
//printf("窗口句柄=%p 行号=%d\n", 窗口句柄, __LINE__);
DWORD pid = 0;//scanf_s 变量地址
//2-通过窗口句柄取得关联进程的 PID
GetWindowThreadProcessId(窗口句柄, &pid);
//printf("PID=%u \n", pid);
//3-根据PID 获取进程读写权限句柄
HANDLE 进程权限句柄 = OpenProcess(
PROCESS_ALL_ACCESS,//所有权限都包含了
FALSE,
pid);
//printf("进程权限句柄=%d 行号=%d\n", (int)进程权限句柄, __LINE__);
return 进程权限句柄;
}
DWORD R4(DWORD 地址) //R4
{
HANDLE h = 取游戏权限句柄();
DWORD 地址D = 0;
DWORD 返回值 = 0;
DWORD 实际访问字节数量 = 0;
ReadProcessMemory(
h,
(LPVOID)地址,//要访问的目标进程地址 //此地址是游戏的 是目标进程
&返回值, //待写入数值的地址 //当前进程的地址
4,// 读4个字节 DWORD 无符号整数 sizeof(int)=4 sizeof(飞机数量)=4
&实际访问字节数量);//实际写入的字节数量 保存的地址 LPDWORD //DWORD*
if (h)
{
CloseHandle(h);//释放相应的内核资源
}
return 返回值;
}
BOOL 写4字节(DWORD 地址, DWORD 值) //W4
{
HANDLE h = 取游戏权限句柄();
DWORD 地址D = 0;
//DWORD 返回值 = 0;
DWORD 实际访问字节数量 = 0;
BOOL 返回值 = WriteProcessMemory(
h,
(LPVOID)地址,//要访问的目标进程地址 //此地址是游戏的 是目标进程
&值, //待写入数值的地址 //当前进程的地址
4,// 读4个字节 DWORD 无符号整数 sizeof(int)=4 sizeof(飞机数量)=4
&实际访问字节数量);//实际写入的字节数量 保存的地址 LPDWORD //DWORD*
if (h)
{
CloseHandle(h);//释放相应的内核资源
}
return 返回值;
}
CSDN上对于栈的简单解释本文应用-->栈和寄存器总结_栈寄存器-CSDN博客
栈:先进后出的形式,从高地址向低地址增长
栈指针寄存器:ESP寄存器,栈顶。(低地址区)-后使用-栈帧
帧指针寄存器:EBP寄存器,栈底。(高地址区)-先使用-变量,参数-基址
EIP:储存下一条指令的地址,运行一次变一次
栈帧:每条语句,或每个过程都有自己的栈区。所以栈帧在栈指针(ESP)和帧指针(EBP)之间。
function(int x,int y,int z) 入栈堆顺序为Z-Y-X,地址大小Z>Y>X
PUSH POP MOV LEA 分别用于元素的入栈、出栈、入栈,入栈操作。入栈时地址-4,出栈时地址+4
CALL 跳转到ESP-4/-8的位置,然后让Call的下一行指令入栈
RET 跳转到ESP+4/+8的位置;若后面有数值RET X,再跳转到ESP+X的位置
总结:调用指令CALL和返回指令RET。都属于无条件转移指令,会改变程序的执行过程。
调用者保存寄存器:EAX寄存器、ECX寄存器、EDX寄存器被调用者保存寄存器:EBX寄存器、ESI寄存器、EDI寄存器
函数的形参在函数执行的时候是一个局部变量。局部变量被保存在栈中间或者栈的寄存器中。全局变量通常被保存在静态存储区。
_cdecl:是C++/C 对于函数的,标准平栈方式(Call下一行与第一次压栈的时候ESP相等)
标准函数头会指定新的栈低,或栈顶
push esp/ebp
mov xxx,esp/ebp
EBP+4n 表示函数的参数,n=0-->参数1BP
EBP-X 表示函数的局部变量(栈帧上)
stdcall是内平栈,区别与cdeclcall
fastcall是内平栈,但是参数1一般用ecx/cx/dl传递参数,参数2一般用edx/dx/dl
|
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|