用汇编语言给XP记事本添加“自动保存”功能 good
【文章标题】: 用汇编语言给XP记事本添加“自动保存”功能
【文章作者】: newjueqi
【作者邮箱】:zengjiansheng1@126.com
【作者QQ】:190678908
【使用工具】: OD, LordPE,eXeScope
【操作平台】: XP-SP2
【作者声明】: 本人平时一般的文字处理都是用记事本(用Word好像大材小用了),电脑自从拿去大修后有时候会莫名其妙的重启,弄得经常重写(本人常常忘记保存^-^),于是想给记事本增加类似于Word的自动保存功能,以图个方便。失误之处敬请诸位大侠赐教!
具体的思路:其实自动保存功能就是程序隔一段时间保存一次,而记事本程序是自带了保存功能的,所以只要编程安装一个记时器,每隔一段时间模拟点击“保存菜单”,就能实现自动保存,最后退出时把记时器撤销。
首先,用eXeScope给记事本增加两个菜单项“自动保存”“关闭自动保存”,如图1所示:
图1
其中,“自动保存”的菜单ID是8 ,“关闭自动保存” 的菜单ID是13。
完成后的菜单选项如图2所示:
图2
本次修改要用到3个window API函数: SetTimer, KillTimer , SendMessageA, 这3个API没包括在记事本的输入表里,所以要用LordPE在输入表里增加这3个API。
用LordPE打开记事本程序,依次选择Direction->输入表的“…”按钮->点击右键->add import,出现如图3的界面,就可以在输入表里增加新的API
图3
完成后就新增了一个区段Slivana如图4,放的就是新的IID数据,如图4所示
图4
添加完新的API后又有一个新的问题了,那就是要确定新的API地址,这个在PEDIY的过程中是要自己解决的,而平时是编译器帮忙的。获得API地址有两个方法:
(1) 直接查看新增的IID数据,载入程序后在命令行打入d 1013000,如图5所示:
图5
从IAT与INT的对应关系可得
SetTimer的地址=[0101302C ]
MessageBoxA的地址=[ 01013030]
KillTimer的地址=[01013034 ]
(2) 在OD中,按Ctrl+N组合键,就能看到API地址的位置,如图6的红框部分所示
图6
由于PEDIY一般都是在默认的窗口过程前先处理我们定义的消息,所以接下来分析一下记事本程序的流程,看看记事本的窗口过程地址。众所周知,在一个标准的窗口程序中,必须要注册窗口类,函数原型如下:
ATON RegisterClassEx(CONST WNDCLASSEX *Ipwcx);
其中WNDCLASSEX *Ipwcx是个结构体指针,定义如下:
WNDCLASSEX STRUCT DWORD
cbSize DWORD ?
style DWORD ?
lpfnWndProc DWORD ?
cbClsExtra DWORD ?
cbWndExtra DWORD ?
hInstance DWORD ?
hIcon DWORD ?
hCursor DWORD ?
hbrBackground DWORD ?
lpszMenuName DWORD ?
lpszClassName DWORD ?
hIconSm DWORD ?
WNDCLASSEX ENDS
lpfnWndProc就是窗口过程的地址,所以我们只需要在RegisterClassEx下中断,就能知道窗口过程的地址,在OD中如图7所示:
图7
从图7可看到1003429就是系统默认的窗口过程的地址。
在开始写代码前我们先简单回顾一下的windows的窗口过程函数和一般函数调用的过程,因为我们在后面的实际编码过程中必须要对这两个方面的知识有一定的了解。
窗口过程的原型为
wondowPrco proc hwnd,uMsg, wParam, lParam
hwnd: 窗口的句柄,可通告CreateWindowEx函数的返回值获取
uMsg: 消息的标识,一般以WM开头
wParam, lParam: 消息的两个参数
当我们点击某个菜单后就产生了WM_COMMAND消息,对于菜单引发的的WM_COMMAND消息, lParam 的值为0,wParam的低16位是命令ID,高16位是通知码,菜单消息的通知码是0。
当调用一个_stdcall函数的时候,首先是函数的参数按从右到左的顺序入栈,然后是函数的返回地址入栈,一般函数调用的开始有“push ebp mov ebp,esp”这句,所以我们进入窗口过程后就能得到类似于图8的堆栈结构
图8
0006FDE0 /0006FE0C ; ebp的值
0006FDE4 |77D18734 ; 返回到 user32.77D18734,返回地址值
0006FDE8 |00100618 ;窗口的句柄
0006FDEC |00000111 ;WM_COMMAND的16进制值,可查阅WinUser.h文件获得
0006FDF0 |00000008 ;wParam,“自动保存”的菜单ID是8
0006FDF4 |00000000 ;lParam,
由此可知,[ebp+c]是消息的类型,[ebp+10]是wParam参数,获取菜单的
ID就需要知道wParam参数。
另外还有一个问题要解决,SetTimer和KillTimer这两个API函数的参数中必须要传入窗口句柄作为参数,但窗口句柄怎么找呢?我们知道,在用CreateWindowExW函数创建窗口后会返回一个窗口句柄,在OD里对CreateWindowExW下断点,中断后代码如图9:
图9
从红框部分可知,窗口句柄保存在地址[1009830]。
我们要模拟点击“保存”菜单,可以通过SendMessageW函数向窗口过程发送菜单消息,SendMessageW的原型如下:
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
参数:
hWnd就是窗口句柄,从上面分析可知,保存在[1009830]地址上。
Msg是要发送的消息类型,查阅WinUser.h文件可知,WM_COMMAND为0x111
wParam的低16位是命令ID,高16位是通知码,菜单消息的通知码是0,通过eXeScope可查知“保存”的菜单ID 为3,所以wParam参数为3。
lParam,对于菜单消息来说,为0。
接下来就是实际的代码,本人选择在0100874F处添加代码,所以要把图7红框部分的1003429改为0100874F。
下面是写入的代码
0100874F . 55 push ebp
01008750 . 8BEC mov ebp, esp
01008752 . 60 pushad
01008753 . 817D 0C 11010>cmp dword ptr [ebp+C], 111 ;先比较消息的类型,看是否WM_COMMAND, 如果是WM_COMMAND的话再检查wParam参数进一步确定是哪个菜单的消息
0100875A . 75 0C jnz short 01008768 ;如果不是WM_COMMAND消息的话就检查是否WM_TIMER或WM_CLOSE消息
0100875C . 837D 10 08 cmp dword ptr [ebp+10], 8 ;比较菜单的ID号,看是否“自动保存”的菜单ID
01008760 . 74 1C je short 0100877E ;不是的话就跳去检查其它的消息类型
01008762 . 837D 10 0D cmp dword ptr [ebp+10], 0D ;比较菜单的ID号,看是否“关闭自动保存”的菜单ID
01008766 . 74 48 je short 010087B0 ;不是的话就跳去检查其它的消息类型
01008768 > 817D 0C 13010>cmp dword ptr [ebp+C], 113 ;比较消息的类型是否是WM_TIMER消息,响应定时器消息
0100876F . 74 5F je short 010087D0 ;不是的话就跳去函数的结束清场工作
01008771 . 837D 0C 10 cmp dword ptr [ebp+C], 10 ;比较消息的类型是否是WM_CLOSE消息,闭关时要先撤销定时器
01008775 . 74 39 je short 010087B0 ;不是的话就跳去函数的结束清场工作
01008777 > 61 popad
01008778 . 5D pop ebp
01008779 .^ E9 ABACFFFF jmp 01003429 ;跳回原来记事本的消息循环
0100877E > C605 20890001>mov byte ptr [1008920], 1 ;标记已使用自动保存功能
01008785 . 6A 00 push 0 ; /Timerproc = NULL
01008787 . 68 60EA0000 push 0EA60 ; |Timeout = 60000. ms
0100878C . 6A 01 push 1 ; |TimerID = 1
0100878E . FF35 30980001 push dword ptr [1009830] ; |hWnd = [1009830],在CreateWindowExW后保存窗口句柄的地址
01008794 . FF15 2C300101 call dword ptr [<&user32.SetTimer>] ; /SetTimer
0100879A . 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
0100879C . 68 00DB0001 push 0100DB00 ; |Title = "Note"
010087A1 . 68 10DB0001 push 0100DB10 ; |Text = "AutoSave Start!"
010087A6 . 6A 00 push 0 ; |hOwner = NULL
010087A8 . FF15 30300101 call dword ptr [<&user32.MessageBoxA>>; /MessageBoxA ;提示已使用自动保存功能
010087AE .^ EB C7 jmp short 01008777 ;跳去函数结束清场
010087B0 > 803D 20890001>cmp byte ptr [1008920], 0 ;先比较是否已启动定时器
010087B7 .^ 74 BE je short 01008777 ;如果没启动定时器就跳去函数结束清场
010087B9 . C605 20890001>mov byte ptr [1008920], 0 ;把启动定时器的标记恢复
010087C0 . 6A 01 push 1 ; /TimerID = 1
010087C2 . FF35 30980001 push dword ptr [1009830] ; |hWnd,在CreateWindowExW后保存窗口句柄的地址
010087C8 . FF15 34300101 call dword ptr [<&user32.KillTimer>] ; /KillTimer,撤销定时器
010087CE .^ EB A7 jmp short 01008777 ;跳去函数结束清场
010087D0 > 6A 00 push 0 ; /lParam = 0
010087D2 . 6A 03 push 3 ; |wParam = 3 ,“保存”菜单的ID号
010087D4 . 68 11010000 push 111 ; |Message = WM_COMMAND
010087D9 . FF35 30980001 push dword ptr [1009830] ; |hWnd ,在CreateWindowExW后保存窗口句柄的地址
010087DF . FF15 40120001 call dword ptr [<&USER32.SendMessageW>; /SendMessageW ;发送点击菜单“保存”的信号给记事本窗口,实现保存功能。
010087E5 .^ EB 90 jmp short 01008777 ;跳去函数结束清场
下载修改好的记事本地址
http://download.csdn.NET/source/1109397
http://blog.csdn.net/newjueqi/article/details/3992084
用汇编语言给XP记事本添加“自动保存”功能 good的更多相关文章
- WebStorm 编辑器 关闭自动保存功能及添加*星星标记
WebStorm 关闭自动保存功能添加*星星标记为什么要关闭自动保存? 在前端项目工作当中,往往会采用自动化环境(Gulp.webpack等)当文本发生变化的时候就会自动编译代码.在we ...
- PyCharm 去掉自动保存功能
PyCharm 4.5.4 环境配置 1.去掉"自动保存功能" pycharm默认是自动保存的,习惯自己按 ctrl + s 的可以进行如下设置: 菜单File -> Set ...
- 第四十一篇-android studio 关闭自动保存功能
此方法不可用. 第一步:取消自动保存功能 File > Settings > Appearance & Behavior > System Settings > Syn ...
- Intellij IDEA 开启自动保存功能
IntelljJ IDEA关于文件自动保存功能主要有两种方式: 切换到其他应用时保存变化(默认使能) 设置路径:Settings >> Apperance & Behavior & ...
- 【工具】Sublime Text 自动保存功能
经常需要所以要频繁用到"ctrl+s"保存还是挺麻烦的,所以有的人需要用到失去焦点自动保存功能,这里简单记录下 1.点击"Preferences"里的设置-用户 ...
- 关于vscode自动跳转回车的解决方法(关闭vscode自动保存功能;可能和其他插件有冲突)
关于vscode自动跳转回车的解决方法(关闭vscode自动保存功能:可能和其他插件有冲突)
- 在Word中为标题样式添加自动编号功能
原文地址:http://blog.chinaunix.net/uid-16685753-id-2738270.html 摘要: 本文可以帮助你在Office 2007中为Word标题样式添加和设置自动 ...
- C#实体图片下载与批量下载(自动保存功能)
新工作,第一个小任务,制作一个点击下载图片的功能.并提供批量下载操作.图片是字节流的形式,存放在数据库中的. 为了避免直接从数据库中,下载失败,会在本地保存一份. 进行压缩的是SharpZip这个压缩 ...
- DynamicsCRM中的自动保存
DynamicsCRM的自动保存功能 在DynamicsCRM2013开始,引入了自动保存功能. 保存一条记录 在新建一条记录的时候, 你必须在左上角手动点击保存按钮.如下图: 当保存完后,会发现,左 ...
随机推荐
- C#7模范和实践
C# 7 中的模范和实践 原文地址:https://www.infoq.com/articles/Patterns-Practices-CSharp-7 关键点 遵循 .NET Framework ...
- 【22.70%】【codeforces 591C】 Median Smoothing
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- Android菜鸟的成长笔记(23)——获取网络和SIM卡信息
TelephonyManager是一个管理手机通话状态.电话网络信息的服务类,该类提供了大量的getXxx()方法来获取电话网络的相关信息.这些信息包括设备编号.软件版本.网络运营商代号.网络运营商名 ...
- WPF 渲染级别
原文:WPF 渲染级别 很少人会知道 WPF 也可以知道当前的显卡能支持的渲染级别. 根据显卡的不同,包括显存.纹理等的支持是否打到要求,指定渲染级别. 使用 System.Windows.Media ...
- C# 程序内的类数量对程序启动的影响
原文:C# 程序内的类数量对程序启动的影响 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.i ...
- Memory device control for self-refresh mode
To ensure that a memory device operates in self-refresh mode, the memory controller includes (1) a n ...
- C#将string转换为十六进制
/// <summary> /// 将string格公式为十六进制数据 /// </summary> /// <param ...
- MySQL于ON DUPLICATE KEY UPDATE采用
今天我们做的推断插入用途MySQL于ON DUPLICATE KEY UPDATE.现在,Mark下面! 假设你想做的事,再有就是在数据库中插入数据没有数据.如果有数据更新数据,然后你可以选择ON D ...
- NS2网络模拟(4)-吞吐率图
1: #NS2_有线部分\ForGnuplot.plot 2: 3: #gnuplot> 4: #set xtics 0, 1, 10 5: set grid 6: set xrange [0: ...
- ubuntu12.04单卡server(mentohust认证)再加上交换机做路由软件共享上网
最近成立了实验室的网络环境中,通过交换机连接的所有主机实验室.想要一个通过该server(单卡)做网关,使用mentohust认证外网,然后内网中的其它主机通过此网关来连接外网. 1.首先在serve ...