首页
社区
课程
招聘
[网络漫步兄弟 求助贴(解决)] 把记事本置顶
发表于: 2007-8-3 15:06 21283

[网络漫步兄弟 求助贴(解决)] 把记事本置顶

2007-8-3 15:06
21283

作者:大菜一号
     bbs.pediy.com
     kkxlnbukn@126.com

看见有论坛朋友(http://bbs.pediy.com/showthread.php?t=48962)求助把记事本改为置顶的,中午回去搞一会儿,所以有了下文!嘿嘿...

改为置顶方法多种,我用SetWindowPos函数,该函数的在msdn中定义如下:
BOOL SetWindowPos(
  HWND hWnd,             // handle to window
  HWND hWndInsertAfter,  // placement-order handle
  int X,                 // horizontal position
  int Y,                 // vertical position
  int cx,                // width
  int cy,                // height
  UINT uFlags            // window-positioning options
);
需要下面的参数:
1、要设置窗口的句柄;
2、设置的状态;
3、设置x坐标;
4、设置y坐标;
5、设置窗口宽度;
6、设置窗口高度;
7、设置标志

调用这个函数需要的参数,我们必须拥有,所以下面来一个个得到:
1、窗口句柄
我们知道CreateWindow函数创建完窗口之后会返回窗口的句柄,用OD载入记事本程序,ctrl+n打开导入函数表,找到CreateWindowExW(为Unicode扩展函数),右键在所有参考上下断点,可以看到下了两个断点!f9运行,断在下面:

01004694  |.  FF15 E0110001 call    dword ptr [<&USER32.CreateWindow>; \CreateWindowExW<-断在这里
0100469A  |.  8BD0          mov     edx, eax             //该函数的返回值,也就是句柄,在eax里面;
0100469C  |.  3BD3          cmp     edx, ebx
0100469E  |.  8915 30980001 mov     dword ptr [1009830], edx
010046A4  |.  8915 A4A40001 mov     dword ptr [100A4A4], edx         ;  mov     edx, eax
010046AA  |.  0F84 FE020000 je      010049AE                         ;  cmp     edx, ebx

记下0100469a这个地址,待会用来跳到全0处,已知道程序执行到这句代码时,eax为主窗口句柄

2、设置的状态
查看一下msdn,知道我们要的是置顶状态:
HWND_TOPMOST
Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.
就设置HWND_TOPMOST这个标志,其定义为一个宏,所以我们查看一下常数表:

#define HWND_TOPMOST    ((HWND)-1)

HWND_TOPMOST实际为-1;

3、设置x坐标
   设为0,有关于最后一个参数的标志,所以设为0
4、设置Y坐标
   设为0
5、设置宽度
   设为0
6、设置高度
   设为0
7、设置标志
  刚才说过,前面四个参数有关于这个标志,关于这个参数,标志很多,我们要用到的是SWP_NOSIZE不改变原窗口尺寸,SWP_NOMOVE不移动窗口!所以前面四个参数不用了!具体介绍请看msdn;

用peid在.text区上找全0,我找到的是100874e这个地方!

OK,已具备条件,下面打补丁代码:
----------------------------------------------
ctrl+g到0100469a(是窗口句柄为eax时的代码地址)
0100469A  |.  8BD0          mov     edx, eax<-到这里,跳到我们的代码处,改为jmp 100874e

ps:"jmp 100874e"这句代码为5个字节,所以会把
0100469A  |.  8BD0          mov     edx, eax            
0100469C  |.  3BD3          cmp     edx, ebx
0100469E  |.  8915 30980001 mov     dword ptr [1009830], edx
这三句为盖了,所以先行记下这三句代码,以便待会恢复!·

--------------------------------------------
全0处的补丁代码如下:
0100874E   > \60            pushad                //保护现场一下
0100874F   .  90            nop
01008750      8BD0          mov     edx, eax                  //恢复上面被盖掉的代码
01008752      3BD3          cmp     edx, ebx
01008754      8915 30980001 mov     dword ptr [1009830], edx
0100875A      90            nop
0100875B      6A 03         push    3//函数最后一个参数,为什么是3,因为SWP_NOSIZE和SWP_NOMOVE两个参数分别被定义为1和2,所以1|2,呵呵!
0100875D      6A 00         push    0//高度为0
0100875F      6A 00         push    0//宽度为0
01008761      6A 00         push    0//y坐标为0
01008763      6A 00         push    0//x坐标为0
01008765      6A FF         push    -1//HWND_TOPMOST查看常数表为-1
01008767      52            push    edx //上面把句柄传到edx了,这里直接传参edx
01008768      FF15 1A300101 call    dword ptr [<&User32.SetWindowPos>;  USER32.SetWindowPos//调用SetWindowPos函数
0100876E   .  61            popad                //恢复一下现场
0100876F   .^ E9 30BFFFFF   jmp     010046A4     //跳回去执行

---------------------------------------------
调用SetWindowPos函数
注意,我们OD载入后,ctrl+n,发现程序并没有调用SetWindowPos这个函数,所以我们必须手动添加这个函数,并得到他的rva,!
因为这篇文章并不在家里写的,所以手头上并没有lord pe,呵呵,凭记忆讲一下,就不截图了!

我们知道SetWindowPos这个函数在user32.dll这个动态链接库中,所以,把记事本程序载入pe编辑器!
可以看找一个映像地址,为1000000,记住它,和rva配合着用!
点击“目录”,找到导入表,点击后面的“...”,
在上面的列表框上找到user32.dll,点击一下可以在下面的列表框看到程序所从user32.dll导入的函数,并没有SetWindowPos,所以我们添加一个,在上面的列表框上点击右键,选择“添加导入函数”,dll输入框上输入SetWindowPos函数所在的dll,也就是user32.dll,下面就要输入要添加的函数了,就是"SetWindowPos",再点击'+'按钮后,再点确定,就成功添加了~
用工具添加当然比手动来得简单,不过就是会多出一个“user32.dll"就是了,呵呵呵!
在新加的user32.dll上单击一下,下面的函数列表可以看到刚添加的SetWindowPos函数,最左边的就是rva了!为0001301a
我们知道映像地址是10000000,所以加上rva,就是0101301a,这个就是刚添加的SetWindowPos函数的地址
就可以这么调用,call dword ptr[0101301a],前提先把该函数的参数压入栈中!
-----------------------------------------------

成功!!
看成功截图吧!
激活窗口为后面的窗口了,不过记事本程序还是在前面,呵呵~~


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (51)
雪    币: 707
活跃值: (1301)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
2
呵呵,学习了...
2007-8-4 10:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
严重支持一下大菜兄弟
学习 支持
2007-8-4 10:46
0
雪    币: 623
活跃值: (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
4
支持大头菜!!!!!!!
2007-8-4 15:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
基本上看不懂。。。。。。。。。。。
2007-8-4 15:22
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
verygood……
2007-8-4 18:38
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
7
大菜又出手了,支持哈~
2007-8-4 19:30
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不错的说,收起来先。。。
2007-8-4 19:30
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
谢谢大菜一号,大菜万岁万岁万万岁!
2007-8-5 10:53
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
10
那我系不系该改口叫自己"朕"了``
哈哈,开玩笑开玩笑
不知道你把记事本置顶有啥用?
2007-8-5 11:10
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
大菜老师我想用置顶的记事本替换windows下的notepad.exe为什么只能运行一次有效?
替换后头一次运行有效,刷新一下第二次运行就不能置顶了,这是什么道理。
当然不替换系统的记事本是可以正常置顶的。
2007-8-5 11:49
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
12
呵呵,这也是正常的,记事本程序是系统的,大概系统会自动还原,重启之后进入安全模式,再替换吧!
2007-8-5 11:56
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
学习 学习   ......
2007-8-5 13:17
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
谢谢楼主,辛苦了,学习中。
2007-8-5 13:52
0
雪    币: 245
活跃值: (469)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
楼主您好:

 我把调用SetWindowPos中的代码中的NOP去掉了,改成了这样,却不能运行了!

0100874E   > \60            pushad
0100874F   .  8BD0          mov     edx, eax
01008751   ?  3BD3          cmp     edx, ebx
01008753   ?  8915 30980001 mov     [1009830], edx
01008759   ?  6A 03         push    3
0100875B   .  6A 00         push    0                                ; /Flags = 0
0100875D   .  6A 00         push    0                                ; |Height = 0
0100875F   .  6A 00         push    0                                ; |Width = 0
01008761   .  6A 00         push    0                                ; |Y = 0
01008763   .  6A FF         push    -1                               ; |X = FFFFFFFF (-1.)
01008765   .  52            push    edx                              ; |InsertAfter
01008766   ?  E8 AFA80000   call    <&USER32.SetWindowPos>
0100876B   ?  61            popad
0100876C   ?^ E9 33BFFFFF   jmp     010046A4

却无法运行,为什么?? 我只不过去了两个NOP?
我一直想不通.
2007-8-6 18:22
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
学习中,lz加油!!!!
2007-8-6 18:47
0
雪    币: 208
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
呵呵果然够帅,写的够详细,支持
2007-8-6 18:50
0
雪    币: 213
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
老大你对Windows的函数很了解!佩服!
2007-8-6 19:52
0
雪    币: 22
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
游戏外挂上又有新玩法了,(*^__^*) 嘻嘻……
2007-8-7 00:22
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
20
呵呵,nop是在写入汇编指令时,选中"用nop填充",所以会出现的一个字节的机器码,也就是0x90

我们能改的只是机器码,因为机器码和汇编指令一一对应,所以也可以直接改汇编指令,但我们不可以改变原程序的大小,所以要选中"用nop填充",你去掉了两个nop,等于去掉了两个字节,改变了原程序的大小,不能运行也是正常的!
比如 mov ax,0123h
这句指令有五个字节,nop的话,od中会出现五个nop,也就是五个0x90,绝不会出现两个或不等于五个的0x90

同理``呵呵
mov ax,0123h<-----这句在Od中nop之后,就变成下面这样

005A54CB      90            nop
005A54CC      90            nop
005A54CD      90            nop
005A54CE      90            nop
005A54CF      90            nop
五个0x90
2007-8-7 09:27
0
雪    币: 245
活跃值: (469)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
谢谢楼主的回复:
    可是我并没有删除任何字节:

0100874F   .  90            nop      <-----------我用下面的mov edx,eax.....把这个覆盖掉了
01008750      8BD0          mov     edx, eax                  //恢复上面被盖掉的代码
01008752      3BD3          cmp     edx, ebx
01008754      8915 30980001 mov     dword ptr [1009830], edx
0100875A      90            nop   <-------------------这一句也是这样,用下面的.....
我知道NOP的意思为空操作 可为什么去了掉我的程序却运行不起来.
2007-8-7 11:06
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
22
不太清楚你的意思
你是说
0100874F   .  90            nop      <-----------这改为mov edx,eax?
01008750      8BD0          mov     edx, eax                  //恢复上面被盖掉的代码
01008752      3BD3          cmp     edx, ebx
01008754      8915 30980001 mov     dword ptr [1009830], edx

你看一下,pushad这指令有一字节,
2007-8-7 11:24
0
雪    币: 245
活跃值: (469)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
23
pushad 有两个指令??  60 90??

0100874E   > \60               pushad
0100874F   .  90               nop
01008750   .  8BD0             mov     edx, eax
01008752   .  3BD3             cmp     edx, ebx
01008754   .  8915 30980001    mov     [1009830], edx
0100875A   .  6A 03            push    3
0100875C   ?  6A 00            push    0
0100875E   ?  6A 00            push    0
01008760   ?  6A 00            push    0
01008762   ?  6A 00            push    0
01008764   ?  6A FF            push    -1
01008766   ?  52               push    edx
01008767   .  E8 AEA80000      call    <&USER32.SetWindowPos>           ; |hWnd
0100876C   ?  61               popad
0100876D   ?  90               nop
0100876E   .^ E9 31BFFFFF      jmp     010046A4
01008773   ?  90               nop

我现在的跳转是这个样子的,程序运行不起来,我跟踪了一下,在调用SetWindowPos中出错了,
程序被中止, 我察看了一下堆栈:

这是执行到: 01008767   .  E8 AEA80000      call    <&USER32.SetWindowPos>
一句的.   EIP=01008767

0006FDE8   00000000
0006FDEC   0069060E
0006FDF0   FFFFFFFF
0006FDF4   00000000
0006FDF8   00000000
0006FDFC   00000000
0006FE00   00000000
0006FE04   00000003
0006FE08   77D19D69  USER32.LoadCursorW

F8执行说是异常,然后就中止了.  不知为什么? 
2007-8-7 11:36
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
24
不好意思,我搞错,
是一个字节,0x60
2007-8-7 11:48
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
25
请把你改的代码贴出来`
2007-8-7 11:49
0
游客
登录 | 注册 方可回帖
返回
//