信息来源:Pediy
文章作者:andy00
;===============================================修改说明===============================================
【软件名称】XP记事本(Notepad)
【下载地址】附件(附本文)
【应用平台】Win9x/NT/2000/XP
【软件大小】70K
【软件限制】未修改时,不能使用背景色,文字色,下划线,删除线。
【保护方式】--------
【修改者】andy00
【修改难度】1/10
【修改说明】只是为了熟悉逆向工程,所以使用静态分析。
【分析工具】Olldbg,计算器
【参考资料】MSDN
【软件简介】--------
;===============================================增加的功能分析=========================================
功能1使字体对话框显示颜色,下划线,删除线的选项
功能2在"查看"菜单下添加"背景色"菜单,点击能够选择颜色
功能3让编辑框使用文字颜色,文字下划线,文字删除线,背景颜色功能
;==========================================步骤1增加数据与代码区段===================================
用OLLDBG查看数据段,估计数据段的空闲字节数能够保存修改后生成的所有数据,此处选择从AE00到结束的空间来保存要用到的变量.添加代码需要比较大的空间,因此添加一个可执行区段(既然为了熟悉PE结构就手工添加),添加后在LordPE中验证添加成功:
SecNameVOffsetVSizeROffsetRSizeFlags
andy00130001000104001000E0000020
因此新加代码放到:13000-10400(RVA)
新加变量放到:0AE00-0AFFC(RVA)
;=========================================步骤2需增加的变量与代码分析==================================
;功能1使字体对话框显示颜色,下划线,删除线的选项
记事本使用API函数ChooseFont打开字体对话框,此函数只有一个参数,指向CHOOSEFONT结构体的指针,CHOOSEFONT结构体定义如下
typedefstruct{
DWORDlStructSize;
HWNDhwndOwner;
HDChDC;
LPLOGFONTlpLogFont;
INTiPointSize;
DWORDFlags;
COLORREFrgbColors;
LPARAMlCustData;
LPCFHOOKPROClpfnHook;
LPCTSTRlpTemplateName;
HINSTANCEhInstance;
LPTSTRlpszStyle;
WORDnFontType;
INTnSizeMin;
INTnSizeMax;
}CHOOSEFONT,*LPCHOOSEFONT;
成员说明:
rgbColors用来保存用户选择的文字颜色
Flags用来初始化字体对话框的各选项
因此:
1将用户选择的颜色rgbColors保存起来,放到AF94设为DWORD(COLOREF)crText
2记事本打开字体对话框时默认没有颜色的,下划线,删除线选项.要增加这些选项.只需要将Flags|CF_EFFECT,其中CF_EFFECT==0x100
;功能2在"查看"菜单下添加"背景色"菜单,点击能够选择颜色
直接用ResHack在"查看"菜单下添加一个菜单项"背景色(&B)",ID为1C
点击菜单打开对话框,需要处理WM_COMMAND消息,并在消息在调用API函数ChooseColor().WM_COMMAND消息定义如下
WM_COMMAND(==111)
WPARAMwParam
LPARAMlParam;
参数说明:
wParam对于菜单,低字代表菜单ID,高字为0
lParam对于菜单,为0
API函数ChooseColor打开颜色选择对话框,此函数只有一个参数,指向CHOOSECOLOR结构的指针其中CHOOSECOLOR结构定义如下
typedefstruct{
DWORDlStructSize;//+0
HWNDhwndOwner;//+4
HWNDhInstance;//+8
COLORREFrgbResult;//+C
COLORREF*lpCustColors;//+10
DWORDFlags;//+14
LPARAMlCustData;//+18
LPCCHOOKPROClpfnHook;//+1C
LPCTSTRlpTemplateName;//+20
}CHOOSECOLOR,*LPCHOOSECOLOR;
1结构体长度为24,选用空间AFA0-AFC0存放此结构,设为CHOOSECOLORcc
2此结构的一个成员lpCustColors指向一个COLORREF数组,此处用AE00开始的空间保存,设为COLORREFcrCustomColor[10]
3还需要一个变量用来保存用户选择的颜色,此处用AF98保存,设为COLORREFcrBkgnd;
;功能3将选择的字体颜色和背景颜色应用到编辑框上面
设置文字颜色和背景颜色需要处理编辑框的WM_CTLCOLOREDIT消息,消息定义如下:
WM_CTLCOLOREDIT(==133)
WPARAMwParam
LPARAMlParam;
参数说明
wParam编辑框的设备内容句柄.
lParam编辑框的窗口句柄
每个非Disable和非ReadOnly的编辑框都可以发送这个消息,但是因为这里只有一个编辑框,所以不需要判断.直接在消息中调用
SetTextColor(wParam,crText);设置文字颜色
SetBkColor(wParam,crBkgnd);设置背景颜色
此处需要一个画刷,颜色与背景色相同,返回给父窗口用来刷背景.将此画刷在AF9C,设为HBRUSHhBrBkgnd
;=========================================步骤3功能实现伪代码====================================
HWNDhEdit;;编辑框句柄,原程序中肯定已保存,因此暂不分配空间
COLORREFcrCustomColor[10];;AE00
COLORREFcrText;;AF94
CHOOSECOLORcc;;AFA0-AFC0
COLORREFcrBkgnd;;AF98
HBRUSHhBrBkgnd;;AF9C
LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
{
switch(message)
{
caseWM_COMMAND://WM_COMMAND=111
switch(LOWORD(wParam))
{
caseIDM_EDIT_CHOOSEFONT://"字体"菜单
......
CHOOSEFONT.Flags|=CF_EFFECT;//增加颜色,下划线,删除线选项
//..ChooseFont()
crText=CHOOSEFONT.rgbColor;//保存选择的颜色
break;
caseIDM_VIEW_CHOOSECOLOR://IDM_VIEW_CHOOSECOLOR==1C"背景色"菜单
cc.lStructSize=sizeof(cc);//+0
cc.hwndOwner=hEdit;//+4
cc.hInstance=0;//+8
cc.rgbResult=0x00ff00;//+C
cc.lpCustColors=crCustom;//+10
cc.Flags=CF_RGBINIT;//+14
cc.lCustData=0;//+18
cc.lpfnHook=0;//+1C
cc.lpTemplateName=0;//+20
if(ChooseColor(&cc)==TRUE)
{
DeleteObject(hBrBkgnd);//删除以前创建的,以免内存泄露
clBkgnd=cc.rgbResult;//保存背景色
hBrBkgnd=CreateSolidBrush(clBkgnd);//根据选择的颜色创建画刷
InvalidateRect(hEdit,NULL,TRUE);//强制更新
}
break;
default:
returnDefWindowProc(hWnd,message,wParam,lParam);
}
break;
caseWM_CTLCOLOREDIT:
SetTextColor((HDC)wParam,clText);//设置文字色
SetBkColor((HDC)wParam,clBkgnd);//设置背景色
return(LRESULT)hBrBkgnd;//返回画刷
caseWM_DESTROY:
DeleteObject(hBrBkgnd);//删除GDI对象,避免内存泄露
//....
PostQuitMessage(0);//原有代码,退出程序
break;
//case.......
//case.......
default:
returnDefWindowProc(hWnd,message,wParam,lParam);
}
return0;
}
;=========================================步骤4增加输入函数======================================
从步骤2,3分析可知,需要用到的API函数
ChooseColorW
CreateSolidBrush
SetTextColor
SetBkColor
DeleteObject
InvalidateRect
用LordPE查看记事本的输入表,已输入的函数:
DllNameFunName(函数名)ThunkRVA(调用偏移)
gdi32.dllDeleteObject1224
gdi32.dllInvalidateRect1068
输入其余函数(本来用手动输入,但是调用的时候总有问题,因此用LordPE输入)
DllNameFunName(函数名)ThunkRVA(调用偏移)
comdlg32.dllChooseColorW1401C
gdi32.dllCreateSolidBrush1405D
gdi32.dllSetTextColor14061
gdi32.dllSetBkColor14065
;=========================================步骤5修改记事本代码======================================
;====================增加对话框的颜色,下划线,删除线选项.====================
用OD打开记事本,查找调用ChooseFont,来到以下代码.
0100308A|.C785B4FDFFFF410>MOV[LOCAL.147],01000041;cf.Flags;
01003094|.89B5B8FDFFFFMOV[LOCAL.146],ESI;|cf.rgbColors
0100309A|.89B5BCFDFFFFMOV[LOCAL.145],ESI;|cf.lCustData
010030A0|.89B5C0FDFFFFMOV[LOCAL.144],ESI;|cf.lpfnHook
010030A6|.89B5C4FDFFFFMOV[LOCAL.143],ESI;|cf.lpTemplateName
010030AC|.89B5C8FDFFFFMOV[LOCAL.142],ESI;|cf.hInstance
010030B2|.89B5CCFDFFFFMOV[LOCAL.141],ESI;|cf.lpszStyle
010030B8|.66:C785D0FDFFFF>MOVWORDPTRSS:[EBP-230],2000;|cf.nFontType
010030C1|.89B5D4FDFFFFMOV[LOCAL.139],ESI;|cf.nSizeMin
010030C7|.89B5D8FDFFFFMOV[LOCAL.138],ESI;|cf.nSizeMax
010030CD|.FF1590110001CALLDWORDPTRDS:[<&USER32.ReleaseDC>];
010030D3|.8D85A0FDFFFFLEAEAX,[LOCAL.152];
010030D9|.50PUSHEAX;&cf参数入栈
010030DA|.FF15D0120001CALLDWORDPTRDS:[<&comdlg32.ChooseFontW>];\ChooseFont(&cf)
;................
;................
将pCHOOSEFONT的各成员分析出来,可知,Flags成员在SS:[EBP-24C],因此这里只需要将0100308A改为
;更改后的0100308A
0100308AC785B4FDFFFF410>MOVDWORDPTRSS:[EBP-24C],01000141;0100041|100
;变成0100141
保存更改到文件,运行更改后的文件,此时出现了颜色等效果选项,但是现在还不能起作用.如图

