作者:大菜一号
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],前提先把该函数的参数压入栈中!
-----------------------------------------------
成功!!
看成功截图吧!
激活窗口为后面的窗口了,不过记事本程序还是在前面,呵呵~~
[课程]Android-CTF解题方法汇总!
上传的附件: