首 页论 坛破解QQ密码领免费QQ秀QQ等级修改盗取QQ教程QQ密码暴力破解QQ空间完整做法免费开所有QQ业务
设为首页
加入收藏
联系我们
您当前的位置:下载者 -> 编程设计 -> 文章内容
栏目导航
· QQ文章 · 综合文章
· 安全文章 · 新闻动态
· 实用技巧 · 入侵检测
· 木马病毒 · 电脑常识
· 编程设计 · 网络技术
相关文章

在可执行文件中添加菜单项
发布时间:2008-2-16 12:14:19

任务: 添加允许的‘打开’ 菜单项和变灰的‘关闭’ 菜单项在退出菜单项之前。 

工具: hex editor (例如 Hiew), 大脑(如你平常一般使用) 

Ok, 开始工作 

使用你熟悉和惯用的十六进制编辑工具(如Hiew)打开Hello.exe, 直接到资源区(.rsrc). 如果使用hiew 则按F8, 再按F6,进入.rsrc。(译注:使用EXESCOPE 参见.rsrc中的pointer to RAW data也表示这个偏移值). 这样,你就看到了IMAGE_RESOURCE_DIRECTORY(资源目录),它的结构如下: 

typedef struct _IMAGE_RESOURCE_DIRECTORY { 
ULONG Characteristics; 
ULONG TimeDateStamp; 
USHORT MajorVersion; 
USHORT MinorVersion; 
USHORT NumberOfNamedEntries; 
USHORT NumberOfIdEntries; 
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; 

ULONG = 4 bytes, USHORT = 2 bytes 共16个字节 

这些东西对我们没什么大用,但你需要知道,哪里是后面数据的开始. 因此,向前16个字节你会看到一些IMAGE_RESOURCE_DIRECTORY _ENTRies (资源目录入口地址), 它的结构: 

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { 
ULONG Name; 
ULONG OffsetToData; 
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { 

以十六进制格式,你将看到(类似的数据):  

(译注:为便于分析,翻译时使用了win2003下的 NOTEPAD 5.2 作为演示样例) 
xx 00 00 00 xx 00 00 xx xx 00 00 00 xx 00 00 xx 

 1  2  3  4  5  6  7  8    9 10 11 12 13 14 15 16 
00008000h: 00 00 00 00 00 00 00 00 04 00 00 00 00 00 08 00 ; 
00008010h: 03 00 00 00 50 00 00 80 04 00 00 00 A8 00 00 80 ; 

03 00 00 00-50 00 00 80 - 04 00 00 00-A8 00 00 80 
                           1  2  3  4  5  6  7  8 
... 

每个 IMAGE_RESOURCE_DIRECTORY _ENTRY(资源目录入口) 是 8 字节长。在给出的实例数据中,前8个字节(03-80)对于我们来说并不重要(它通常用于: 图标Icon, 菜单Menu, 对话框Dialog...),但字节从‘04’到‘80’(参见上面的示意数据,即9-16位)是非常重要的。 

从9-16位,其中前4个字节代表名称(对于我们没有用),第5-8位字节代表偏移量,如果这个重要的标志位即数据的最高位是1, 表示指向另一个IMAGE_RESOURCE_DIRECTORY(资源目录), 否则,它指向IMAGE_RESOURCE_DATA_ENTRY(真正我们需要发现的位置)。 

在我们的例子中,数据是 800000A8 (A8 00 00 80),最重要的标识位被设置为1(数据最高位),这表示,A8是从.rsrc区段开始到一个IMG_RES_DIR(资源目录)的偏移量。 

经检测,资源段开始的偏移是8000,则在80A6处放置的是另一个IMG_RES_DIR(资源目录),就像前面提过的,它也不重要,继续跳过16字节,你能看到下一个IMG_RES_DIR_ENTRY(资源目录入口)。 

000080a0h: 09 00 00 00 48 02 00 80-00 00 00 00 00 00 00 00 ; 
000080b0h: 04 00 00 00 00 00 01 00-01 00 00 00 60 02 00 80 ; 

跳过前4个字节,它代表名字,后4个字节是80000260 (60 02 00 80),标志位依然是1,那继续到8260(8000+260), 那里是下一个IMG_RES_DIR(资源目录),再跳过16字节,又是一个IMG_RES_DIR_ENTRY(资源目录入口),跳过4字节(名字), 看到数据是00000440.  

00008260h: 00 00 00 00 00 00 00 00 04 00 00 00 00 00 01 00 ; 
00008270h: 04 08 00 00 40 04 00 00 00 00 00 00 00 00 00 00 ; 

好了,标志位为0,因此在00008440(8000+440)处就是我们要找的目标了-IMAGE_RESOURCE_DATA_ENTRY(资源数据入口),它的结构是 

typedef struct _IMAGE_RESOURCE_DATA_ENTRY { 
ULONG OffsetToData; 
ULONG Size; 
ULONG CodePage; 
ULONG Reserved; 
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; 

只有前两个域对我们来说是重要的,数据是 0011750 (数据偏移)和 330 (尺寸),我们一会儿要用到这些数据,因此记下IMAGE_RESOURCE_DATA_ENTRY(资源数据入口)的地址,在我们的实例中是8440. 

00008440h: 50 17 01 00 30 03 00 00 E4 04 00 00 00 00 00 00 ; P...0...&....... 
           数据偏移    尺寸 

(译注:当尺寸第二位不为0时,数据偏移地址应减去该值 11750-300=0e750,原文未说明,经观察发现,可能不正确,更多细节,参见有关技术资料) 


现在,到了0E750,你应该可以在这里看见菜单资源: 

0000e750h: 00 00 00 00 10 00 87 65 F6 4E 28 00 26 00 46 00 ; ......‡e&N(.&.F. 
0000e760h: 29 00 00 00 00 00 01 00 B0 65 FA 5E 28 00 26 00 ; ).......°eú^(.&. 
0000e770h: 4E 00 29 00 09 00 43 00 74 00 72 00 6C 00 2B 00 ; N.)...C.t.r.l.+. 
0000e780h: 4E 00 00 00 00 00 02 00 53 62 00 5F 28 00 26 00 ; N.......Sb._(.&.  


菜单项的结构 

00 00|00 00|10 00| 87 65 F6 4E 28 00 26 00 46 00 ; 
属性   ID    菜单项名称 

前两个字节 – 不知道用途,可能仅起分隔符作用 
3-4字节   - 属性 (描述见后) 
5-6字节   - 菜单项的ID (对于弹出菜单,此项不代表ID) 
从第7字节开始 – 菜单项名称 (当是弹出菜单时,名字从第5个字节开始) 

注意一个例外: 在开始的菜单项之前,有两个空(Null)字节作为开始标识 

特性 – 我仅仅列出比较重要的属性,完整的列表无法从winuser.h或网站上获知 

0800 – Separator    (分隔符) 
0000 – Enabled      (允许) 
0001 – Grayed       (变灰) 
0002 – Disabled     (禁止) 
0010 – Popup        (弹出) 
0080 – End          (结束) 

菜单项的分割符,看起来象这样: 
00 00 | 00 08 | 00 00 
属性   名称字符串 (仅仅两个空字节) 

例如,菜单项如下 

00 00 00 00 | 90 00 | 26 00 46 00 69 00 6C 00 65 00 

00 00 | 80 00 | 69 00 45 00 26 00 78 00 69 00 74 00 


你可以看到第一个菜单项的属性是 90 = 80 | 10 表示是弹出菜单项,并且结束。 
第二个属性仅是 80 = End. 它不是弹出菜单, 因此它肯定是子菜单。 

现在,我们要加菜单项,首先应该知道它象是什么样子,如一个OPEN菜单项应该象这样: 

00 00 | 00 00 |70 00| 26 00 4F 00 70 00-65 00 6E 00 
属性    ID    &     O     p     e     n 
你看,ID是 0070, 但它可以是任何未被使用的值. ‘O’字符前的(&)号将使得‘O’具有下划线以及可以键入字母‘O’来激活相关菜单项 

现在再设置一个‘Close’关闭菜单项: 

00 00 | 01 00 |71 00 | 26 00-43 00 6C 00-6F 00 73 00-65 00 
属性    ID     &     C    l     o     s     e 

你可以看到,属性是0001(表示灰色),ID值是自定义的。 

在我的演示程序中(一个简单的Hello World应用程序示范,仅有2个菜单项,它使用MS VC++编写)我在发现我的菜单资源后的位置找到了一块空间(通常是被‘0’填充的区域),在 
6960,因此我写了一个文件菜单,插入‘Open’和‘Close’菜单项. 最后是一个退出菜单项‘Exit’ ,它们的样子如下: 

00 00 00 00-90 00 26 00-46 00 69 00-6C 00 65 00 
00 00 00 00-70 00 26 00-4F 00 70 00-65 00 6E 00 
00 00 01 00-71 00 26 00-43 00 6C 00-6F 00 73 00 
65 00 00 00-80 00 69 00-45 00 26 00-78 00 69 00 
74 00 00 00 

现在w, 写下6960,它指向一个44(十六进制)字节的区域, 
现在,回到刚才提到的那个地址(在演示的NOTEPAD里是0E750,在我的HELLO WORLD里是61F0,指向的地址是000067C8,尺寸是22),你应该已经记下来了,将它的内容改为新的地址(从 000067C8 到 00006960,尺寸. 然后改变尺寸,从 22 到 44)。现在保存程序再运行它,我是可以看见我的‘Open’和‘Close’菜单项了。如何,你明白了吗? 

有一件事情需要提醒你,当你希望在一个可执行文件中,添加菜单项时,可能需要改变相关的段(section)尺寸,这方面的资料,你可以比较容易的在网上查到。如果你高兴,你可以在某个程序的‘退出’菜单项前加上一道分隔符. 


感谢你们大家 

作者:FENRI 

有关资料,请参见: 
可知行文件格式(The Portable Executable File Format - by Johannes Plachy) 
PE文件内部结构(Peering Inside the PE: A Tour of the Win32 Portable Executable File Format- by Matt Pietrek) 
[] [打 印] [收 藏]
关于本站 网站帮助 广告合作 下载声明 友情连接 网站地图 联系站长
如果您对本站有任何建议或意见,请联系站长,感谢您对本站一如既往的支持!
Powered by:NewAsp SiteManageSystem Version 2.1 SP1 1030