• 标 题:给应用程序加个弹出对话框
  • 作 者:二点
  • 时 间:2003年10月12日 08:12
  • 链 接:http://bbs.pediy.com

其实看雪的一些前辈已经学过了相关的文章,由于本人技术很菜,下面如果有写得不足之处还请指出.

*********************
作者:二点(BrOkeN)
*********************
工具:
PEditor
stud-PE
HIEW
Winhex

实验对象:Window 98的记事本(notepad.exe).
*********************
描述:
我们要给一个程序加一个对话框首先要有:
1.在程序中多余的空间,这样可以用来加入我们的代码,对话框标题和内容的文本.
2.要有MessageBox或MessageBoxA函数的地址,MessageBoxA位于user.dll里面,如果程序本身已经引入了这个函数,我们找到该函数在程序里面的地址就可以直接可以在程序里调用它了(记事本里已经引入了MessageBoxA这个函数,关于如何知道请见下面),如果程序本身没有引入了这个函数,那么我们就要手动在输入表(import table)里加入该函数(这里本文不讨论,详细可以见一些打QQ补丁的文章,看学精华里有).
3.在汇编中调用一个函数,首先先将函数参数压栈,最后一个参数先压栈,然后是最第二个...最后是第一个参数压栈,压栈在汇编里是这样表达的:
push xxx
xxx 可以是一个常数,也可以是一个函数参数的地址.

MessageBoxA的函数模型.
int MessageBox
( HWND hWnd, // 窗口句柄,一般不需要,我们可以设为0,
LPCTSTR lpText, // 对话框的内容. 
LPCTSTR lpCaption, // 对话宽的标题,
UINT uType //对话框的风格.

***********************
手术过程:
我们先来看看notepad.exe的块表;用PEditor打开notepad .exe,点击右下角的"sections",看到:
 Section    Virtual Size   Virtual Offset   Raw Size    Raw Offset    Characteristics 
 .text       00003FD4        00001000       00004000     00001000       60000020 
 .data       0000084C        00005000       00001000     00005000       C0000040
 .idata      00000E02        00006000       00001000     00006000       40000040
 .rsrc       00004FB8        00007000       00005000     00007000       40000040      
 .reloc      00000AC6        0000C000       00001000     0000C000       40000040

从这里我们可以知道notepad.exe的RVA=Offset(Virtual Offset=Raw Offset),这样我们下面的一些操作就可以省去要用工具把Offset (文件偏移)转换为RVA(相对虚拟地址)或VA(虚拟地址)的麻烦了,如果不相同就要将Offset转换为RVA,VA)
看sections除了了解一下程序本身外,也为了要找到一些空余的空间可以用来加入我们的代码,因为一般情况下在每一个段的间缝处都可以找到一些空余的空间,我们可以看到.data(数据段)是从00005000开始的,用Winhex打开,跳到Offset 00005000,向下翻果然在004052A0开始发现有一大段空间(注意:如果在程序中找不到空余的空间,那么可以用一些工具来增加一些空间,比如:topo ) :

000052A0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052B0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052C0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052D0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052E0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052F0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005300:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005310:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005320:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005330:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005340:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00

现在我们选择004052E0来加入我们的对话宽的标题.
选择00405300来加入我们的对话框的内容. 

000052A0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052B0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052C0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052D0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000052E0:  4D 65 73 73-61 67 65 42-6F 58 21 00-00 00 00 00  MessageBoX!
000052F0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005300:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005310:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005320:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00005330:  48 65 48 65-21 54 68 69-73 20 4E 6F-74 65 70 61  HeHe!This Notepa
00005340:  64 20 77 61-73 20 70 61-74 63 68 65-64 20 42 79  d was patched By
00005350:  20 42 72 4F-6B 65 4E 2E-0A 63 6E 62-72 6F 6B 65   BrOkeN.cnbroke
00005360:  6E 40 68 61-63 6B 65 72-6D 61 69 6C-2E 63 6F 6D  n@hackermail.com
现在我们搞定了对话宽的标题和对话框的内容,接着的就是要找MessageBoxA在notepad.exe中调用的地址, 用stud-PE打开notepad.exe选择functions,将选中左下角最左的两个选择框,展开user.dll可以看到:
+MessageBoxA ord:428 rva:0064AC
那么MessageBoxA的虚拟地址就是(VA)=RVA(相对虚拟地址) + imagebase(基址)=000064AC+00400000=004064AC
所以,我们的代码中Call dword [004064AC]就等于Call MessageBoxA。

现在就可以来写我们的代码了,我把代码放在Offset=000053A0处,我构造的代码如下;
push 00000000         //对话框的风格,0为只有一个确定(OK)按键,1为一个确定和取消按键,其它请参考编                         程书籍。
push 004052E0         // 对话宽的标题.注意:这里表示的都是虚拟地址,我们上面在文件中添加文本的是                         文件的Offset,如果程序的Offset <> RVA,那么就要用工具进行转换了,PEditor                         有这个功能。
push 00405330         // 对话框的内容. 
push 00000000         // 窗口句柄,一般不需要,我们可以设为0
Call dword [004064AC]  //调用MessageBoxA.
jmp 10CC          //执行代码后跳到notepad入口点(可以在PEditor看到Entry Point=000010CC)

现在手术就要成功了,用hiew打开notepad,f4选择decode 模式,按f5,输入53A0,enter来到53A0处,按f3,enter后
输入上面代码,完成后esc,再按f9更新:

004053A0: 6A00                         push        000
004053A2: 68E0524000                   push        0004052E0  ----- (1)
004053A7: 6830534000                   push        000405330  ----- (2)
004053AC: 6A00                         push        000
004053AE: FF15AC644000                 call        MessageBoxA ;USER32.dll
004053B4: E913BDFFFF                   jmp        .0004010CC  ----- (3)

现在要做的就是让程序运行的从我们的代码处开始运行,也就是要把程序的入口点改到我们的代码处,先执行我们的代码然后在跳到程序原来的入口点,用PEditor打开notepad将Entry Point=000010CC改为Entry Point=000053A0就大功告成了,运行程序看看,哈哈,对话框是不是跳出来了啊,好开心