;====================保存选择的颜色到clText(RVA==AF94)========================
010030E0|.85C0TESTEAX,EAX
010030E2|.0F847F020000JE01003367
0101301FFF3584AB0001PUSHDWORDPTRDS:[100AB84];更新这一句跳到自己的保存代码
;0101301F更改为010030E8,多余字节用NOP填充
010030E8-E932FF0000JMP01013000;上一句更改后的代码
010030ED90NOP;多余字节用NOP填充
010030EE|.8B1D8C110001MOVEBX,DWORDPTRDS:[<&USER32.SetCursor>];自己的代码最后必须跳回此处.
;................
;................
;010030E8跳到此处,自己的代码
01013000FF3584AB0001PUSHDWORDPTRDS:[100AB84];还原0101301F被修改后的代码
01013006A3FCAF0001MOVDWORDPTRDS:[100AFFC],EAX;保存EAX现场
0101300B8B442428MOVEAX,DWORDPTRSS:[ESP+28];EAX=pCHOOSEFONT.rgbColor
;保存选择的颜色到EAX
0101300FA394AF0001MOVDWORDPTRDS:[100AF94],EAX;保存到crText(RVA==AF94)
01013014A1FCAF0001MOVEAX,DWORDPTRDS:[100AFFC];还原EAX
01013019-E9D000FFFFJMP010030EE;跳回原程序处
;====================在中处理"背景色"菜单(==1C)的WM_COMMAND(==111)消息======================
;首先用RegisterClass(Ex)函数定位WndProc(主窗口的消息处理函数)
RegisterClassEx只有一个参数WNDCLASSEX,此结构体定义如下
typedefstruct{
UINTcbSize;
UINTstyle;
WNDPROClpfnWndProc;
intcbClsExtra;
intcbWndExtra;
HINSTANCEhInstance;
HICONhIcon;
HCURSORhCursor;
HBRUSHhbrBackground;
LPCTSTRlpszMenuName;
LPCTSTRlpszClassName;
HICONhIconSm;
}WNDCLASSEX,*PWNDCLASSEX
一共12个成员,其中第3个成员就是窗口的消息处理函数.在堆栈中它们的顺序是反的,应该倒着数,也就是第10个成员
在OD中用RegisterClassEx函数找到以下初始化WNDCLASSEX结构体的代码
;RegisterClassEx注册窗口类
010044E2|.C745D030000000MOV[LOCAL.12],30;|成员cbSize=30
010044E9|.FF151C120001CALLDWORDPTRDS:[<&USER32.GetSystemMetrics>;\GetSystemMetrics
010044EF|.F7D8NEGEAX
010044F1|.1BC0SBBEAX,EAX
010044F3|.05017F0000ADDEAX,7F01
010044F8|.50PUSHEAX;/RsrcName=EAX
010044F9|.33FFXOREDI,EDI;|
010044FB|.57PUSHEDI;|hInst=NULL
010044FC|.FF15D8110001CALLDWORDPTRDS:[<&USER32.LoadCursorW>];\EAX=LoadCursorW(NULL,RsrcName);
01004502|.6A02PUSH2;/RsrcName=2.
01004504|.56PUSHESI;|hInst
01004505|.8945ECMOV[LOCAL.5],EAX;|hCursor=EAX;
01004508|.FF15EC110001CALLDWORDPTRDS:[<&USER32.LoadIconW>];\EAX=LoadIconW(hInst,RsrcName);
0100450E|.57PUSHEDI;/Options=>LR_DEFAULTCOLOR
0100450F|.6A10PUSH10;|Height=10(16.)
01004511|.6A10PUSH10;|Width=10(16.)
01004513|.6A01PUSH1;|Type=IMAGE_ICON
01004515|.6A02PUSH2;|ResourceName=2
01004517|.56PUSHESI;|hInst
01004518|.8945E8MOV[LOCAL.6],EAX;|成员hIcon(大图标)
0100451B|.FF15D4110001CALLDWORDPTRDS:[<&USER32.LoadImageW>];\LoadImageW
01004521|.8945FCMOV[LOCAL.1],EAX;成员hIconSm(小图标)
01004524|.8D45D0LEAEAX,[LOCAL.12]
01004527|.50PUSHEAX;/参数pWndClassEx入栈
01004528|.C745F401000000MOV[LOCAL.3],1;成员lpszMenuName;
0100452F|.8975E4MOV[LOCAL.7],ESI;|hInstance=hInst;
01004532|.C745F820900001MOV[LOCAL.2],01009020;成员lpszClassName="Notepad"
01004539|.C745D829340001MOV[LOCAL.10],01003429;|lpfnWndProc=01003429
;窗口处理函数01003429
01004540|.C745F006000000MOV[LOCAL.4],6;成员hbrBackground
01004547|.897DD4MOV[LOCAL.11],EDI;成员style
0100454A|.897DDCMOV[LOCAL.9],EDI;成员cbClsExtra;
0100454D|.897DE0MOV[LOCAL.8],EDI;|成员cbWndExtra;
01004550|.FF15D0110001CALLDWORDPTRDS:[<&USER32.RegisterClassExW>;\RegisterClassExW
;................
;................
由以上代码分析可知WNDPROC=01003429,来到函数WNDPROC
;WNDPROC
010034298BFFMOVEDI,EDI;
0100342B/.55PUSHEBP;ESP-4
0100342C|.8BECMOVEBP,ESP;EBP=ESP
0100342E|.51PUSHECX;ESP-4
0100342F|.51PUSHECX;ESP-4
01003430|.56PUSHESI;ESP-4
01003431|.8B750CMOVESI,DWORDPTRSS:[EBP+C];ESI=message
01003434|.83FE1CCMPESI,1C
01003437|.57PUSHEDI;ESP-4
01003438|.6A08PUSH8
0100343A|.5APOPEDX;EDX=8;
0100343B|.0F8741020000JA01003682;if(message>1C)goto01003682
;................;WM_COMAND==111>1C所以到01003682
;................
理一下堆栈,[EBP]=原EBP,[EBP+4]=返回地址,[EBP+8]=hWnd,[EBP+C]=message,[EBP+10]=wParam,[EBP+14]=lParam
;0100343B跳到此处
01003682|>\8B7D14MOVEDI,DWORDPTRSS:[EBP+14];EDI=lParam
01003685|.8BC6MOVEAX,ESI;EAX=message
01003687|.2D11010000SUBEAX,111;EAX-=111(=WM_COMMAND)
0100368C|.0F8435020000JE010038C7;if(eax==WM_COMMAND)goto010038C7
;................;到WM_COMMAND的处理过程
;................
;0100368C跳到此处
010038C7|>\3B3D38980001CMPEDI,DWORDPTRDS:[1009838];
010038CD|.754CJNZSHORT0100391B;
;................
;................
这里遇到一个条件转移,但是我们并不清楚,1009838里放着什么,如果点击了"背景色"菜单,这里是跳不是不跳呢?不清楚,所以我们必须弄清楚,这里DWORDPTRDS:[1009838],但是因为EDI=lParam,在WM_COMMAND中,对于菜单,lParam==0,对于控件,lParam=控件窗口句柄.因此DWORDPTRDS:[1009838]最有可能是一个句柄,在记事本程序中,要在代码中使用句柄的也许只有编辑框和主窗口了.而且,在主窗口的消息处理函数中,很少用lParm与hWnd比较的(几乎没有).所以这里假设它为编辑框的句柄.
为了确定,用CreateWindowEX函数找到创建编辑框的代码,有两个,其中一个包含了对地址DWORDPTRDS:[1009838]的访问如下
;................
;................
01004771|.FF15E0110001CALLDWORDPTRDS:[<&USER32.CreateWindowExW>>;\CreateWindowExW
01004777|.3BC3CMPEAX,EBX
01004779A338980001MOVDWORDPTRDS:[1009838],EAX;1009838=hEdit
;................
;................
很容易看出来,DWORDPTRDS:[1009838]保存的就是编辑框句柄hEdit(也可用查找的方法找到DWORDPTRDS:[1009838])的保存的什么.
回到010038C7继续分析,由于对于菜单,lParam为0,即EDI=0,所以EDI!=hEdit,程序将跳到0100391B继续执行.
010038C7|>\3B3D38980001CMPEDI,DWORDPTRDS:[1009838];lParam!=hEdit
010038CD|.754CJNZSHORT0100391B;点击"背景色"菜单,此处必跳
;................
;................
;010038CD跳到此处
0100391B|>\57PUSHEDI;/Arg3=lParam
0100391C|.FF7510PUSHDWORDPTRSS:[EBP+10];|Arg2=wParam
0100391F|.FF7508PUSHDWORDPTRSS:[EBP+8];|Arg1=hWnd
01003922|.E860F2FFFFCALL01002B87;\非编辑框的WM_COMMAND消息的处理函数
;................
;................
;01003922处调用此处,非编辑框的WM_COMMAND消息的处理函数01002B87(hWnd,wParam,lParam)
01002B87/$8BFFMOVEDI,EDI
01002B89|.55PUSHEBP;ESP-4
01002B8A|.8BECMOVEBP,ESP;EBP=ESP
;[EBP+4]=返回地址,[EBP+8]=hWnd
;[EBP+C]=wParam,[EBP+10]=lParam
01002B8C|.81EC60020000SUBESP,260;ESP-260;
01002B92|.A104960001MOVEAX,DWORDPTRDS:[1009604];
01002B97|.8B5508MOVEDX,DWORDPTRSS:[EBP+8];EDX=hWnd
01002B9A|.53PUSHEBX;ESP-4
01002B9B|.56PUSHESI;ESP-4
01002B9C|.57PUSHEDI;ESP-4
01002B9D|.8945FCMOVDWORDPTRSS:[EBP-4],EAX;localVar1=EAX
01002BA0|.33F6XORESI,ESI
01002BA2|.33C0XOREAX,EAX;EAX=ESI=0;
01002BA4|.66:89B5F4FDFFFFMOVWORDPTRSS:[EBP-20C],SI;localVar83=0
01002BAB|.B981000000MOVECX,81;ECX=81;
01002BB0|.8DBDF6FDFFFFLEAEDI,DWORDPTRSS:[EBP-20A];EDI=&localVar82
01002BB6|.F3:ABREPSTOSD
01002BB8|.66:ABSTOSW
01002BBA|.0FB77D0CMOVZXEDI,WORDPTRSS:[EBP+C];EDI=wParam取得控件/菜单ID到EDI
01002BBE|.83FF40CMPEDI,40;这里开始比较控件/菜单ID了,
01002BC1|.8995F0FDFFFFMOVDWORDPTRSS:[EBP-210],EDX;所以更改此处跳到自己的代码
01002BC7|.0F8FF9060000JG010032C6;自己的代码最后必须跳回此处
;................
;................
;01002BBE与01002BC1改为,多余字节以NOP填充
01002BBE.-E95B040100JMP0101301E;跳到自己的代码处
01002BC390NOP
01002BC490NOP
01002BC590NOP
01002BC690NOP;多余字节以NOP填充
;01002BBE跳到此处,自己的代码,用于响应"背景色"菜单,弹出颜色对话框,保存颜色,创建画刷
0101301E83FF1CCMPEDI,1C;比较控件ID
010130210F85A3000000JNZ010130CA;如果wParam!=1C(不是"背景色"菜单)
0101302790NOP;则跳到010130CA,让给程序处理
01013028A138980001MOVEAX,DWORDPTRDS:[1009838];EAX=hEdit
;以下几行初始化CHOOSECOLOR各成员
0101302DA3A4AF0001MOVDWORDPTRDS:[100AFA4],EAX;/cc.hwndOwner=hEdit
01013032C705A0AF000124000>MOVDWORDPTRDS:[100AFA0],24;|cc.lStructSize=24
0101303CC705A8AF000100000>MOVDWORDPTRDS:[100AFA8],0;|cc.hInstance=NULL
01013046C705ACAF00010000F>MOVDWORDPTRDS:[100AFAC],0FF0000;|cc.rgbResult=蓝色
01013050C705B0AF000100AE0>MOVDWORDPTRDS:[100AFB0],0100AE00;|cc.lpCustColors=0100AE00
0101305AC705B4AF000101000>MOVDWORDPTRDS:[100AFB4],1;|cc.Flags=CC_RGBINIT
01013064C705B8AF000100000>MOVDWORDPTRDS:[100AFB8],0;|cc.lCustData=0
0101306EC705BCAF000100000>MOVDWORDPTRDS:[100AFBC],0;|cc.lpfnHook=0
01013078C705C0AF000100000>MOVDWORDPTRDS:[100AFC0],0;|cc.lpTemplateName=NULL
0101308250PUSHEAX;|保存EAX现场
0101308368A0AF0001PUSH0100AFA0;|参数&cc入栈
01013088FF151C400101CALLDWORDPTRDS:[<&comdlg32.ChooseColorW>];\ChooseColorW(&cc)
0101308E09C0OREAX,EAX
010130907437JESHORT010130C9;if(EAX==0)说明用户取消或出错
;则不保存选择的颜色,交给程序处理
01013092A1ACAF0001MOVEAX,DWORDPTRDS:[100AFAC]
01013097A398AF0001MOVDWORDPTRDS:[100AF98],EAX;crBkgnd(RVA=AF98)=cc.rgbResult
;保存颜色到crBkgnd
0101309CFF359CAF0001PUSHDWORDPTRDS:[100AF9C];/参数hBrBkgnd(RVA==AF9C)画刷句柄入栈
010130A2FF1568100001CALLDWORDPTRDS:[<&GDI32.DeleteObject>];\DeleteObject(hBrBkgnd)
;删除原画刷防止内存泄漏
010130A8FF3598AF0001PUSHDWORDPTRDS:[100AF98];/参数crBkgnd入栈
010130AEFF155D400101CALLDWORDPTRDS:[101405D];\EAX=CreateSolidBrush(crBkgnd)
;根据选择的颜色创建画刷
010130B4A39CAF0001MOVDWORDPTRDS:[100AF9C],EAX;画刷句柄保存到hBrBkgnd(RVA==AF9C)
010130B96A01PUSH1;/
010130BB6A00PUSH0;|
010130BDFF3538980001PUSHDWORDPTRDS:[1009838];|参数hEdit入栈
010130C3FF1524120001CALLDWORDPTRDS:[<&USER32.InvalidateRect>];\InvalidateRect(hEdit,NULL,TRUE)
;强制更新编辑框使画刷与背景色生效
010130C958POPEAX;还原EAX
010130CA83FF40CMPEDI,40;原来的代码
010130CD8995F0FDFFFFMOVDWORDPTRSS:[EBP-210],EDX;原来的代码
010130D3-E9EBFAFEFFJMP01002BC3;跳回01002BC7继续执行.
;====================处理WM_DESTORY(==2)删除画刷对象以免内存泄漏======================
;WNDPROC
010034298BFFMOVEDI,EDI
0100342B.55PUSHEBP
0100342C.8BECMOVEBP,ESP
0100342E.51PUSHECX
0100342F.51PUSHECX
01003430.56PUSHESI
01003431.8B750CMOVESI,DWORDPTRSS:[EBP+C];ESI=message;
01003434.-E9A7FC0000JMP010130E0
0100343990NOP
0100343A.5APOPEDX
0100343B.0F8741020000JA01003682
01003441.0F84B7010000JE010035FE
01003447.3BF2CMPESI,EDX
01003449.0F87ED000000JA0100353C
0100344F.0F84DB000000JE01003530
01003455.8BC6MOVEAX,ESI;EAX=message;
01003457.48DECEAX;message--;
01003458.48DECEAX;message--;
01003459.0F84C7000000JE01003526;if(message==WM_DESTORY)goto1003526
;................
;................
01003526>\6A00PUSH0;修改此句跳到自己的代码
01003528.FF15F4110001CALLDWORDPTRDS:[010011F4];此句被修改
0100352E.^EB8DJMPSHORT010034BD;此句被修改
;................
;................
;修改后的代码01003526-01003528-0100352E,多余字节用NOP填充
01003526>-\E925FC0000JMP01013150;Case2ofswitch01003457
0100352B90NOP
0100352C90NOP
0100352D90NOP
0100352E90NOP
0100352F90NOP
01003530>FF7514PUSHDWORDPTRSS:[EBP+14]
;................
;................
;自己的代码,删除画刷句柄hBrBkgdn(RVA==AF9C)
01013150FF359CAF0001PUSHDWORDPTRDS:[100AF9C];hBrBkgnd(RVA==AF9C)入栈
01013156FF1568100001CALLDWORDPTRDS:[<&GDI32.DeleteObject>];DeleteObject(hBrBkgnd)删除画刷
;释放内存,防止泄漏
0101315C6A00PUSH0;原来的代码
0101315EFF15F4110001CALLDWORDPTRDS:[<&USER32.PostQuitMessage>>;USER32.PostQuitMessage
01013164-E95403FFFFJMP010034BD;原来的代码
保存更改到文件,然后运行修改过的程序,点击"背景色"菜单,就能弹出颜色对话框了,但是现在选择的颜色还不能起作用,因为要给编辑框设背景色或者文字色,必须处理WM_CTLCOLOREDIT消息.如图

;====================处理WM_CTLCOLOREDIT(==133)消息设置颜色画刷======================
因为程序原来是不处理WM_CTLCOLOREDIT的消息的,所以处理WM_CTLCOLOREDIT消息的过程与WM_COMMND及WM_DESTORY稍有不同,必须自己添加判断代码,再次来到WNDPROC:
;WNDPROC
010034298BFFMOVEDI,EDI;
0100342B/.55PUSHEBP;ESP-4
0100342C|.8BECMOVEBP,ESP;EBP=ESP
0100342E|.51PUSHECX;ESP-4
0100342F|.51PUSHECX;ESP-4
01003430|.56PUSHESI;ESP-4
01003431|.8B750CMOVESI,DWORDPTRSS:[EBP+C];ESI=message
01003434|.83FE1CCMPESI,1C;=====修改这里跳到自己的代码====
01003437|.57PUSHEDI;=======此句被修改ESP-4=========
01003438|.6A08PUSH8;=======此句被修改==============
0100343A|.5APOPEDX;EDX=8;;如果不是WM_CTLCOLOREDIT消息
;................;则最后必须跳回到此处
;................;如果是WM_CTLCOLOREDIT消息则最后
;必须返回函数值,结束WNDPROC,
;而不再顺到这里,原因请见伪代码
;修改后的01003434-01003437-01003438,多余字节以NOP填充
01003434.-E9A7FC0000JMP010130E0
0100343990NOP
;................
;................
;01003434跳到此处,自己的代码,判断及处理WM_CTLCOLOREDIT消息
010130E081FE33010000CMPESI,133
010130E6752BJNZSHORT01013113;假如不是WM_CTLCOLOREDIT消息则
;自己不处理,跳回原处,交给程序处理
010130E850PUSHEAX;保存EAX现场
010130E9FF3594AF0001PUSHDWORDPTRDS:[100AF94];/参数crText(RVA==AF94)入栈
010130EFFF7510PUSHDWORDPTRSS:[EBP+10];|参数wParam入栈
010130F2FF1561400101CALLDWORDPTRDS:[1014061];\SetTextColor(wParam,crText)
010130F8FF3598AF0001PUSHDWORDPTRDS:[100AF98];/参数crBkgnd(RVA==AF98)入栈
010130FEFF7510PUSHDWORDPTRSS:[EBP+10];|参数wParam入栈
01013101FF1565400101CALLDWORDPTRDS:[1014065];\SetBkColor(wParam,crBkgnd)
0101310758POPEAX;恢复EAX
01013108A19CAF0001MOVEAX,DWORDPTRDS:[100AF9C];EAX=hBrBkgnd(RVA==AF9C)准备返回画刷
0101310D5FPOPEDI
0101310E5EPOPESI
0101310FC9LEAVE
01013110C21000RET10;平衡堆栈并返回画刷(eax),结束WNDPROC
0101311383FE1CCMPESI,1C;原来的代码
0101311657PUSHEDI;原来的代码
010131176A08PUSH8;原来的代码
01013119-E91C03FFFFJMP0100343A;0100343A
保存修改到文件,运行修改过的文件,现在可以设置文字色,背景色了,并且设置可以反应到编辑框了,但是程序刚启动的时候,默认的背景色和文字色都是黑色的,并且在有文字行才有背景色,显示不正常,并且看不到文字
默认背景色是黑色是因为,程序启动的时候开始WM_CTLCOLOREDIT消息中的SetBkColor和SetTextColor都在起作用了,但是这时候,crText(RVA==AF94)和crBkgnd(RVA==AF98)在内存中的值都是00000000,改变它们就能改变默认背景色和文字色.
在有文字的行才有背景色是因为,此时的hBrBkgnd(RVA==AF9C)是个无效的画刷句柄,程序不能用此画刷画背景,导致显示不正常.
所以也需要初始化hBrBkgnd.
初始化他们的最好地方是编辑框刚被创建还没有显示的时候.再次来到创建编辑框的地方
;创建编辑框:
01004765|.50PUSHEAX;|Style
01004766|.56PUSHESI;|WindowName
01004767|.6894170001PUSH01001794;|Class="Edit"
0100476C|.6800020000PUSH200;|ExtStyle=WS_EX_CLIENTEDGE
01004771|.FF15E0110001CALLDWORDPTRDS:[<&USER32.CreateWindowExW>];\CreateWindowExW
01004777|.3BC3CMPEAX,EBX;修改此然跳到自己的代码
01004779|.A338980001MOVDWORDPTRDS:[1009838],EAX;改这一句跳到0101311E
0100477E|.0F842A020000JE010049AE;最后必须返回到这里
;................
;................
;修改后的代码01004777-01004779修改为
01004777.90NOP
01004778.90NOP
01004779-E9A1E90000JMP0101311E;跳到自己的代码0101311E
;自己的代码初始化crText,crBkgnd,hBrBkgnd
0101311EA338980001MOVDWORDPTRDS:[1009838],EAX;原来的代码
0101312368FFFFFF00PUSH0FFFFFF;RGB(FF,FF,FF)白色入栈
01013128FF155D400101CALLDWORDPTRDS:[101405D];CreateSolidBrush创建白色画刷
0101312EA39CAF0001MOVDWORDPTRDS:[100AF9C],EAX;画刷句柄保存到hBrBkgnd(RVA==AF9C)
01013133C70598AF0001FFFFF>MOVDWORDPTRDS:[100AF98],0FFFFFF;crBkgnd(RVA==AF98)=白色
0101313DA138980001MOVEAX,DWORDPTRDS:[1009838];原来的代码
010131423BC3CMPEAX,EBX;原来的代码
01013144-E93516FFFFJMP0100477E;跳回原处交给程序处理
最后的效果:

=======THEEND!=========
;===============================================QQ:41086722=========================================
欢迎交流
有两个问题
196.6K的BMP图片无法上传....
2新增加的代码区段和原来的代码段都修改了代码如何一次性保存所有更改到可执行文件???