【文章标题】: 给记事本加上透明窗体和置顶功能(通过扩展消息循环的方法)-入门级的东东
【软件名称】: 系统自带记事本
【软件大小】: 65.2KB
【下载地址】: X:\windows\notepad.exe
【加壳方式】: 无壳
【保护方式】: 无
【编写语言】: Microsoft Visual C++ 7.0
【使用工具】: OD,LordPE,ResHacker
【操作平台】: XP-Sp2
【软件介绍】: 系统自带记事本,小巧实用.
--------------------------------------------------------------------------------
【详细过程】
在开始本文时,说一下整体的思路。
整个过程的基本思想是在记事本的消息处理之前,先转到我们自己添加的消息处理函数处理相关的事件,处理完再转到原WndProc执行。自己添加的消息处理功能放在动态链接库(MyPePlug.dll)中。
说完了整体思路,下面我们分步来完成整个过程。
(1) 用ResHacker添加一个新的菜单:
POPUP "附加功能(&A)"
{
MENUITEM "透明(&T)", 118 //记住这个ID号(118),在下面的MyPePlug.cpp会用到
MENUITEM "置顶(&K)", 119 //记住这个ID号(119),在下面的MyPePlug.cpp会用到
}
(2) 用OD加载记事本,在命令行输入:bp RegisterClassExW (也可能是RegisterClassExA),然后F9运行程序.此时程序会断下.看堆栈框如下:
其中0006FDF0就是注册类的结构定义,在它上面点右键,再选择“堆栈窗口跟随”,此时在堆栈中查看,就成这样了:
其中01003429就是记事本的消息处理函数的地址了。记住这个地址,下面会用到。
然后按ALT+F9,看反汇编窗口,向上拉一段代码你会在反汇编窗口中看到下图的代码:
记住消息处理过程的地址01004539,等一下会回过头来修改这段代码。
(3)写一个自己的消息处理函数
/////////////////////////////////////////// MyPePlug.h ///////////////////////////////////////////////////////////
#ifdef MYPEPLUG
#else
#define MYPEPLUG extern "C" __declspec(dllimport)
#endif
MYPEPLUG void LoadPlug(const DWORD reversed,
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////// MyPePlug.cpp//////////////////////////////////////////////////////////////
#include <Windows.h>
#define MYPEPLUG extern "C" __declspec(dllexport)
#include "MyPePlug.h "
bool flag = true;
void MySetLayeredWindowAttributes(HWND hWnd)
{
SetWindowLong(hWnd,GWL_EXSTYLE,
GetWindowLong(hWnd,GWL_EXSTYLE)^0x80000);
HINSTANCE hInst = LoadLibrary("User32.DLL");
if(hInst)
{
typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
MYFUNC fun = NULL;
//取得SetLayeredWindowAttributes函数指针
fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
if(fun)fun(hWnd,0,128,2);
FreeLibrary(hInst);
}
}
void LoadPlug(const DWORD reversed, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg) {
case WM_COMMAND:
if(wParam == 118)//这是我自己通过资源添加的一个菜单的id
{
//由于我的vc++的sdk是老版本,所以没有SetLayeredWindowAttributes函数,如果你的sdk
//是新版本,就不用我这么麻烦了,你就可以直接调用SetLayeredWindowAttributes函数了
MySetLayeredWindowAttributes(hWnd);
}
else if(wParam == 119)
{
if(flag)
{
SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
flag=false;
}
else
{
SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
flag=true;
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
(4)编译上面的源文件,生成MyPePlug.dll,把生成的dll文件放在记事本的当前目录里。
(5)用LordPE把LoadPlug函数添加到记事本程序中。(详细过程看<<加密与解密>>第三版P513)
记住ThunkRVA项的值(00013038),下面会用到.
(6) 再次用OD加载记事本,然后Ctrl+G,在对话框中输入01003429(这是在第二步要你记住的值),来到01003429.如下图:
然后利用5个int3和mov edi,edi共7个字节,改写一个call指令:call dword ptr [1013018](共六个,后面不一个nop),这就是调用我们自己的消息处理函数.至于为什么是这样,你可以看看<<加密与解密>>第三版P513
(7)修改消息处理过程的地址,由前面的分析可以知道该地址是01004539。
再一次按Ctrl+G,在对话框中输入01004539,来到01004539处,把这处的代码“mov dword ptr [ebp-28], 1003429”改成“mov dword ptr [ebp-28], 01003424”。
(8)在OD的反汇编窗口点右键-->复制到可执行文件-->右键保存文件(全部)-->选择你要保存的文件名-->保存。
好了,就这样就成功的添加了你想要的功能了.
------------------------------------------------------------------------------------------
【 参考文章】
记事本功能增加方案(http://bbs.pediy.com/showthread.php?threadid=17376 )
<<加密与解密>>第三版 第19章 代码的二次开发
--------------------------------------------------------------------------------------
二〇〇八年八月五日
由于权限不够,图不能够上传,详细的内容请看附件
附件:http://www.live-share.com/files/341931/____________.doc.html
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课