参照书籍:《Windows PE权威指南》;
使用工具:WinHex、CFF、OD、IDA、MSDN;
所需文件干净的PE文件,在[原创] 小试牛刀·手动构建HelloWorld弹窗可执行文件中有说明和附件下载;
本帖文件在附件中(文件密码:apebro
);
环境:Windows7 x86,没有开DEP(数据执行保护);
在跟一个大兄弟请教问题的时候,他说了一句让我虎躯一震的话:”jmp过去不需要那个节有可执行权限。“
这倒是一个有意思的说法,以前还真没怎么注意;
在经过询问后,得到可以写贴的答复;
以下探索有问题之处,还请大佬们指正;
1、先复习一下节表结构(_IMAGE_SECTION_HEADER
);
我们使用一个干净的PE文件,来查看一下例子;
本期重点在于最后一个字段Characteristics
;
以及书中总结:
所以,我们一共要考虑9种可能
2、在此之前,我们先给test1.exe
文件进行添加节(使用WinHex
);
根据PE头中文件对齐是0x00000200
,知道文件内一页有多少;
增加节的数量;
在标出的位置是节数量,我们先根据页面可否读写先增加三个节。所以填0004
;
这里我们还要修改节区VirtualAddress
、PointerToRawData
参数;
都已经添加进去了,美滋滋,这时候还没完,还需要改SizeOfImage
字段;
一个节占用一个页,一个页是0x1000
,还要加上头节,所以共0x5000
;
3、现在开始填充代码;
这就是上一帖子很熟悉的代码,我们尝试每个节区都放上这个MessageBoxA
代码;
这是程序入口地址的代码,复制,填充到每个节区的开头;
然后再把程序拖进OD;
将入口点0x00401080
处添加代码jmp 00402020
,跳转到execute section
;
然后保存到可执行test2.exe
文件,如何保存在上一贴有描述;
可以执行!
然后保存到可执行test3.exe
文件,如何保存在上一贴有描述;
然后保存到可执行test4.exe
文件,如何保存在上一贴有描述;
准备工作做了那么多,我们要开始实验了;
4、准备工作做了那么多,我们要开始实验了(使用WinHex
);
(1)看0x00000020
+0x20000000
,代码段可执行,使用test2.exe
;
可执行!
(2)看0x00000020
+0x40000000
,代码段可读,使用test2.exe
;
可执行!
(3)看0x00000020
+0x80000000
,代码段可写,使用test2.exe
;
可执行!
(4)看0x00000040
+0x20000000
,已初始化数据区可执行,使用test3.exe
;
可执行!
(5)看0x00000040
+0x40000000
,已初始化数据区可读,使用test3.exe
;
可执行!
(6)看0x00000040
+0x80000000
,已初始化数据区可写,使用test3.exe
;
可执行!
(7)看0x00000080
+0x20000000
,未初始化数据区可执行,使用test4.exe
;
可执行!
(8)看0x00000080
+0x40000000
,未初始化数据区可读,使用test4.exe
;
可执行!
(9)看0x00000080
+0x80000000
,未初始化数据区可写,使用test4.exe
;
可执行!
由此可见,的确如此呀。
由此可以看出,操作系统在加载PE文件的细节问题;
我想起在C/C++中,对于const *str="hello world"
定义声明后,对于原位置不能更改(通过debug修改段属性可以更改),现在看来并不影响执行指令;
大概这也就是为啥看别人写的shellcode放在数组里却依旧能执行的原因吧;
实验文件我放在附件了,欢迎下载论证;
有大佬指出有环境的特殊性,我准备在后续写到内核时,续写这个话题;
感谢各位大佬指正;
欢迎大佬讨论指点;
typedef struct _IMAGE_SECTION_HEADER
{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
/
/
0x00
union {
DWORD PhysicalAddress;
/
/
0x08
DWORD VirtualSize;
/
/
0x08
} Misc;
DWORD VirtualAddress;
/
/
0x0c
DWORD SizeOfRawData;
/
/
0x10
DWORD PointerToRawData;
/
/
0x14
DWORD PointerToRelocations;
/
/
0x18
DWORD PointerToLinenumbers;
/
/
0x1c
WORD NumberOfRelocations;
/
/
0x20
WORD NumberOfLinenumbers;
/
/
0x22
DWORD Characteristics;
/
/
0x24
};
typedef struct _IMAGE_SECTION_HEADER
{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
/
/
0x00
union {
DWORD PhysicalAddress;
/
/
0x08
DWORD VirtualSize;
/
/
0x08
} Misc;
DWORD VirtualAddress;
/
/
0x0c
DWORD SizeOfRawData;
/
/
0x10
DWORD PointerToRawData;
/
/
0x14
DWORD PointerToRelocations;
/
/
0x18
DWORD PointerToLinenumbers;
/
/
0x1c
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-4-8 15:41
被平头猿小哥编辑
,原因: 上传文件