我来我网
https://5come5.cn
 
您尚未 登录  注册 | 菠菜 | 软件站 | 音乐站 | 邮箱1 | 邮箱2 | 风格选择 | 更多 » 
 

本页主题: [玩玩]Crackme & Reverseme & Overflowme 显示签名 | 打印 | 加为IE收藏 | 收藏主题 | 上一主题 | 下一主题

yinx



性别: 帅哥 状态: 该用户目前不在线
等级: 人见人爱
家族: 丢丢
发贴: 2333
威望: 0
浮云: 1260
在线等级:
注册时间: 2006-09-15
最后登陆: 2009-05-11

5come5帮你背单词 [ grace /greis/ a. 优美,雅致,(pl.)风度,魅力 ]


[玩玩]Crackme & Reverseme & Overflowme

【文章标题】: bxm的第6个CrackMe[屏蔽]分析
【文章作者】: netwind
【作者QQ号】: 群:8601428
【下载地址】: http://bbs.pediy.com/attachment.php?s=&attachmentid=4612
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
od载入,查找-》所有参考文本串-》双击“good job!"
可以看到如下代码:
004016F0   . 83EC 60     sub   esp, 60
004016F3   . 53         push   ebx
004016F4   . 55         push   ebp
004016F5   . BB 01000000   mov   ebx, 1
004016FA   . 57         push   edi
004016FB   . 8BE9       mov   ebp, ecx
004016FD   . 53         push   ebx
004016FE   . E8 B5780100   call   00418FB8
00401703   . 8D4424 0C   lea   eax, [esp+C]
00401707   . 6A 14       push   14             ; /Arg3 = 00000014
00401709   . 50         push   eax             ; |Arg2
0040170A   . 68 E9030000   push   3E9             ; |Arg1 = 000003E9
0040170F   . 8BCD       mov   ecx, ebp         ; |
00401711   . E8 1F820100   call   00419935         ; \crackme_.00419935
00401716   . 83F8 03     cmp   eax, 3           ; 用户名长度需大于3
00401719   . 0F8C A7000000 jl     004017C6
0040171F   . 8D4C24 48   lea   ecx, [esp+48]
00401723   . 6A 21       push   21             ; /Arg3 = 00000021
00401725   . 51         push   ecx             ; |Arg2
00401726   . 68 EA030000   push   3EA             ; |Arg1 = 000003EA
0040172B   . 8BCD       mov   ecx, ebp         ; |
0040172D   . E8 03820100   call   00419935         ; \crackme_.00419935
00401732   . 8D7C24 0C   lea   edi, [esp+C]       ; 将用户名字符串地址给edi
00401736   . 83C9 FF     or     ecx, FFFFFFFF
00401739   . 33C0       xor   eax, eax
0040173B   . 33D2       xor   edx, edx
0040173D   . F2:AE       repne   scas byte ptr es:[edi>
0040173F   . F7D1       not   ecx
00401741   . 49         dec   ecx
00401742     74 25       je     short 00401769     ; 用户名串长度为0则跳(感觉多余代码,前面已经判断要大于3了)
00401744   . 56         push   esi             ; 保存esi
00401745   . BE 14000000   mov   esi, 14
0040174A   > 0FBE4414 10   movsx   eax, byte ptr [esp+edx+10>; 从头开始取用户名字符asc码
0040174F   . 0FAFC6     imul   eax, esi         ; 将取得的asc码乘以esi
00401752   . 03D8       add   ebx, eax
00401754   . 42         inc   edx
00401755   . 8D7C24 10   lea   edi, [esp+10]
00401759   . 83C9 FF     or     ecx, FFFFFFFF
0040175C   . 33C0       xor   eax, eax
0040175E   . 4E         dec   esi             ; esi-1
0040175F   . F2:AE       repne   scas byte ptr es:[edi>; 从头开始扫描edi指的字符串,同时ecx-1。
00401761   . F7D1       not   ecx
00401763   . 49         dec   ecx
00401764   . 3BD1       cmp   edx, ecx         ; ecx 实际上是edi指的字符串的长度。
00401766   .^ 72 E2       jb     short 0040174A     ; 因此这里循环次数为用户名的长度
00401768   . 5E         pop   esi
00401769     8B15 C0D04200 mov   edx, [42D0C0]       ; 这里获取通过GetStartupInfo(&si)运算得到的随机数
0040176F   . 8D4C24 24   lea   ecx, [esp+24]
00401773   . 6A 0A       push   0A
00401775   . 03D3       add   edx, ebx         ; ebx为上面的那个循环计算得到的数
00401777   . 51         push   ecx
00401778   . 52         push   edx
00401779   . E8 687F0000   call   004096E6         ; 将edx对应的十进制数转为字符串
0040177E   . 8D7C24 30   lea   edi, [esp+30]       ; 取得字符串地址
00401782   . 83C9 FF     or     ecx, FFFFFFFF
00401785   . 33C0       xor   eax, eax
00401787   . 83C4 0C     add   esp, 0C
0040178A   . 33D2       xor   edx, edx
0040178C   . F2:AE       repne   scas byte ptr es:[edi>
0040178E   . F7D1       not   ecx
00401790   . 49         dec   ecx             ; 执行后ecx 实际上是edi指的字符串的长度。
00401791     74 23       je     short 004017B6     ; 若串长度为0提示正确信息(感觉这里的代码是多余的,它不可能为0)
00401793   > 0FBE4414 24   movsx   eax, byte ptr [esp+ed>; 取所得串第一个字符
00401798   . 0FBE4C14 48   movsx   ecx, byte ptr [esp+ed>; 取输入的注册码第一个字符
0040179D   . 03C2       add   eax, edx         ; 将串第一个字符asc码加其序号(从0开始)
0040179F   . 3BC1       cmp   eax, ecx         ; 再与注册码第一个字符比较
004017A1     75 23       jnz   short 004017C6     ; 不相等,则错
004017A3   . 8D7C24 24   lea   edi, [esp+24]
004017A7   . 83C9 FF     or     ecx, FFFFFFFF
004017AA   . 33C0       xor   eax, eax
004017AC   . 42         inc   edx
004017AD   . F2:AE       repne   scas byte ptr es:[edi>
004017AF   . F7D1       not   ecx
004017B1   . 49         dec   ecx
004017B2   . 3BD1       cmp   edx, ecx
004017B4   .^ 72 DD       jb     short 00401793     ; 再对第二个字符比较,循环次数为所得串的长度
004017B6   > 6A 00       push   0               ; 两串匹配则提示正确消息
004017B8   . 6A 00       push   0
004017BA   . 68 34B14200   push   0042B134         ; ASCII "Good job!"
004017BF   . 8BCD       mov   ecx, ebp
004017C1   . E8 96700100   call   0041885C
004017C6   > 5F         pop   edi
004017C7   . 5D         pop   ebp
004017C8   . 5B         pop   ebx
004017C9   . 83C4 60     add   esp, 60
004017CC   . C3         retn

下面看看42D0C0里的随机数是怎么得到的:
重新用od载入,载od左下角内存窗口右键-转到-表达式 填42D0C0 然后转到这个地址;现在这个地址是四个0
将这四个0选中,右键-断点-内存写入。
然后运行程序断在:0040141E   . 8915 C0D04200 mov   [42D0C0], edx       ; |
其附近有如下代码:
00401405   . 51         push   ecx             ; /pStartupinfo
00401406   . FF15 78224200 call   [<&KERNEL32.GetStartu>; \GetStartupInfoA
0040140C   . 8B5424 30   mov   edx, [esp+30]       ; startupinfo结构第9个参数
00401410   . 8B4424 24   mov   eax, [esp+24]       ; 第6个参数
00401414   . 8B5C24 20   mov   ebx, [esp+20]       ; 第5个参数
00401418   . 03D0       add   edx, eax
0040141A   . 03D3       add   edx, ebx         ; 将三个参数相加就得到随机数
0040141C   . 6A 00       push   0               ; /Revert = FALSE
0040141E   . 8915 C0D04200 mov   [42D0C0], edx       ; |


大致算法如下:
1、将用户名每一位乘以esi(esi=esi-1初始值esi=0x14)所得的和相加,再加1,得到一个数。
2、将此数加上随机数,得到另一个数。
3、将得到数的十进制每一位加上它对应的序号(比如123加序号后为135)得到的数的十进制,作为一个字符串就是注册码。
根据bxm提示,随机数是在用od载入时才产生,那么第二步则可省略,就剩下第一步和第三步。
算法c程序表示如下:
#include <stdio.h>
#include <string.h>
void main()
{
  char name[]="netwind";
  char temp[20];
  long c=1,esi=0x14;
  int i,l;
  for(i=0;i<strlen(name);i++,esi--)
    c=c+name*esi;
  i=0;
    while(c)               //将数字十进制转字符串。
  { temp[i++]=c%10+'0';     //这里得的是逆序的。
    c/=10;
  }
  temp=0;
  l=strlen(temp);
    for(i=0;i<strlen(temp);i++,l--) //每一位加上其正序时的序号。
  printf("%c",temp[l-1]+=i);     //将逆序串从最后一为开始输出,就是注册码。
  printf("\n");
  }
过程与汇编代码一样,只是汇编代码中间有一步把逆序串转正序,这里节省了这一步。
感想:
这个crackme很特别,很容易让人感觉写不出注册机.
程序应该加了异常处理吧,
od载入时,则会读取本进程STARTUPINFO 结构.
lpStartupInfo,参数结构
typedef struct _STARTUPINFO { // si
  DWORD   cb; //结构长度
  LPTSTR lpReserved; //保留
  LPTSTR lpDesktop; //保留
  LPTSTR lpTitle; //如果为控制台进程则为显示的标题
  DWORD   dwX; //窗口位置...........
  DWORD   dwY; //窗口位置...........
  DWORD   dwXSize; //窗口大小
  DWORD   dwYSize; //窗口大小
  DWORD   dwXCountChars; //控制台窗口字符号宽度 .........
  DWORD   dwYCountChars; //控制台窗口字符号高度
  DWORD   dwFillAttribute; //控制台窗口填充模式
  DWORD   dwFlags; //创建标记
  WORD   wShowWindow; //窗口显示标记如同ShowWindow中的标记
  WORD   cbReserved2; //
  LPBYTE lpReserved2; //
  HANDLE hStdInput; //标准输入句柄
  HANDLE hStdOutput; //标准输出句柄
  HANDLE hStdError; //标准错误句柄
} STARTUPINFO, *LPSTARTUPINFO;
将读出的结构的第9,6,5个参数的值相加得到随机数,然后加上前面运算得到的数字,得到一个数,把该数十进制每一位加该位的序号(从0开始)得到一个数,把该数十进制表示的数转为字符串形式便是注册码.
如果单用od跟踪,而没考虑到异常的话,很难想象可以做出一个注册机.
因为:
netwind (2007-03-02 22:42:07)
问下:
GetStartupInfo(&si);获得当前进程的STARTUPINFO 结构
如何获得指定某个进程的STARTUPINFO 结构
大牛(2007-03-02 22:43:16)
那些信息都存放在那个进程的 PEB 里。
大牛 (2007-03-02 22:43:30)
PEB 不公开的。去找些资料来看
netwind (2007-03-02 22:44:06)
恩,谢谢了
没有其他的简单方法了吗?
大牛 (2007-03-02 22:44:17)

大牛 (2007-03-02 22:44:27)
或者说,我不知道

crackme的算法分析较容易,爆破点也很容易找到,对异常处理那块较感兴趣.
希望有人能贴出更好的破文,谢谢!
这个crackme应该公布 源代码 希望如此,bxm大牛辛苦了,多谢!
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                    2007年03月03日 12:51:45
本帖最近评分记录:
  • 浮云:10 (by 独飞の孤心) | 理由: 貌似现在熟悉汇编的越来越少了
  • 顶端 Posted: 2007-03-05 11:20 | [楼 主]
    yinx



    性别: 帅哥 状态: 该用户目前不在线
    等级: 人见人爱
    家族: 丢丢
    发贴: 2333
    威望: 0
    浮云: 1260
    在线等级:
    注册时间: 2006-09-15
    最后登陆: 2009-05-11

    5come5帮你背单词 [ pure /pjuə/ a. 纯粹的,纯净的,纯洁的,无邪的,贞洁的,完全的,彻底的 ]


    附件: revme_1.rar (2 K) 下载次数:1

    顶端 Posted: 2007-03-05 11:22 | [1 楼]
    yinx



    性别: 帅哥 状态: 该用户目前不在线
    等级: 人见人爱
    家族: 丢丢
    发贴: 2333
    威望: 0
    浮云: 1260
    在线等级:
    注册时间: 2006-09-15
    最后登陆: 2009-05-11

    5come5帮你背单词 [ language /'læŋgwid3ə/ n. 语言 ]


    标 题: 【原创】: OverflowMe溢出分析
    作 者: netwind
    时 间: 2007-01-31,13:33
    链 接: http://bbs.pediy.com/showthread.php?threadid=38864

    【文章标题】: OverflowMe溢出分析
    【文章作者】: netwind
    【作者邮箱】: zwfnetwind@163.com
    【软件名称】: OverflowMe
    【下载地址】: http://bbs.pediy.com/attachment.php?s=&attachmentid=4243
    【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
    --------------------------------------------------------------------------------
    【详细过程】
    利用字符串查找参考来到以下地方:
    00401009 |> /68 54A04000   /push   0040A054           ; please input password:
    0040100E |. |E8 EA010000   |call   004011FD
    00401013 |. |83C4 04     |add   esp, 4
    00401016 |. |8D4424 04   |lea   eax, [esp+4]
    0040101A |. |50         |push   eax
    0040101B |. |68 50A04000   |push   0040A050           ; %s
    00401020 |. |E8 C1010000   |call   004011E6           ; 输入password串(字符串超长覆盖seh可控制程序流程)
    00401025 |. |83C4 08     |add   esp, 8
    00401028 |. |8D4C24 04   |lea   ecx, [esp+4]
    0040102C |. |C64424 0B 00 |mov   byte ptr [esp+B], 0
    00401031 |. |51         |push   ecx               ; /Arg1
    00401032 |. |E8 49000000   |call   00401080           ; \验证密码(跟进去可以发现密码是test)
    00401037 |. |84C0       |test   al, al
    00401039 |. |75 28       |jnz   short 00401063
    0040103B |. |68 48A04000   |push   0040A048           ; error\n\n%s
    00401040 |. |E8 B8010000   |call   004011FD           ; 错误提示
    00401045 |. |83C4 04     |add   esp, 4
    00401048 |. |8BD6       |mov   edx, esi
    0040104A |. |4E         |dec   esi
    0040104B |. |85D2       |test   edx, edx
    0040104D |.^\75 BA       \jnz   short 00401009       ; 循环三次(有三次尝试密码的机会)
    0040104F |. 68 40A04000   push   0040A040           ; pause
    00401054 |. E8 F7000000   call   00401150           ; 提示按任意键继续(call执行完可改变程序流程)

    有两个地方可以控制程序流程
    第一个地方就是第一次输入password时,发现当输入的串向下填充到栈底时,程序将转入seh异常处理,这时后seh处理函数地址
    已经被我们输入字符串覆盖。
    其长度为0x12fffc-0x12ff78 (0x12fffc为栈底,0x12ff7c为字符串填充的起始地址。)
    在覆盖前(程序执行到00401009时 堆栈分布情况如下:
    0012FF7C   00401590   返回到 o.00401590 来自 o.0040164F
    0012FF80   0040A000   o.0040A000
    0012FF84   00401390   返回到 o.<模块入口点>+0B4 来自 o.00401000
    0012FF88   00000001
    0012FF8C   00370ED0
    0012FF90   00370F28
    0012FF94   7C930738   ntdll.7C930738
    0012FF98   FFFFFFFF
    0012FF9C   7FFD6000
    0012FFA0   00000001
    0012FFA4   00000006
    0012FFA8   0012FF94
    0012FFAC   AAD62D08
    0012FFB0   0012FFE0   指向下一个 SEH 记录的指针
    0012FFB4   00403B44   SE处理程序
    0012FFB8   004090F8   o.004090F8
    0012FFBC   00000000
    0012FFC0   0012FFF0
    0012FFC4   7C816D4F   返回到 kernel32.7C816D4F
    0012FFC8   7C930738   ntdll.7C930738
    0012FFCC   FFFFFFFF
    0012FFD0   7FFD6000
    0012FFD4   8054B6ED
    0012FFD8   0012FFC8
    0012FFDC   81F844F8
    0012FFE0   FFFFFFFF   SEH 链尾部
    0012FFE4   7C8399F3   SE处理程序
    0012FFE8   7C816D58   kernel32.7C816D58
    0012FFEC   00000000
    0012FFF0   00000000
    0012FFF4   00000000
    0012FFF8   004012DC   o.<模块入口点>
    0012FFFC   00000000

    用长串字符aaaaaaaaaa..覆盖后运行提示提示不知如何继续,内存地址61616161不可读
    这时堆栈分布情况如下:
    0012FF74   0012FF7C   ASCII "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    0012FF78   FFFFFFFF
    0012FF7C   61616161
    0012FF80   61616161
    0012FF84   61616161
    0012FF88   61616161
    0012FF8C   61616161
    0012FF90   61616161
    0012FF94   61616161
    0012FF98   61616161
    0012FF9C   61616161
    0012FFA0   61616161
    0012FFA4   61616161
    0012FFA8   61616161
    0012FFAC   61616161
    0012FFB0   61616161   指向下一个 SEH 记录的指针
    0012FFB4   61616161   SE处理程序
    0012FFB8   61616161
    0012FFBC   61616161
    0012FFC0   61616161
    0012FFC4   61616161
    0012FFC8   61616161
    0012FFCC   61616161
    0012FFD0   61616161
    0012FFD4   61616161
    0012FFD8   61616161
    0012FFDC   61616161
    0012FFE0   61616161
    0012FFE4   61616161
    0012FFE8   61616161
    0012FFEC   61616161
    0012FFF0   61616161
    0012FFF4   61616161
    0012FFF8   61616161
    0012FFFC   61616161

    这时发生了异常 程序转入seh 处理异常,而seh函数地址又被覆盖成   61616161 所以执行61616161 停下。
    这时后如果我们把seh函数地址覆盖成00401100 (这是提示成功字符串地址) 那么发生异常时程序转入执行00401100
    就达到目的了。但是00401100中有00,如果在password串中有00就会被截断,我常识利用寄存器跳转,但没找到合适的能够
    条到提示成功的程序的位置。

    尝试了很久没达到目的,传统覆盖seh 的方法也不可用。
    传统方法是:当发生异常时,ebx指向seh第一个记录指针,就是上面0012FFB0 的位置,我们把seh处理函数地址(0012FFB4的值)
    覆盖成jmp ebx的地址(可以在内存中搜索通用地址),这时程序执行到0012ffb0 ,把0012ffb0覆盖为eb06eb06,执行时eip
    想下跳8字节,就执行到0012FFB8 而这里面放我们的shellcode,那么就实现了攻击的目的。
    这个方法也是在win2000才成功

    那么我们就利用第二个溢出点:
    用od加载程序 执行。
    输入密码aaaabbbbccccddddeeeeffff
    提示错误
    继续输入密码:aaaabbbbccccddddeeeeffff
    提示错误
    继续输入密码:aaaabbbbccccddddeeeeffff
    提示错误
    按f8继续执行
    当执行完
    0040104F |. 68 40A04000   push   0040A040           ; pause
    00401054 |. E8 F7000000   call   00401150           ; 提示按任意键继续(call执行完可改变程序流程)
    时程序提示 eip 63636363不可以继续执行。
    那么我们可以推断call执行完后回到用cccc覆盖的地址0012FF84去执行。
    我们只要把cccc覆盖为00401100就可以达到目的了。
    三次输入的密码都是从一个地址开始覆盖的。那么以第三次输入的串覆盖的结果为准,也就是前两次密码随便输入只要
    串不太长让程序转入seh就可以了。

    password覆盖前 堆栈分布:
    0012FF7C   00401590   返回到 o.00401590 来自 o.0040164F   //password每次从这里开始覆盖
    0012FF80   0040A000   o.0040A000
    0012FF84   00401390   返回到 o.<模块入口点>+0B4 来自 o.00401000   //
    覆盖后
    0012FF78   FFFFFFFF
    0012FF7C   61616161
    0012FF80   00626262
    0012FF84   63636363           //00401054 call完后程序从这里执行,把这个位置覆盖为00401100就达到目的了
    0012FF88   64646464

    0012FF84原来值为00401390只要把1390覆盖为1100就可以了,而有00会被截断,我们要想办法避免
    看看401100处代码
    004010F7     90         nop
    004010F8     90         nop
    004010F9     90         nop
    004010FA     90         nop
    004010FB     90         nop
    004010FC     90         nop
    004010FD     90         nop
    004010FE     90         nop
    004010FF     90         nop
    00401100   /$ 68 6CA04000   push   0040A06C           ; succeed, you win!\n\n
    00401105   |. E8 F3000000   call   004011FD

    那么我们只要用4010ff(执行一个nop就到401100了)来代替401100就可以了

    好了到这里就达到目的了
    前两次随便输入password别 导致异常就可以了,然后第三次输入aaaabbbb
    附件: overflowme.rar (20 K) 下载次数:1

    顶端 Posted: 2007-03-05 11:23 | [2 楼]
    yinx



    性别: 帅哥 状态: 该用户目前不在线
    等级: 人见人爱
    家族: 丢丢
    发贴: 2333
    威望: 0
    浮云: 1260
    在线等级:
    注册时间: 2006-09-15
    最后登陆: 2009-05-11

    5come5帮你背单词 [ golden /'gəuldən/ a. 金色的,发亮的,金的,金制的,高尔夫球 ]


    那个Reverseme 我做了一下,实在是太难了.

    参考这篇文章蝈蝈们应该可以做出来.

    标 题: 逆向初步,给XP记事本增加显/隐工具栏,从文件载入工具图片
    作 者: andy00
    时 间: 2006-03-30 19:26
    链 接: http://bbs.pediy.com/showthread.php?threadid=23358
    详细信息:


    ;===============================================修改说明===============================================

    【软件名称】XP记事本(Notepad)
    【下载地址】附件(附本文)
    【应用平台】Win9x/NT/2000/XP
    【软件大小】120K
    【软件限制】未修改时,没有工具栏。
    【保护方式】--------
    【修 改 者】andy00
    【修改难度】1/10
    【修改说明】只是为了熟悉逆向工程,所以使用静态分析。
    【分析工具】Olldbg,计算器
    【参考资料】MSDN
    【软件简介】--------

    ;===============================================附加的说明==============================================

      这个程序是接着上一修改的,本文的某些东西如果看不懂请先看这一篇:

      逆向初步,增加XP记事本功能,使用背景色,文字颜色,下划线,删除线

      http://bbs.pediy.com//showthread.php?s=&threadid=23277

      对于比较麻烦的修改,建议大家先弄清流程,搞清楚要哪些函数,哪些变量,然后写出伪代码,划分空闲数据与代码空间,建议两者
    各占空间,不要混合.给变量挨个分配空间,非数组的,尽量都分配双字以上,方便管理.最后再动手,不至于手忙脚乱,思路混乱
    搞到最后自己都不知道在哪里了,只好放弃.

    ;===============================================增加的功能分析==========================================

    功能1   创建工具条菜单
    功能2   创建工具条,能够通过工具条菜单来控制显示/隐藏
    ....   从文件载入工具条位图资源.这时百toolbar.bmp



    ;=============================================功能实现需要的信息=======================================

    ;创建工具条
     
      使用函数CreateToolbarEx或CreateWindowEx,后一个非常麻烦,所以用前一个:
     
    HWND CreateToolbarEx(      
      HWND     hwnd,       //父窗口句柄
      DWORD     ws,         //窗口样式
      UINT     wID,         //窗口ID
      int       nBitmaps,     //位图数
      HINSTANCE   hBMInst,     //位图所在的模块,若为NULL,则wBMID必须是有效的位图句柄
      UINT_PTR   wBMID,       //位图在该模块中的句柄
      LPCTBBUTTON lpButtons,     //TBBUTTON结构
      int       iNumButtons,   //工具栏按钮数(包含分隔符)
      int       dxButton,     //按钮宽度
      int       dyButton,     //按钮高度
      int       dxBitmap,     //按钮位图宽度16,24,32...
      int       dyBitmap,     //按钮位图高度16,24,32...
      UINT     uStructSize   //TBBUTTON结构的大小,为14
    );

      成功则返回工具条句柄,失败则返回0
     
    ; 载入工具栏位图

      因为我们是要从文件载入工具栏位图,所以使用函数LoadImage
     
    HANDLE LoadImage(      
      HINSTANCE   hinst,       //位图所在模块从文件载入此处为0
      LPCTSTR   lpszName,     //位图文件路径(相对或完整均可)
      UINT     uType,       //图像类型这里是IMAGE_BITMAP
      int       cxDesired,     //位图宽度,为0则按真实大小
      int       cyDesired,     //位图高度,为0则按真实大小
      UINT     fuLoad       //载入方式,从文件载入为LR_LOADFROMFILE
    );

      成功返回位图句柄,失败返回0
     
    ; 删除位图对象
     
      凡是GDI对象,多数要在不使用的时候释放它们的内存,位图对象也是.所以要使用函数DeleteObject删除它
     
    BOOL DeleteObject(
    HGDIOBJ     hObject       // 位图句柄
    );

      成功返回真,否则返回假
     
    ; 设置菜单检查标记
     
      使用函数CheckMenuItem

    DWORD CheckMenuItem(      
      HMENU     hmenu,       //主菜单句柄
      UINT     uIDCheckItem,   //子菜单ID
      UINT     uCheck       //检查标志,MF_CHECKED(==8)为检查,MF_UNCHECKED(==0)为不检查
    );


    ; 获得主菜单
     
      使用函数
     
    HMENU GetMenu(
      HWND     hWnd         //窗口句柄
    );

      成功返回菜单句柄,失败返回0
       
    ; 其它函数

      对于窗口及其大小的操作难免用到这几个函数
     
      GetClientRect,     //获取客户区区域
      MoveWindow,       //移动/设置窗口位置/大小
      ShowWinodw       //显示/隐藏窗口
     
      详细请查阅MSDN
     
    ; 相关消息
     
      WM_SIZE

        WPARAM wParam
        LPARAM lParam
       
    参数说明:

    lParam 低字指出了窗口的新的客户区宽度,高字指出了窗口的新的客户区的高度.
     
      WM_COMMAND

        WPARAM wParam
        LPARAM lParam;
    参数说明:

    wParam 消息状态码,如果是加速键消息,高字为1,如果是菜单消息,高字为0,低字为控件/菜单/加速键ID
    lParam 如果是控件消息,则为控件句柄,否则为0


    ;=============================================功能实现伪代码============================================

    #define ID_TOOLBAR   101     //工具栏ID

    TBBUTTON tbButtonsCreate [ ] = //创建工具栏需要的数据,详细请查阅MSDN                            
    {
      //0,   x,         4,             0,     0, 0, 0
      {0, IDM_FILE_NEW,     TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {1, IDM_FILE_OPEN,     TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {2, IDM_FILE_SAVE,     TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {3, IDM_FILE_SAVEAS,   TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {4, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {0,   0       ,   TBSTATE_ENABLED, BTNS_SEP,   {0},0L, 0},
      {5, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {6, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {7, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {8, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {9, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {10, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {11, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {0,   0       ,   TBSTATE_ENABLED, BTNS_SEP,   {0},0L, 0},
      {12, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},
      {13, IDM_FILE_PRINTCFG, TBSTATE_ENABLED, BTNS_BUTTON, {0},0L, 0},

    };

    int         cxEdit
    int         cyEdit;
    int         yEdit;
    int         cyToolBar;
    HWND         hWndToolbar,hWndEdit;
    BOOL         bShowToolBar=TRUE;
    RECT         rcClient;
    HMENU       hMenu;
    HBITMAP       hToolBarBitmap;
    WCHAR       wsBitmap[]="toolbar.bmp";

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
      int wmId,     wmEvent;

      switch (message)
      {
      case WM_CREATE:
        hToolBarBitmap=(HBITMAP)LoadImage(NULL,wcBitmap,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); //载入位图
       
        hWndToolbar = CreateToolbarEx (hWnd,
            WS_CHILD | WS_VISIBLE ,
            ID_TOOLBAR, 14, NULL,(UINT)hToolBarBitmap ,
            tbButtonsCreate, 16, 0, 0, 16, 16, sizeof (TBBUTTON));     //创建工具条
       
        hWndEdit   =CreateWindow("edit"/*.其余参数省略...*/);       //创建编辑框
       
        CheckMenuItem(hMenu,IDM_VIEW_TOOLBAR,MF_CHECKED);           //设置检查标志

        break;

      case WM_SIZE:
        cxEdit=LOWORD(lParam);
        cyEdit=HIWORD(lParam);
       
        cyEdit=cyWnd;
        cyToolBar=0;
        yEdit=0;

        if(bShowToolBar)     //如果当前是显示的
        {
            cyEdit-=28;       //编辑框高度减28
            yEdit+=28;       //下移28
            cyToolBar=28;     //工具栏高度28
        }

        MoveWindow(hWndToolbar,0,0,cxEdit,cyToolBar,TRUE);     //调整工具栏窗口
        MoveWindow(hWndEdit,0,yEdit,cxEdit,cyEdit,TRUE);     //调整编辑框窗口

        return TRUE;

      case WM_COMMAND:  
        wmId   = LOWORD(wParam);
        wmEvent = HIWORD(wParam);

        switch (wmId)
        {  
        case IDM_VIEW_TOOLBAR: //菜单1D==1D

            bShowToolBar=!bShowToolBar;  
            ShowWindow(hWndToolbar,bShowToolBar);     //显示/隐藏工具栏
                   
            CheckMenuItem(hMenu,IDM_VIEW_TOOLBAR,bShowToolBar?MF_CHECKED:MF_UNCHECKED);   //设置/取消检查标志
           
            GetClientRect(hWnd,&rcClient);

            if(bShowToolBar)
            {
              rcClient.top+=30;
            }
           
            MoveWindow(hWndEdit,rcClient.left,rcClient.top,
            rcClient.right-rcClient.left,rcClient.bottom-rcClient.top,TRUE);     //调整编辑框区域
            return TRUE;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
       
      case WM_DESTROY:
        DeleteObject(hToolBarBitmap);     //删除位图对象
        PostQuitMessage(0);

        break;    
      default:
        return DefWindowProc(hWnd, message, wParam, lParam);
      }
      return 0;
    }

    注意由于使用函数LoadImageW,必须使用宽字符集,第个字母占两个字节如图:



    ;==========================================根据伪代码分配空间,输入函数====================================

    ;============================增加输入函数=============================

    ;需要手动输入的函数

    comctl32.dll   CreateToolbarEx   0001408C

    ;已输入的函数
    USEER32.DLL   SendMessageW     01001240
    USR32.DLL     ShowWinodw       010011B0
    USR32.DLL     MoveWindow       01001220
    USR32.DLL     CheckMenuItem     01001248
    USR32.DLL     GetClientRect     01001188
    USR32.DLL     LoadImageW       010011D4
    USR32.DLL     GetMenu         01001264
           
    ;============================增加程序空间=============================

    .andy00   VSize:10000   VOffset:14000   RSize:10000   ROffset:10A00   Flag:E0000060

    空间分配

    10A00(14000)   11000(14600) 输入表   共600
    11100(14700)   19000(1C600) 代码     共7F00
    19100(1C700)   1FA00(23000) 数据     共6900


    ;============================变量分配================================


    ;工具条功能变量(1C704->1C914)

    变量类型     变量名         文件偏移         虚拟偏移
    hWnd ==DWORD PTR DS:[1009830]
    HWND         hWndEdit         8438           9838           ; 编辑框句柄,程序已分配
    int         cxWnd           19104           1C704           ; 编辑框宽度
    int         cyWnd           19108           1C708           ; 编辑框高度
    int         yEdit           1910C           1C70C           ; 编辑框最高位置          

    int         cyToolBar       19114           1C714           ; 工具条高度  
    HWND         hWndToolbar       19118           1C718           ; 工具条句柄
    int         iCheckFlag       1911C           1C71C           ; 是否显示工具条
    HMENU       hMenu           19120           1C720           ; 主菜单句柄
    TBBUTTON[]     tbButtonsCreate   1912C->1926C     1C72C->1C86C     ; 用于创建工具条的数据

    COLORREF     crText         19270           1C870           ;颜色字体功能变量
    COLORREF     crBkgnd         19274           1C874           ;颜色字体功能变量
    HBRUSH       hBrBkgnd         19278           1C878           ;颜色字体功能变量
    CHOOSECOLOR   cc             1927C->1929C     1C87C->1C89C     ;颜色字体功能变量

    TCHAR[]       szBitmapName     19280           1C880

    COLORREF[]     lpcusColor       192A0->192B0     1C8A0->1C8B0     ;颜色字体功能变量
    DWORD       tmp           192B4           1C8B4           ;颜色字体功能变量

    HBITMAP       hBitmap         19300           1C900           ; 工具条位图句柄
    RECT         rcClient.left     19304           1C904           ; 客户区的矩形区域
              rcClient.top     19308           1C908           ;
              rcClient.right     1930C           1C90C
              rcClient.bottom   19310           1C910



    准备的工具栏按钮位图


    ;===========各菜单ID,按在工具栏上从左到右的顺序排列,0为分隔栏=============

    打开,新建,保存,另存,打印,空格,查找,剪切,复制,粘贴,撤消1,撤消2,删除,空格,字体,颜色

    2   1     3   4   5   0     15 300 301 302   10 10     303 0   21 1C



    ;===============================================创建工具条=============================================

    ;找到创建编辑框的地方

    0100473A   . 8B45 90       MOV   EAX, DWORD PTR SS:[EBP-70]
    0100473D   . 53           PUSH   EBX                         ; /lParam
    0100473E   . FF75 AC       PUSH   DWORD PTR SS:[EBP-54]             ; |hInst=[EBP-54]
    01004741   . 83C0 9C       ADD   EAX, -64                     ; |
    01004744   . 6A 0F         PUSH   0F                         ; |
    01004746   . FF35 30980001   PUSH   DWORD PTR DS:[1009830]             ; |hParent=hWnd=[1009830]
    0100474C   . 50           PUSH   EAX                         ; |Height
    0100474D   . FF75 8C       PUSH   DWORD PTR SS:[EBP-74]             ; |Width
    01004750   . A1 50980001     MOV   EAX, DWORD PTR DS:[1009850]         ; |
    01004755   . F7D8         NEG   EAX                         ; |
    01004757   . 53           PUSH   EBX                         ; |Y
    01004758   . 1BC0         SBB   EAX, EAX                     ; |
    0100475A   . 53           PUSH   EBX                         ; |X
    0100475B   . 25 0000F0FF     AND   EAX, FFF00000                   ; |
    01004760   . 05 04013050     ADD   EAX, 50300104                   ; |
    01004765   . 50           PUSH   EAX                         ; |Style
    01004766   . 56           PUSH   ESI                         ; |WindowName
    01004767   . 68 94170001     PUSH   01001794                     ; |Class = "Edit"
    0100476C   . 68 00020000     PUSH   200                         ; |ExtStyle = WS_EX_CLIENTEDGE
    01004771   . FF15 E0110001   CALL   DWORD PTR DS:[<&USER32.CreateWindowExW>>; \CreateWindowExW
    01004777   . 90           NOP
    01004778   . 90           NOP
    01004779   .- E9 A0E90000     JMP   01014900                     ;跳到初始化画刷的代码
    0100477E   . 0F84 2A020000   JE     010049AE
    ;................
    ;................
     
      由以上代码分析可以得到: hInst== SS:[EBP-54]
                      hWnd == DWORD PTR DS:[1009830]



    01014900   A3 38980001       MOV   DWORD PTR DS:[1009838], EAX         ; hWndEdit
    01014905   68 FFFFFF00       PUSH   0FFFFFF                       ; 白色
    0101490A   FF15 5D400101     CALL   DWORD PTR DS:[101405D]             ; 创建白色画刷CreateSolidBrush
    01014910   A3 78C80101       MOV   DWORD PTR DS:[101C878], EAX         ; 保存画刷句柄
    01014915   C705 74C80101 FFFFF>MOV   DWORD PTR DS:[101C874], 0FFFFFF       ; 保存背景颜色白色
    0101491F   A1 38980001       MOV   EAX, DWORD PTR DS:[1009838]         ; 从这里开始添加创建工具条的代码
                                                        ; 这一句在最后加上
    01014924   3BC3           CMP   EAX, EBX                     ; 这一句在最后加上
    01014926 - E9 53FEFEFF       JMP   0100477E                     ; 这一句在最后加上


    ;原来创建画刷的部分:

    010148FC   A3 38980001       MOV   DWORD PTR DS:[1009838], EAX
    01014901   68 FFFFFF00       PUSH   0FFFFFF
    01014906   FF15 5D400101     CALL   DWORD PTR DS:[101405D]             ; GDI32.CreateSolidBrush
    0101490C   A3 78C80101       MOV   DWORD PTR DS:[101C878], EAX
    01014911   C705 74C80101 FFFFF>MOV   DWORD PTR DS:[101C874], 0FFFFFF
    ;................
    ;................

    ;新加的部分,加载工具栏位图创建工具栏,设置"显示工具栏"iCheckFlag(保存在RVA==1C71C)为"显示"(=MF_CHECKED==8)

    0101491B     6A 10           PUSH   10                         ; /fuLoad=LR_LOADFROMFILE
    0101491D     90             NOP                               ; |从文件载入
    0101491E     90             NOP
    0101491F     6A 00           PUSH   0                           ; |cyDesired=0
    01014921     6A 00           PUSH   0                           ; |cxDesired=0
    01014923     6A 00           PUSH   0                           ; |uType=IMAGE_BITMAP
    01014925     68 80C80101       PUSH   0101C880                     ; |UNICODE "toolbar.bmp"
    0101492A     6A 00           PUSH   0                           ; |hinst=NULL(从文件载入)
    0101492C     FF15 D4110001     CALL   DWORD PTR DS:[<&USER32.LoadImageW>]   ; \LoadImageW

    01014932     A3 00C90101       MOV   DWORD PTR DS:[101C900], EAX         ; 保存到hBitmap(RVA==1C900)  
    01014937     6A 14           PUSH   14                         ; /sizof(TBBUTTON)        
    01014939     6A 10           PUSH   10                         ; |dyBitmap=16  
    0101493B     6A 10           PUSH   10                         ; |dxBitmap=16(16*16小图标)
    0101493D     6A 00           PUSH   0                           ; |dyButton默认
    0101493F     6A 00           PUSH   0                           ; |dxButton默认
    01014941     6A 10           PUSH   10                         ; |iNumButtons=10
    01014943     68 2CC70101       PUSH   0101C72C                     ; |lpButtons=tbButtons
    01014948     FF35 00C90101     PUSH   DWORD PTR DS:[101C900]             ; |wBMID=hBitmap(这里使用文件载入)
    0101494E     6A 00           PUSH   0                           ; |hBMInst=NULL(要从文件载入)
    01014950     6A 0D           PUSH   0D                         ; |nBitmap=13
    01014952     6A 65           PUSH   65                         ; |wndID=65
    01014954     68 00000050       PUSH   50000000                     ; |wndStyle=WS_CHILD|WS_VISIBLE
    01014959     FF35 30980001     PUSH   DWORD PTR DS:[1009830]             ; |hParent =hWnd
    0101495F     FF15 8C400101     CALL   DWORD PTR DS:[101408C]             ; \CreateToolbarEx
    01014965     85C0           TEST   EAX, EAX
    01014967     74 2B           JE     SHORT 01014994                 ; 创建失败则不进行下面动作交给程序处理
    01014969     A3 18C70101       MOV   DWORD PTR DS:[101C718], EAX         ; 保存工具条句柄到hWndToolbar(RVA==1C718)
    0101496E     C705 1CC70101 08000>MOV   DWORD PTR DS:[101C71C], 8           ; 设置工具条显示状态为"显示",iCheckFlag=MF_CHECKED

    01014978     FF35 30980001     PUSH   DWORD PTR DS:[1009830]             ; /参数hWnd入栈
    0101497E     FF15 64120001     CALL   DWORD PTR DS:[<&USER32.GetMenu>]     ; \GetMenu(hWnd)
    01014984     A3 20C70101       MOV   DWORD PTR DS:[101C720], EAX         ; 保存菜单句柄到hMenu(RVA==1C720)

    01014989     6A 08           PUSH   8                           ; uCheckFlag=MF_CHECKED (设置选中标志,一个小勾)
    0101498B     6A 1D           PUSH   1D                         ; 要设置的子菜单,"工具栏"菜单
    0101498D     50             PUSH   EAX                         ; 菜单句柄hMenu
    0101498E     FF15 48120001     CALL   DWORD PTR DS:[<&USER32.CheckMenuItem>] ; CheckMenuItem(hMenu,1D,MF_CHECKED);

    01014994     A1 38980001       MOV   EAX, DWORD PTR DS:[1009838]         ; 原来程序的代码
    01014999     3BC3           CMP   EAX, EBX                     ; 原来程序的代码
    0101499B   - E9 DEFDFEFF       JMP   0100477E                     ; 返回原片交给程序处理


    ;========================================清除位图对象,防止内存泄漏====================================

    ;直接来到以前清楚画刷的地方

    01014860   FF35 78C80101     PUSH   DWORD PTR DS:[101C878]             ; 画刷句柄
    01014866   FF15 68100001     CALL   DWORD PTR DS:[<&GDI32.DeleteObject>]   ; DeleteObject(hBrBkgnd)
    0101486C   6A 00           PUSH   0
    0101486E   FF15 F4110001     CALL   DWORD PTR DS:[<&USER32.PostQuitMessage>>; USER32.PostQuitMessage
    01014874 - E9 44ECFEFF       JMP   010034BD


    ;把以上代码改为

    01014860   FF35 78C80101     PUSH   DWORD PTR DS:[101C878]             ; 画刷句柄
    01014866   FF15 68100001     CALL   DWORD PTR DS:[<&GDI32.DeleteObject>]   ; DeleteObject(hBrBkgnd)
    0101486C   FF35 00C90101     PUSH   DWORD PTR DS:[101C900]             ; 位图句柄
    01014872   FF15 68100001     CALL   DWORD PTR DS:[<&GDI32.DeleteObject>]   ; DeleteObject(hBitmap)
    01014878   6A 00           PUSH   0
    0101487A   FF15 F4110001     CALL   DWORD PTR DS:[<&USER32.PostQuitMessage>>; USER32.PostQuitMessage
    01014880 - E9 38ECFEFF       JMP   010034BD


      保存修改,然后运行修改过的程序,这时候,出现了工具条,但是还有问题,任何编辑框的操作都会出现,光栅出现在工具
    条"内部"的情况,而且这时候,工具条是不能用的.



      这是因为,对编辑框进行的某些操作可能导致程序收到WM_SIZE消息,而记事本处理的WM_SIZE的时候,默认是把编辑框
    放到客户区顶端的,所以我们必须处理WM_SIZE消息


    ;===========================================处理WM_SIZE消息=============================================

    ;来到WNDPROC

    01003429     8BFF         MOV   EDI, EDI
    0100342B /. 55           PUSH   EBP
    0100342C |. 8BEC         MOV   EBP, ESP
    0100342E |. 51           PUSH   ECX
    0100342F |. 51           PUSH   ECX
    01003430 |. 56           PUSH   ESI
    01003431 |. 8B75 0C       MOV   ESI, DWORD PTR SS:[EBP+C]         ; ESI=message
    01003434   - E9 67130100     JMP   010147A0                     ; 以前修改的代码,不用关心此处,一会儿会跳回来
    01003439     90           NOP
    0100343A |. 5A           POP   EDX
    0100343B |. 0F87 41020000   JA     01003682
    01003441 |. 0F84 B7010000   JE     010035FE
    01003447 |. 3BF2         CMP   ESI, EDX
    01003449 |. 0F87 ED000000   JA     0100353C
    0100344F |. 0F84 DB000000   JE     01003530
    01003455 |. 8BC6         MOV   EAX, ESI                     ; EAX=message
    01003457 |. 48           DEC   EAX                         ; message--;
    01003458 |. 48           DEC   EAX                         ; message--;  
    01003459 |. 0F84 C7000000   JE     01003526    
    0100345F |. 83E8 03       SUB   EAX, 3                       ; message-=3;
    01003462 |. 74 61         JE     SHORT 010034C5                 ; if(message==WM_SIZE) GOTO 010034c5
    010034BD |> 33C0         XOR   EAX, EAX                     ; Default case of switch 010034CE
    010034BF |> |5F           POP   EDI
    010034C0 |. |5E           POP   ESI
    010034C1 |. |C9           LEAVE
    010034C2 |. |C2 1000       RET   10                         ; 退出WNDPROC,之前不跳就完了


    ;WM_SIZE消息的处理过程,从01003462跳过来

    010034C5 |> \8B45 10       MOV   EAX, DWORD PTR SS:[EBP+10]         ; 从这儿跳到自己的代码,因为我们不关心
    010034C8 |. 33F6         XOR   ESI, ESI                     ; wParam的值为什么.直接处理WM_SIZE消息
    ;................
    ;................                                                      


    ;010034C5-010034C8两句改为

    010034C5   - E9 B0180100     JMP   01014BC0                     ; ===========跳到自己的代码==========
    010034CA |.   2BC6           SUB   EAX, ESI
    010034CC |.   74 06         JE     SHORT 010034D4                   ; wParam==SIZE_RESTORED
    010034CE |.   48           DEC   EAX                         ;
    010034CF |.   74 49         JE     SHORT 0100351A                     ; wParam==   SIZE_MINIMIZED
    010034D1 |.   48           DEC   EAX                         ;
    010034D2 |.^ 75 E9         JNZ   SHORT 010034BD                   ; if(wParam!=SIZE_MAXIMIZED)goto 010034BD

    010034BD |>   33C0           XOR   EAX, EAX                       ; Default case of switch 010034CE
    010034BF |>   |5F           POP   EDI
    010034C0 |.   |5E           POP   ESI
    010034C1 |.   |C9           LEAVE
    010034C2 |.   |C2 1000       RET   10                         ; 退出WNDPROC,之前不跳就完了


    ;
    01014BC0     50             PUSH   EAX
    01014BC1     8B45 14         MOV   EAX, DWORD PTR SS:[EBP+14]         ; EAX=lParam
    01014BC4     25 FFFF0000       AND   EAX, 0FFFF                     ; EAX=LOWORD(lParam),LOWARD(lParam)==窗口现在宽度
    01014BC9     A3 04C70101       MOV   DWORD PTR DS:[101C704], EAX         ; cxEdit
    01014BCE     8B45 14         MOV   EAX, DWORD PTR SS:[EBP+14]         ; EAX=lParam
    01014BD1     C1E8 10         SHR   EAX, 10                       ; EAX=HIWORD(lParam),HIWARD(lParam)==窗口现在高度
    01014BD4     A3 08C70101       MOV   DWORD PTR DS:[101C708], EAX         ; cyEdit=HIWORD(lParam)
    01014BD9     833D 1CC70101 08   CMP   DWORD PTR DS:[101C71C], 8
    01014BE0     75 21           JNZ   SHORT 01014C03                 ; if(iCheckFlag!=MF_CHECKED) goto 01014C03
    01014BE2     90             NOP                               ; 当前没有显示则跳到01014c03    
    01014BE3     90             NOP
    01014BE4     90             NOP
    01014BE5     90             NOP                               ; 如果现在工具条显示的,执行以下动作
    01014BE6     832D 08C70101 1C   SUB   DWORD PTR DS:[101C708], 1C         ; 编辑框高度-=3D
    01014BED     C705 0CC70101 1C000>MOV   DWORD PTR DS:[101C70C], 1C         ; 编辑框最高位置yEdit=30D
    01014BF7     C705 14C70101 1C000>MOV   DWORD PTR DS:[101C714], 1C         ; 工具条高度cyToolbar==30D
    01014C01     EB 14           JMP   SHORT 01014C17                 ; 如果iCheckFlag==0当前没有显示工具条,
    01014C03     C705 0CC70101 00000>MOV   DWORD PTR DS:[101C70C], 0           ; 则编辑框从客户区最高位置yEdit=0
    01014C0D     C705 14C70101 00000>MOV   DWORD PTR DS:[101C714], 0           ; 工具条高度设为0,cyToolbar=0

    01014C17     6A 01           PUSH   1                           ; /bRepaint=TRUE
    01014C19     FF35 14C70101     PUSH   DWORD PTR DS:[101C714]             ; |cyToolbar
    01014C1F     FF35 04C70101     PUSH   DWORD PTR DS:[101C704]             ; |cxEdit
    01014C25     6A 00           PUSH   0                           ; |yToolbar
    01014C27     6A 00           PUSH   0                           ; |xToolbar
    01014C29     FF35 18C70101     PUSH   DWORD PTR DS:[101C718]             ; |hWndToolbar
    01014C2F     FF15 20120001     CALL   DWORD PTR DS:[<&USER32.MoveWindow>]   ; \MoveWindow按参数调整窗口大小位置

    01014C35     6A 01           PUSH   1                           ; /bRepaint=TRUE
    01014C37     FF35 08C70101     PUSH   DWORD PTR DS:[101C708]             ; |cyEdit
    01014C3D     FF35 04C70101     PUSH   DWORD PTR DS:[101C704]             ; |cxEdit
    01014C43     FF35 0CC70101     PUSH   DWORD PTR DS:[101C70C]             ; |yEdit
    01014C49     6A 00           PUSH   0                           ; |xEdit
    01014C4B     FF35 38980001     PUSH   DWORD PTR DS:[1009838]             ; |hEdit
    01014C51     FF15 20120001     CALL   DWORD PTR DS:[<&USER32.MoveWindow>]   ; \MoveWindow按参数调整编辑框窗口大小位置

    01014C57     58             POP   EAX                         ; 还原EAX现场  
    01014C58     8B45 10         MOV   EAX, DWORD PTR SS:[EBP+10]         ; 以下动作退出WNDPROC,平衡堆栈,返回1
    01014C5B     33F6           XOR   ESI, ESI
    01014C5D     B8 01000000       MOV   EAX, 1
    01014C62     5F             POP   EDI
    01014C63     5E             POP   ESI
    01014C64     C9             LEAVE
    01014C65     C2 1000         RET   10

      现在不管怎么样对编辑框操作,都不会有问题了,"工具栏"都老老实实地在那儿,但是,如果我们不想它在那儿怎么办呢?当我们选择
    "查看"菜单下的"工具栏"菜单时,让它显示/隐藏工具栏.

      实现这个功能,当然要处理,"工具栏"菜单的WM_COMMAND消息  

    ;=========================================处理菜单"工具栏"消息=========================================

    010149C1   83FF 1C         CMP   EDI, 1C
    010149C4   0F85 A2000000     JNZ   01014A6C
    010149CA   A1 38980001       MOV   EAX, DWORD PTR DS:[1009838]
    010149CF   A3 80C80101       MOV   DWORD PTR DS:[101C880], EAX
    010149D4   C705 7CC80101 24000>MOV   DWORD PTR DS:[101C87C], 24
    010149DE   C705 84C80101 00000>MOV   DWORD PTR DS:[101C884], 0
    010149E8   C705 88C80101 0000F>MOV   DWORD PTR DS:[101C888], 0FF0000
    010149F2   C705 8CC80101 00AE0>MOV   DWORD PTR DS:[101C88C], 0100AE00
    010149FC   C705 90C80101 01000>MOV   DWORD PTR DS:[101C890], 1
    01014A06   C705 94C80101 00000>MOV   DWORD PTR DS:[101C894], 0
    01014A10   C705 98C80101 00000>MOV   DWORD PTR DS:[101C898], 0
    01014A1A   C705 9CC80101 00000>MOV   DWORD PTR DS:[101C89C], 0
    01014A24   50             PUSH   EAX
    01014A25   68 7CC80101       PUSH   0101C87C
    01014A2A   FF15 1C400101     CALL   DWORD PTR DS:[<&comdlg32.ChooseColorW>] ; comdlg32.ChooseColorW
    01014A30   09C0           OR     EAX, EAX
    01014A32   74 37           JE     SHORT 01014A6B
    01014A34   A1 88C80101       MOV   EAX, DWORD PTR DS:[101C888]
    01014A39   A3 74C80101       MOV   DWORD PTR DS:[101C874], EAX
    01014A3E   FF35 78C80101     PUSH   DWORD PTR DS:[101C878]
    01014A44   FF15 68100001     CALL   DWORD PTR DS:[<&GDI32.DeleteObject>]   ; GDI32.DeleteObject
    01014A4A   FF35 74C80101     PUSH   DWORD PTR DS:[101C874]
    01014A50   FF15 5D400101     CALL   DWORD PTR DS:[101405D]             ; GDI32.CreateSolidBrush
    01014A56   A3 78C80101       MOV   DWORD PTR DS:[101C878], EAX
    01014A5B   6A 01           PUSH   1
    01014A5D   6A 00           PUSH   0
    01014A5F   FF35 38980001     PUSH   DWORD PTR DS:[1009838]
    01014A65   FF15 24120001     CALL   DWORD PTR DS:[<&USER32.InvalidateRect>] ; USER32.InvalidateRect
    01014A6B   58             POP   EAX
    01014A6C   83FF 40         CMP   EDI, 40
    01014A6F   8995 F0FDFFFF     MOV   DWORD PTR SS:[EBP-210], EDX
    01014A75 - E9 49E1FEFF       JMP   01002BC3



    更改为:

    ;原有代码大部分在http://bbs.pediy.com//showthread.php?s=&threadid=23277有详细说明,此处不作解释

    010149C1   83FF 1C         CMP   EDI, 1C
    010149C4   0F85 A2000000     JNZ   01014A6C
    010149CA   50             PUSH   EAX
    010149CB   A1 38980001       MOV   EAX, DWORD PTR DS:[1009838]
    010149D0   A3 80C80101       MOV   DWORD PTR DS:[101C880], EAX
    010149D5   C705 7CC80101 24000>MOV   DWORD PTR DS:[101C87C], 24
    010149DF   C705 84C80101 00000>MOV   DWORD PTR DS:[101C884], 0
    010149E9   C705 88C80101 0000F>MOV   DWORD PTR DS:[101C888], 0FF0000
    010149F3   C705 8CC80101 00AE0>MOV   DWORD PTR DS:[101C88C], 0100AE00
    010149FD   C705 90C80101 01000>MOV   DWORD PTR DS:[101C890], 1
    01014A07   C705 94C80101 00000>MOV   DWORD PTR DS:[101C894], 0
    01014A11   C705 98C80101 00000>MOV   DWORD PTR DS:[101C898], 0
    01014A1B   C705 9CC80101 00000>MOV   DWORD PTR DS:[101C89C], 0
    01014A25   68 7CC80101       PUSH   0101C87C
    01014A2A   FF15 1C400101     CALL   DWORD PTR DS:[<&comdlg32.ChooseColorW>] ; comdlg32.ChooseColorW
    01014A30   09C0           OR     EAX, EAX
    01014A32   74 37           JE     SHORT 01014A6B
    01014A34   A1 88C80101       MOV   EAX, DWORD PTR DS:[101C888]
    01014A39   A3 74C80101       MOV   DWORD PTR DS:[101C874], EAX
    01014A3E   FF35 78C80101     PUSH   DWORD PTR DS:[101C878]
    01014A44   FF15 68100001     CALL   DWORD PTR DS:[<&GDI32.DeleteObject>]   ; GDI32.DeleteObject
    01014A4A   FF35 74C80101     PUSH   DWORD PTR DS:[101C874]
    01014A50   FF15 5D400101     CALL   DWORD PTR DS:[101405D]             ; GDI32.CreateSolidBrush
    01014A56   A3 78C80101       MOV   DWORD PTR DS:[101C878], EAX
    01014A5B   6A 01           PUSH   1
    01014A5D   6A 00           PUSH   0
    01014A5F   FF35 38980001     PUSH   DWORD PTR DS:[1009838]
    01014A65   FF15 24120001     CALL   DWORD PTR DS:[<&USER32.InvalidateRect>] ; USER32.InvalidateRect
    01014A6B   58             POP   EAX
                                       
                                                       
    ; 判断是否点击的"工具栏"菜单
             
    01014A6C   83FF 1D         CMP   EDI, 1D                       ; 是否点击的"工具栏"菜单                  
    01014A6F   0F85 A0000000     JNZ   01014B15                     ; 不是则交张程序处理

    ; 以下新加代码用于"显示","隐藏"工具栏

    01014A75   50             PUSH   EAX                         ; 保存EAX现场
    01014A76   833D 1CC70101 08   CMP   DWORD PTR DS:[101C71C], 8
    01014A7D   74 0E           JE     SHORT 01014A8D                 ; 如果当前是显示,则跳到隐藏代码
    01014A7F   C705 1CC70101 08000>MOV   DWORD PTR DS:[101C71C], 8           ; 否则显示,置显示状态为显示
    01014A89   6A 01           PUSH   1                           ; nCmdShow=SW_SHOW
    01014A8B   EB 0C           JMP   SHORT 01014A99    
    01014A8D   C705 1CC70101 00000>MOV   DWORD PTR DS:[101C71C], 0
    01014A97   6A 00           PUSH   0                           ; nCmdSHOW=SW_HIDE
    01014A99   FF35 18C70101     PUSH   DWORD PTR DS:[101C718]
    01014A9F   FF15 B0110001     CALL   DWORD PTR DS:[<&USER32.ShowWindow>]   ; ShowWindow(hWndToolbar,nCmdShow)
    01014AA5   FF35 1CC70101     PUSH   DWORD PTR DS:[101C71C]             ; 显示状态=
    01014AAB   6A 1D           PUSH   1D                         ; 菜单ID
    01014AAD   FF35 20C70101     PUSH   DWORD PTR DS:[101C720]             ; hMenu
    01014AB3   FF15 48120001     CALL   DWORD PTR DS:[<&USER32.CheckMenuItem>] ; CheckMenuItem
    01014AB9   68 04C90101       PUSH   0101C904                     ; /&RECT
    01014ABE   FF35 30980001     PUSH   DWORD PTR DS:[1009830]             ; |hWnd
    01014AC4   FF15 88110001     CALL   DWORD PTR DS:[<&USER32.GetClientRect>] ; \GetClientRect(hWnd,&RECT)
    01014ACA   833D 1CC70101 08   CMP   DWORD PTR DS:[101C71C], 8           ;
    01014AD1   75 07           JNZ   SHORT 01014ADA                 ; 不显示则不处理直接MoveWindow
    01014AD3   8305 08C90101 1E   ADD   DWORD PTR DS:[101C908], 1E         ; 如果显示,则编辑框位置下移1C
    01014ADA   6A 01           PUSH   1                           ; bRepaint=TRUE;
    01014ADC   A1 10C90101       MOV   EAX, DWORD PTR DS:[101C910]
    01014AE1   2B05 08C90101     SUB   EAX, DWORD PTR DS:[101C908]
    01014AE7   57             PUSH   EDI                         ;
    01014AE8   56             PUSH   ESI                         ; 保存寄存器现场
    01014AE9   8BF8           MOV   EDI, EAX
    01014AEB   A1 0CC90101       MOV   EAX, DWORD PTR DS:[101C90C]
    01014AF0   2B05 04C90101     SUB   EAX, DWORD PTR DS:[101C904]
    01014AF6   8BF0           MOV   ESI, EAX                     ;    
    01014AF8   57             PUSH   EDI                         ; rc.bottom-rc.top    
    01014AF9   56             PUSH   ESI                         ; rc.right-rc.left
    01014AFA   FF35 08C90101     PUSH   DWORD PTR DS:[101C908]             ; rc.right
    01014B00   FF35 04C90101     PUSH   DWORD PTR DS:[101C904]             ; rc.left
    01014B06   FF35 38980001     PUSH   DWORD PTR DS:[1009838]             ; hWndEdit
    01014B0C   FF15 20120001     CALL   DWORD PTR DS:[<&USER32.MoveWindow>]   ; MoveWindow
    01014B12   5E             POP   ESI                        
    01014B13   5F             POP   EDI                        
    01014B14   58             POP   EAX                         ; 还原寄存器现场

    ;原有代码
    01014B15   83FF 40         CMP   EDI, 40
    01014B18   8995 F0FDFFFF     MOV   DWORD PTR SS:[EBP-210], EDX         ; 被修改的代码还原
    01014B1E - E9 A0E0FEFF       JMP   01002BC3                     ; 交给原程序处理


      现在保存所有的修改,然后运行程序,"工具栏"已经能正常工作了,并能设置检查标志.是不是一切都OK了呢?
     
      现在如果我们点击"自动换行"或者"状态栏"菜单,编辑框跑到工具栏下面去,这个是因为记事本对"自动换行"和"状态栏"两个菜单
    命令的处理,也是默认把编辑框放到客户区最高处的,如果工具栏此是时显示状态的,则会出现上面的BUG



      所以必须处理这两个命令消息.
     
    ;========================================处理菜单"自动换行"(ID=20)消息=====================================

    ; 跟踪WM_COMMAND消息处理过程

    01002BBE   .- E9 FE1D0100     JMP   010149C1                     ; 这是以前修改的不用理它,一会儿会跳回来
    01002BC3     90           NOP
    01002BC4     90           NOP
    01002BC5     90           NOP
    01002BC6     90           NOP
    01002BC7   . 0F8F F9060000   JG     010032C6
    01002BCD   . 0F84 DB060000   JE     010032AE
    01002BD3   . 83FF 15       CMP   EDI, 15                       ; Switch (cases 1..21)
    01002BD6   . 0F8F CE020000   JG     01002EAA                     ; 因为20>15此处必跳
    ;................
    ;................

    ;01002BD6跳到此处

    01002EAA   > \83FF 1A       CMP   EDI, 1A                       ; 20>1A 此处必跳
    01002EAD   . 0F8F 66010000   JG     01003019
    ;................
    ;................

    ;01002EAD跳到此处

    01003019   > \6A 1B         PUSH   1B                           ;
    0100301B   . 5B           POP   EBX                         ; EBX=1B
    0100301C   . 2BFB         SUB   EDI, EBX                       ; wParam-=1B
    0100301E   . 0F84 F7010000   JE     0100321B                       ;
    01003024   . 83EF 05       SUB   EDI, 5                       ; wParam-=5;
    01003027   . 0F84 11010000   JE     0100313E                       ; wParam==20(是"自动换行"菜单") 跳  
    ;................
    ;................


    ;01003027跳到此处,"自动换行"菜单的处理代码

    0100313E   > \A1 50980001     MOV   EAX, DWORD PTR DS:[1009850]         ; Case 20 of switch 01002BD3
    01003143   . F7D8         NEG   EAX
    01003145   . 1BC0         SBB   EAX, EAX
    01003147   . 25 00001000     AND   EAX, 100000
    0100314C   . 05 04012050     ADD   EAX, 50200104
    01003151   . 50           PUSH   EAX                         ; /Arg1
    01003152   . E8 EA290000     CALL   01005B41                     ; \01005B41,处理自动换行菜单
    ;................
    ;................

    ;跟到这里,发现用户选择了"自动换行"菜单,记事本会在这里重新创建编辑框,搞不懂为什么要这么做....

    01005C11 |. 57           PUSH   EDI                         ; /lParam
    01005C12 |. FF35 80AB0001   PUSH   DWORD PTR DS:[100AB80]             ; |hInst = 01000000
    01005C18 |. 6A 0F         PUSH   0F                         ; |hMenu = 0000000F
    01005C1A |. FF35 30980001   PUSH   DWORD PTR DS:[1009830]             ; |hParent = 009509CA ('无标题 - 记事本',class='Notepad')
    01005C20 |. FF75 D4       PUSH   DWORD PTR SS:[EBP-2C]             ; |Height 高度
    01005C23 |. FF75 D0       PUSH   DWORD PTR SS:[EBP-30]             ; |Width
    01005C26 |. 57           PUSH   EDI                         ; |Y     最高位置,默认是0
    01005C27 |. 57           PUSH   EDI                         ; |X = 0
    01005C28 |. FF75 08       PUSH   DWORD PTR SS:[EBP+8]             ; |Style
    01005C2B |. 68 94130001     PUSH   01001394                     ; |WindowName = ""
    01005C30 |. 68 94170001     PUSH   01001794                     ; |Class = "Edit"
    01005C35 |. 68 00020000     PUSH   200                         ; |ExtStyle = WS_EX_CLIENTEDGE
    01005C3A |. FF15 E0110001   CALL   DWORD PTR DS:[<&USER32.CreateWindowExW>>; \CreateWindowExW
    ;................
    ;................


        分析以上代码,我们只需要更改创建编辑框时的两个参数,编辑框高度和编辑框的最高位置,在这里是这两句

    ;需要修改的代码

    01005C20 |. FF75 D4       PUSH   DWORD PTR SS:[EBP-2C]             ; |高度
    01005C26 |. 57           PUSH   EDI                         ; |最高位置,默认是0

        如果当前工具栏状态是"显示",则需要更改它们,如果不是,则不需要更改.必须修改跳转到我们的判断代码

       
    ;在这里我们修改 01005C1A,因为必须在高度入栈之前修改它们.多余字节以NOP填充
     
    01005C1A     - E9 91F00000     JMP   01014CB0
    01005C1F     90           NOP
    01005C20   |. FF75 D4       PUSH   DWORD PTR SS:[EBP-2C]             ; 高度
    01005C23     FF75 D0       PUSH   DWORD PTR SS:[EBP-30]
    01005C26     57           PUSH   EDI                         ; 最高位置
    01005C27     57           PUSH   EDI
    01005C28     FF75 08       PUSH   DWORD PTR SS:[EBP+8]
    01005C2B   |. 68 94130001     PUSH   01001394                     ; |WindowName = ""
    01005C30   |. 68 94170001     PUSH   01001794                     ; |Class = "Edit"
    01005C35   |. 68 00020000     PUSH   200                         ; |ExtStyle = WS_EX_CLIENTEDGE
    01005C3A   |. FF15 E0110001   CALL   DWORD PTR DS:[<&USER32.CreateWindowExW>>; \CreateWindowExW    
    ;................
    ;................

    ;01005C1A跳到此处,用于判断是否需要更改高度与最高位置

    01014CB0     A3 84C80101       MOV   DWORD PTR DS:[101C884], EAX         ; 保存EAX现场,这里不能PUSH EAX
    01014CB5     FF35 30980001     PUSH   DWORD PTR DS:[1009830]             ; 被修改的代码还原
    01014CBB     833D 1CC70101 08   CMP   DWORD PTR DS:[101C71C], 8           ; 开始判断工具栏显示状态
    01014CC2     75 0F           JNZ   SHORT 01014CD3                 ; 不相等则跳
    01014CC4     90             NOP
    01014CC5     90             NOP
    01014CC6     90             NOP
    01014CC7     90             NOP
    01014CC8     836D D4 1C       SUB   DWORD PTR SS:[EBP-2C], 1C           ; 显示则高度减去1C
    01014CCC     B8 1C000000       MOV   EAX, 1C                       ; 最高位置+1C(往下移)
    01014CD1     EB 02           JMP   SHORT 01014CD5
    01014CD3     33C0           XOR   EAX, EAX                     ; 不显示则不修改直接入栈
    01014CD5     FF75 D4         PUSH   DWORD PTR SS:[EBP-2C]
    01014CD8     FF75 D0         PUSH   DWORD PTR SS:[EBP-30]            
    01014CDB     50             PUSH   EAX                         ; 最高位置入栈
    01014CDC     57             PUSH   EDI
    01014CDD     A1 84C80101       MOV   EAX, DWORD PTR DS:[101C884]         ; 还原EAX现场
    01014CE2   - E9 410FFFFF       JMP   01005C28                     ; 跳回原来的创建编辑框代码



    ;=======================================处理菜单"状态栏"(==1B)消息========================================

    ;跟踪到WNDPROC里处理"状态栏"菜单的代码

    01003019   > \6A 1B         PUSH   1B  
    0100301B   . 5B           POP   EBX                         ; EBX=1B
    0100301C   . 2BFB         SUB   EDI, EBX                     ; wParam-=1B
    0100301E   . 0F84 F7010000   JE     0100321B                     ; 点击了"状态栏"此处必跳
    ;................
    ;................

    ;从0100321b一路跟踪,可以来到这儿

    01003273   . 2B85 E4FDFFFF   SUB   EAX, DWORD PTR SS:[EBP-21C]
    01003279   . 33F6         XOR   ESI, ESI
    0100327B   . 50           PUSH   EAX                         ; /Arg2==hegiht
    0100327C   . 8B85 E8FDFFFF   MOV   EAX, DWORD PTR SS:[EBP-218]         ; |
    01003282   . 2B85 E0FDFFFF   SUB   EAX, DWORD PTR SS:[EBP-220]         ; |
    01003288   . 46           INC   ESI                         ; |
    01003289   . 50           PUSH   EAX                         ; |Arg1=width
    0100328A   . 8935 40980001   MOV   DWORD PTR DS:[1009840], ESI         ; |
    01003290   . E8 4BE7FFFF     CALL   010019E0                     ; \Notepad_.010019E0
    ;................
    ;................

    01001A01   |. 2305 E0A60001   AND   EAX, DWORD PTR DS:[100A6E0]
    01001A07   |. 6A 01         PUSH   1                           ; /Repaint = TRUE
    01001A09   |. 2BC8         SUB   ECX, EAX                     ; |
    01001A0B   |. 51           PUSH   ECX                         ; |Height======从这里跳=========
    01001A0C   |. FF75 08       PUSH   DWORD PTR SS:[EBP+8]             ; |Width
    01001A0F   |. 6A 00         PUSH   0                           ; |Y = 0
    01001A11   |. 6A 00         PUSH   0                           ; |X = 0
    01001A13   |. FF35 38980001   PUSH   DWORD PTR DS:[1009838]             ; |hWnd = 01680E64 (class='Edit',parent=01A60E30)
    01001A19   |. FF15 20120001   CALL   DWORD PTR DS:[<&USER32.MoveWindow>]   ; \MoveWindow
    01001A1F   |. 5D           POP   EBP
    01001A20   \. C2 0800       RET   8


    01001A0B     - E9 F0320100     JMP   01014D00                     ;==========跳到自己的代码========
    01001A10     90           NOP
    01001A11   |. 6A 00         PUSH   0                           ; |X = 0
    01001A13   |. FF35 38980001   PUSH   DWORD PTR DS:[1009838]             ; |hWnd = NULL
    01001A19   |. FF15 20120001   CALL   DWORD PTR DS:[<&USER32.MoveWindow>]   ; \MoveWindow
    01001A1F   |. 5D           POP   EBP
    01001A20   \. C2 0800       RET   8


    ;01001A0B跳到此处,根据显示状态处理编辑框高度与最高位置

    01014D00     833D 1CC70101 08   CMP   DWORD PTR DS:[101C71C], 8
    01014D07     75 12           JNZ   SHORT 01014D1B                 ; 如果当前是不显示的则不处理
    01014D09     90             NOP
    01014D0A     90             NOP
    01014D0B     90             NOP
    01014D0C     90             NOP
    01014D0D     83E9 1C         SUB   ECX, 1C                       ; 当前是显示的则编辑高度减1C
    01014D10     51             PUSH   ECX                         ; 高度入栈
    01014D11     FF75 08         PUSH   DWORD PTR SS:[EBP+8]             ; |Width
    01014D14     6A 1C           PUSH   1C                         ; 编辑框最高位置设为1C
    01014D16   - E9 F6CCFEFF       JMP   01001A11                     ; 跳回原处
    01014D1B     51             PUSH   ECX
    01014D1C     FF75 08         PUSH   DWORD PTR SS:[EBP+8]             ; |Width当前是不显示的        
    01014D1F     6A 00           PUSH   0                           ; 则编辑框最高位置为0
    01014D21   - E9 EBCCFEFF       JMP   01001A11                     ; 跳回原处

      现在一切都没有问题了如图
     
     
     
      ;=====THE !END======
     
    ;=========================================QQ:41086722=================================================

    发现任何问题或者有任何建议请交流...
    附件下载:notepad_modified_toolbar.rar


    --------------------------------------------------------------------------------

    标 题: 答复
    作 者: qyc
    时 间: 2006-03-30 22:03
    详细信息:


    爽//精华//学习啊//近连几日学习楼主的文章来/
    再一次更新楼主修改版/小Q再一次以17521方法加入TOP与窗口透明功能
    上一次是以http://bbs.pediy.com/showthread.php?threadid=22877
    加上TOP/保留
    这次是加17521写的DLL功能插件(窗口透明),在完全不知到17521的方法下加入/
    过程序引用peansen的:记事本功能增加方案
    http://bbs.pediy.com/showthread.php?threadid=17376
    取精华处:
    导出这个函数,注意这个函数是_cdecl的。原因后面我会讲述。
    中断RegisterClassExW函数,很容易到这里
    01004521   |. 8945 FC       mov dword ptr ss:[ebp-4],eax
    01004524   |. 8D45 D0       lea eax,dword ptr ss:[ebp-30]
    01004527   |. 50           push eax                           ; /pWndClassEx,下面的mov是对其进行赋值
    01004528   |. C745 F4 01000000 mov dword ptr ss:[ebp-C],1               ; |
    0100452F   |. 8975 E4       mov dword ptr ss:[ebp-1C],esi             ; |
    01004532   |. C745 F8 20900001 mov dword ptr ss:[ebp-8],NOTEPAD.01009020     ; |UNICODE "Notepad"
    01004539     C745 D8 29340001 mov dword ptr ss:[ebp-28],NOTEPAD.01003429//这是消息处理过程的赋值
    01004540   |. C745 F0 06000000 mov dword ptr ss:[ebp-10],6               ; |
    01004547   |. 897D D4       mov dword ptr ss:[ebp-2C],edi             ; |
    0100454A   |. 897D DC       mov dword ptr ss:[ebp-24],edi             ; |
    0100454D   |. 897D E0       mov dword ptr ss:[ebp-20],edi             ; |
    01004550   |. FF15 D0110001   call dword ptr ds:[<&USER32.RegisterClassExW>] ; \RegisterClassExW

    我想这个结构在windows编程中是很重要的一部分,那个WndClassEx结构看看msdn就更清楚了。
    接着我们看看消息处理过程部分
    01003421   \. C2 0800       retn 8
    01003424     CC           int3-------------------将从这里开始消息处理,只是一个简单的call
    01003425     CC           int3
    01003426     CC           int3
    01003427     CC           int3
    01003428     CC           int3
    01003429     8BFF         mov edi,edi-------------消息处理过程是从这里开始的
    0100342B   /. 55           push ebp
    0100342C   |. 8BEC         mov ebp,esp
    0100342E   |. 51           push ecx
    0100342F   |. 51           push ecx
    01003430   |. 56           push esi
    01003431   |. 8B75 0C       mov esi,dword ptr ss:[ebp+C]
    01003434   |. 83FE 1C       cmp esi,1C                         ; Switch (cases 2..8001)

    利用5个int3和mov edi,edi共7个字节,改写一个call指令
    ----------------------------------------------关于mov edi,edi--抄的
    MOV EDI,EDI is indeed a 2-byte no-op that is there to enable hot-patching.   It enables the application of a hot-fix to a function without a need for a reboot, or even a restart of a running application.   Instead, at runtime, the 2-byte NOP is replaced by a short jump to a long jump instruction that jumps to the hot-fix function.   A 2-byte instruction is required so that when patching the instruction pointer will not point in a middle of an instruction.
    ------------------------------------------------------------------------
    call dword ptr [1013018](共六个,后面不一个nop)
    然后修改01004539处的赋值mov dword ptr ss:[ebp-28],NOTEPAD.01003429(改成01003424)

    用LordPE查看17521的plug.dll
    发现只导入一个Plug含数
    现在在要改的版本加入/调用接口:00024032(以你的机子而定)
    以peansen的:记事本功能增加方案即可
    现在这个记事本真正的好用多了/现在正与楼主谈给记事本加个自动隐藏功能呢/


    --------------------------------------------------------------------------------

    ©2000-2007 PEdiy.com All rights reserved.
    By PEDIY
    顶端 Posted: 2007-03-05 17:01 | [3 楼]
    yinx



    性别: 帅哥 状态: 该用户目前不在线
    等级: 人见人爱
    家族: 丢丢
    发贴: 2333
    威望: 0
    浮云: 1260
    在线等级:
    注册时间: 2006-09-15
    最后登陆: 2009-05-11

    5come5帮你背单词 [ angry /'æŋgri/ a. 发怒的,愤怒的 ]


    不知道楼上指的是哪一个链接?
    顶端 Posted: 2007-03-05 22:28 | [4 楼]
    yinx



    性别: 帅哥 状态: 该用户目前不在线
    等级: 人见人爱
    家族: 丢丢
    发贴: 2333
    威望: 0
    浮云: 1260
    在线等级:
    注册时间: 2006-09-15
    最后登陆: 2009-05-11

    5come5帮你背单词 [ watchful /'wotful/ a. 警惕的,注意的 ]


    我只有"知道SHELL CODE是什么东西"的水平.不会用,我还有需要[屏蔽],呵呵.
    顶端 Posted: 2007-03-06 22:38 | [5 楼]
    我来我网·5come5 Forum » 程序员之家

    Total 0.013722(s) query 6, Time now is:11-23 18:39, Gzip enabled
    Powered by PHPWind v5.3, Localized by 5come5 Tech Team, 黔ICP备16009856号