用汇编语言编写内存修改器

Windows汇编程序
在编写不使用图形界面(或使用简单的图形界面)的32 位Windows应用程序时,使用汇编语言会使程序简单、快捷,并且这类程序生成的可执行文件比较小(一般不超过10K),执行速度快,无需安装即可运行。在Windows环境中,汇编语言的编程方式与C语言类似,要调用Windows API。在汇编语言中调用API函数使用call 指令,并且函数的参数使用Push指令先入堆栈,这步工作在masm32v6中可以由invoke 宏指令自动完成。函数的返回值由eax寄存器返回。
例如MessageBox函数的声明如下:
int MessageBox(HWND h1 , LPCTSTR lp1 , LPCTSTR lp2 , UINT u1 );
则其汇编调用如下:
invoke MessageBox,h1,lp1,lp2,u1
其中参数入栈、检查等工作,由invoke宏指令自动完成。
一个简单的Win 32程序如下:
.386
.model flat, stdcall ;使用32位平坦存储模式
option casemap :none ;区分大小写字母
include /MASM32/INCLUDE/windows.inc
include /MASM32/INCLUDE/kernel32.inc
includelib /MASM32/LIB/kernel32.lib
.code
start:
invoke ExitProcess,0
end start
以上程序与一个DOS下的汇编程序类似,其中语句“invoke ExitProcess,0”相当于DOS下的 int 20H或mov ah,04cH/int 21h,即结束程序并返回。这个框架程序并没有完成什么具体的功能,程序运行后马上返回,并在其运行期间不生成窗口。
实现内存修改器
对上述程序添加语句,就可以使其成为一个真正能用的内存修改器。以修改Windows附件中计算器程序为例,如要修改计算器程序虚拟内存地址40b181H的值为1234H(在运行修改器程序进行修改前,应先运行计算器程序)。
首先为程序添加一个数据段。在 .code 前加上以下语句:
.data
ProcessId dd ? ;进程ID
windowname db “计算器”,0 ;窗口程序名
writeaddr dd 40b181H ;写入的地址
writedate dd 1234H ;写入的数据
然后在start: 后添加以下语句:
invoke FindWindow,NULL,addr windowname
invoke GetWindowThreadProcessId,eax,addr
ProcessId
invoke OpenProcess,PROCESS_ALL_ACCESS, FALSE, ProcessId
invoke WriteProcessMemory,eax,writeaddr,
addr writedate, 4, 0
invoke ExitProcess,0
在上述代码中,首先使用 FindWindow 函数取得目标窗口的句柄,其中addr windowname是目标窗口名称(字符串)在内存中的开始地址,字符串以0结束。窗口句柄由eax返回。如果eax=0表示函数出错,其他值表示取得的目标窗口句柄。使用GetWindowThreadProcessId 函数,通过窗口句柄eax取得进程标识符ProcessId。同样,如果函数返回eax=0表示函数出错,其他值表示成功取得ProcessId。利用OpenProcess 函数,从进程标识符ProcessId得到计算器程序的进程句柄。其中PROCESS_ALL_ACCESS表示拥有所有权限,参数FALSE是固定的。同样,句柄由eax返回,如果eax=0表示函数出错,其他值表示取得目标进程句柄。
然后用WriteProcessMemory 函数修改内存,调用方法如下:
invoke WriteProcessMemory,eax,writeaddr, addr writedate, 4, 0
其参数的含义如下:
●eax:从OpenProcess 函数中取得的目标进程的句柄;
●writeaddr :计算器程序的虚拟内存中将要被修改的地址;
●addr writedate :将要写入上述地址的数据开始的地址;
●4 :希望写入addr writedate地址的字节数;
●0 :函数执行返回后,写入目标地址的实际字节数,能被用来确认函数实际的执行情况,这里用0填入。
该函数返回eax,如果eax=0表示函数出错。
最后调用ExitProcess函数结束程序,返回0值给操作系统。
编辑好上述代码存盘后,用masm32v6中的编译、连接命令生成执行文件。该执行文件可以在Windows 95/98/Me中执行,并完成内存修改。由于Windows NT的内存管理方式与Windows 98等不同,所以在Windows NT中该程序可以执行,但不能修改内存。
编译:
ML /c /coff 文件名.asm
连接:
LINK /SUBSYSTEM:WINDOWS 文件名.obj
内存修改器的改进
上述程序虽然可以执行,但是缺乏交互性和通用性,这可以从以下两个方面进行改进。
1.改进程序执行后无论是否修改了内存或者产生了其他错误,都没有任何提示的问题。要增强交互性,可对每个函数执行后返回的eax值作检查,若eax=0,则产生对话框向用户提示错误,并返回操作系统。
为了能产生出错提示,在数据段增加以下定义:
text1 db “提示!”,0 ;对话框的标题
text2 db “目标程序未运行!“,0
text3 db “不能获得目标进程句柄!”,0
text4 db “不能打开目标进程!”,0
text5 db “未能修改目标内存!”,0
text6 db “命令格式:程序名 窗口名 欲修改地址 新值”,0
使用MessageBox函数弹出对话框,向用户提示出错信息:
invoke FindWindow,NULL,windowname
.if eax==0
 invoke MessageBox,NULL,addr text2,addr text1,MB_OK
