游戏辅助原理与制作01.扫雷-02菜单CALL

4.菜单CALL

CALL是汇编中的一个指令,CPU执行这条指令会执行2个动作:(1)压入EIP入栈 (2)跳转到后面的地址。跟RETN指令配合就实现了汇编中子程序的作用,通常我们说的写CALL就是调用游戏中已经存在的功能子程序。

CALL指令具体原理请参阅汇编语言相关书籍。

下面来看下,扫雷游戏中菜单CALL(初级、中级、高级、自定义),并使用代码注入器,注入汇编代码来模拟一次菜单选择的调用。

 

用OllyDBG打开并运行扫雷游戏,选择菜单“查看”->“窗口”

(窗口用于列出所有属于被调试程序窗口及其窗口相关的重要参数)

在打开的Windows窗口上鼠标右键->刷新

在窗口过程上右键->跟随ClassProc,跟随一下回调函数

OD窗口跳转到地址0x01001BC9处

当访问某一个菜单的时候,都会向窗口的回调函数发送一个WM_COMMAND消息。

根据这个条件,来设置一个条件断点。

 

在设置条件断点之前,假定参数为WinProc(hWnd, msg, wParam, lParam)

(为了能在消息上设置断点,OllyDbg 创建了一个名为“<WinProc>”的特殊条件记录断点)

设置后在地址0x01001BC9的注释处变为 “解码为<WinProc>”

 

在该位置上设置条件断点 WM_COMMAND==msg

条件断点是一个带有条件表达式的普通INT3断点。断点为红色。

 

此时,访问扫雷程序的菜单,将会在断点处断下来,根据OD中堆栈窗口

找到CALL及相关参数如下图所示:

可以通过这个消息来控制菜单(或直接调用这个0x01001BC9的这个CALL)

点击不同的菜单,获取相关数据如下:

 

初级

中级

高级

自定义

hWnd

001C01B4

   

msg

00000111

   

Notify

00000209

0000020A

0000020B

0000020C

hControl

00000000

   

备注:消息处理函数WindowProc的原型,见WindowsAPI函数原型一节。

 

代码注入器测试

先加载扫雷游戏,选择菜单-初级,以便于观察窗口的变化。

在代码注入器窗口中写入以下汇编代码后,点击“注入远程代码”按钮,可以看到扫雷窗口变为中级。

push 0

push 0000020A

push 00000111

push 001C01B4

CALL 0x01001BC9

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,以下是一个C语言实现的扫雷小游戏的简要介绍: 1. 创建一个自定义的头文件mine.h,其中包含扫雷程序所需的头文件、常量和所有函数的声明。 2. 创建主函数test.c,用自己喜欢的方式构建一个游戏的框架。 3. 在test.c中,可以使用以下函数来实现扫雷游戏的功能: - `initBoard()`:初始化游戏棋盘。 - `printBoard()`:打印游戏棋盘。 - `setMines()`:随***Square()`:揭开一个方格。 - `checkWin()`:检查是否获胜。 4. 在游戏框架中,可以使用循环来不断接收用户输入,并调用相应的函数来更新游戏状态,直到游戏结束。 以下是一个简单的示例代码: ```c // mine.h #ifndef MINE_H #define MINE_H #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 10 // 游戏棋盘大小 #define MINE_COUNT 10 // 地雷数量 void initBoard(char board[][SIZE]); void printBoard(char board[][SIZE]); void setMines(char board[][SIZE]); void setNumbers(char board[][SIZE]); void revealSquare(char board[][SIZE], int row, int col); int checkWin(char board[][SIZE]); #endif // test.c #include "mine.h" int main() { char board[SIZE][SIZE]; int row, col; srand(time(NULL)); initBoard(board); setMines(board); setNumbers(board); while (1) { printBoard(board); printf("Enter row and column (separated by space): "); scanf("%d %d", &row, &col); if (row < 0 || row >= SIZE || col < 0 || col >= SIZE) { printf("Invalid input. Please try again.\n"); continue; } revealSquare(board, row, col); if (checkWin(board)) { printf("Congratulations! You win!\n"); break; } } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值