invoke ExitProcess,1
.endif
2.改进缺乏通用性的问题。以上修改器程序若要修改另外一个窗口程序的内存,则需对源程序数据段中的windowname、writeaddr、writedate进行修改,重新赋予初值,以适应另一窗口程序,然后重新编译、连接才能实现。如果内存修改器带有参数,就可提高程序的通用性。格式如下:
执行程序名 参数1 参数2 参数3
执行程序名 窗口程序名 要修改的地址 新值
要获得命令行参数,可以在数据段定义一个变量,用来存放命令行参数在虚拟内存中存放的开始地址。在代码段的开始(start:标识符后)插入以下语句获得命令行参数的首址。
invoke GetCommandLine
mov CommandLine, eax
获得命令行参数首址后,对命令行参数进行分析,分离出参数1、参数2、参数3,然后将分离出的参数送到数据段的相应变量中即可。
小结
本文只是简单介绍了用汇编语言编写Windows程序的方法。一个完整的内存修改器应包含内存搜索功能和尽可能高的搜索效率和准确度。内存搜索功能可以利用具有读内存功能的API函数ReadProcessMemory,通过一个循环结构完成。但提高搜索效率和准确度需要丰富的编程经验和技巧才能实现。
阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
××××××××××××××××××××××××××× × 《Windows环境下32位汇编语言程序设计》 × × 附书代码说明 × ××××××××××××××××××××××××××× 1. 编译器和链接器 本附书代码全部采用 MASM 格式编写,推荐使用 MASM32 软 件包作为编译环境,MASM32 软件包可以在以下地址下载: MASM32官方站点: http://www.masm32.com 安装及开发的操作系统建议采用32位的Windows 7,在64位操作系统 上安装 MASM32 软件包,安装生成的Lib文件可能不兼容。 安装完成以后请将本光盘根目录下的环境设置批处理文件Var.bat 拷贝到 Masm32\bin 目录下,并根据 MASM32 的安装位置编辑修改 Var.bat 文件中的相关目录名称。 2. 代码维护工具 每个例子都包括了描述编译、链接方法的 makefile 文件, 使用 nmake 工具可以自动根据此文件进行编译链接,nmake 工 具可以从 Visual C++ 的 bin 目录中找到,也可以从作者的网 站中下载。 3. 编译环境和编译方法 建议使用命令行方式进行编译,以编译 Chapter02\Test 目录中 Test.asm 为例,步骤是: I. 打开一个“命令提示符”窗口。 II. 进入环境设置批处理文件 Var.bat 所在目录并执行 它,以后就可以使用这个“命令提示符”窗口编译 文件了。 x: cd \masm32\bin var III. 进入源代码目录: cd \chapter02\test IV. 使用 nmake 工具进行编译链接: nmake V. 执行编译好的可执行文件。 如果需要对源代码进行修改,不必关闭“命令提示符”窗口, 只要切换到编辑器窗口,在修改 *.asm 文件后重复进行第 IV 和 第 V 步骤即可。 # 特别注意:将光盘中的代码拷贝到硬盘后,必须将文件的只读属性去除! 4. 本光盘所包含目录的说明 根目录下的 *.pdf ;附录A、B、C的电子版文档 Chapter02\Test ;测试编译环境 Chapter03\HelloWorld ;Hello World Chapter04\FirstWindow ;用Win32汇编写第一个窗口 Chapter04\FirstWindow-1 ;用Win32汇编写第一个窗口 Chapter04\SendMessage ;窗口间的消息互发 Chapter04\SendMessage-1 ;窗口间的消息互发 Chapter05\Menu ;使用资源 - 使用菜单 Chapter05\Icon ;使用资源 - 使用图标 Chapter05\Dialog ;使用资源 - 使用对话框 Chapter05\Listbox ;使用资源 - 使用列表框 Chapter05\Control ;使用资源 - 使用子窗口控件 Chapter05\ShowVersionInfo ;使用资源 - 显示版本信息资源的程序 Chapter05\VersionInfo ;使用资源 - 使用版本信息资源 Chapter06\Timer ;定时器的使用 Chapter07\DcCopy ;在两个窗口的 DC 间互相拷贝屏幕 Chapter07\Clock ;模拟时钟程序 Chapter07\BmpClock ;用 Bitmap 图片做背景的模拟时钟程序 Chapter07\TestObject ;一些常见的绘图操作 Chapter08\CommDlg ;使用通用对话框 Chapter09\Toolbar ;使用工具栏 Chapter09\StatusBar ;使用状态栏 Chapter09\Richedit ;使用丰富编辑控件 Chapter09\Wordpad ;一个完整的文本编辑器例子 Chapter09\SubClass ;窗口的子类化例子 Chapter09\SuperClass ;窗口的超类化例子 Chapter10\MemInfo ;显示当前内存的使用情况 Chapter10\FindFile ;全盘查找文件的例子 Chapter10\FormatText ;文件读写例子 Chapter10\FormatText\FileMap ;使用内存映射文件进行文件读写的例子 Chapter10\MMFShare ;使用内存映射文件进行进程间数据共享 Chapter11\Dll\Dll ;最简单的动态链接库例子 - 编写 DLL Chapter11\Dll\MASM Sample ;最简单的动态链接库例子 - 使用 DLL Chapter11\Dll\VC++ Sample ;最简单的动态链接库例子 - 在VC++中使用汇编编写的DLL Chapter11\KeyHook ;Windows 钩子的例子 - 监听键盘动作 Chapter11\RecHook ;Windows 日志记录钩子的例子 - 监听键盘动作 Chapter12\Counter ;有问题的程序 - 一个计数程序 Chapter12\Thread ;用多线程的方式解决上一个程序的问题 Chapter12\Event ;使用事件对象 Chapter12\ThreadSynErr ;一个存在同步问题的多线程程序 Chapter12\ThreadSyn\UseCriticalSection ;使用临界区对象解决多线程同步问题 Chapter12\ThreadSyn\UseEvent ;使用事件对象解决多线程同步问题 Chapter12\ThreadSyn\UseMutex ;使用互斥对象解决多线程同步问题 Chapter12\ThreadSyn\UseSemaphore ;使用信号灯对象解决多线程同步问题 Chapter13\CmdLine ;使用命令行参数 Chapter13\Process ;创建进程的例子 Chapter13\ProcessList ;显示系统中运行的进程列表 Chapter13\Patch1 ;一个内存补丁程序 Chapter13\Patch2 ;一个内存补丁程序 Chapter13\Patch3 ;一个内存补丁程序 Chapter13\HideProcess9x ;Windows 9x下的进程隐藏 Chapter13\RemoteThreadDll ;用 DLL 注入的方法实现远程进程 Chapter13\RemoteThread ;不依靠任何外部文件实现远程进程 Chapter14\TopHandler ;使用筛选器处理异常 Chapter14\SEH01 ;最基本结构化异常处理例子 Chapter14\SEH02 ;改进后的结构化异常处理例子 Chapter14\Unwind ;异常处理中的展开操作例子 Chapter15\Ini ;使用 INI 文件 Chapter15\Reg ;操作注册表的例子 Chapter15\Associate ;操作注册表实现文件关联 Chapter16\TcpEcho ;实现 TCP 服务器端的简单例子 Chapter16\Chat-TCP ;用 TCP 协议实现的聊天室例子 Chapter17\PeInfo ;查看 PE 文件的基本信息 Chapter17\Import ;查看 PE 文件的导入表 Chapter17\Export ;查看 PE 文件的导出表 Chapter17\Resource ;查看 PE 文件的资源列表 Chapter17\Reloc ;查看 PE 文件的重定位信息 Chapter17\NoImport ;不使用导入表调用 API 函数 Chapter17\AddCode ;在 PE 文件上附加可执行代码的例子 Chapter18\OdbcSample ;用ODBC操作数据库的例子 Appendix A\EchoLine ;控制台输入输出的例子 Appendix B\MsgWindow01 ;消息机制试验 1 Appendix B\MsgWindow02 ;消息机制试验 2 Appendix B\MsgWindow03 ;消息机制试验 3 Appendix B\MsgWindow04 ;消息机制试验 4 Appendix C\BrowseFolder ;浏览目录对话框 6. 联系作者 虽然本书中所有的例子代码都已经在32位的Windows 98、Windows 2000、 Windows XP、Windows Vista和Windows 7下测试通过,但也有存在Bug的可能,如果 发现代码存在错误或者有其它问题,请告知作者,联系方法: E-mail:luoyunbin@hotmail.com 感谢您的支持! 作者:罗云彬

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heyongzhou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值