首页
社区
课程
招聘
[原创]小试牛刀·jmp指令跳转非代码节区初探
2021-4-7 03:20 6883

[原创]小试牛刀·jmp指令跳转非代码节区初探

2021-4-7 03:20
6883

工具说明

参照书籍:《Windows PE权威指南》;

使用工具:WinHex、CFF、OD、IDA、MSDN;

所需文件干净的PE文件,在[原创] 小试牛刀·手动构建HelloWorld弹窗可执行文件中有说明和附件下载;

本帖文件在附件中(文件密码:apebro);

环境:Windows7 x86,没有开DEP(数据执行保护);

摘要

在跟一个大兄弟请教问题的时候,他说了一句让我虎躯一震的话:”jmp过去不需要那个节有可执行权限。“

这倒是一个有意思的说法,以前还真没怎么注意;

在经过询问后,得到可以写贴的答复;

以下探索有问题之处,还请大佬们指正;

探索开始

1、先复习一下节表结构(_IMAGE_SECTION_HEADER);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
};

我们使用一个干净的PE文件,来查看一下例子;

 

image-20210406203724636

 

本期重点在于最后一个字段Characteristics

  • 我们查看《Windows PE权威指南》 P88,一下它的字段设置规则;

image-20210406203930673

 

以及书中总结:

 

image-20210406204021673

1
2
3
4
5
6
7
0x00000020    // 代码段
0x00000040  // 已初始化数据区
0x00000080    // 未初始化数据区
 
0x20000000    //    可执行
0x40000000    //    可读
0x80000000    //    可写

所以,我们一共要考虑9种可能

 

2、在此之前,我们先给test1.exe文件进行添加节(使用WinHex);

  • 根据PE头中文件对齐是0x00000200,知道文件内一页有多少;

  • 增加节的数量;

image-20210406204844248

 

在标出的位置是节数量,我们先根据页面可否读写先增加三个节。所以填0004;

  • 再在紧贴着.text节下面增加三个两行半(一个节有两行半的数据);

image-20210407031609946

 

这里我们还要修改节区VirtualAddressPointerToRawData参数;

 

image-20210407023147041

  • 因为文件最后一个节的起始地点是0x00000800,文件是0x200对齐,所以要填充到0x000009FF

image-20210406214914626

  • CFF查看;

image-20210406210620681

 

都已经添加进去了,美滋滋,这时候还没完,还需要改SizeOfImage字段;

 

image-20210406214536221

 

一个节占用一个页,一个页是0x1000,还要加上头节,所以共0x5000

  • 点击运行,如果成功,就是扩展成功了;

image-20210406215035416

 

3、现在开始填充代码;

  • 因为一些字段没有正确设置,所以直接拖进没有插件的OD可能无法成功,可以先运行然后尝试attach附加上去;

image-20210406215416511

 

这就是上一帖子很熟悉的代码,我们尝试每个节区都放上这个MessageBoxA代码;

  • 所以我们先用WinHex把代码编码填充到每个节区的开头位置;

image-20210406215657640

 

这是程序入口地址的代码,复制,填充到每个节区的开头;

 

image-20210407021648626

 

image-20210407021727695

 

image-20210407021840983

  • 然后再把程序拖进OD;

  • 将入口点0x00401080处添加代码jmp 00402020,跳转到execute section;

image-20210407014420164

 

然后保存到可执行test2.exe文件,如何保存在上一贴有描述;

 

image-20210407015108801

 

可以执行!

  • 将入口点0x00401080处添加代码jmp 00403020,跳转到read section;

image-20210407014657829

 

然后保存到可执行test3.exe文件,如何保存在上一贴有描述;

 

image-20210407014506105

  • 将入口点0x00401080处添加代码jmp 00404020,跳转到write section;

image-20210407015002644

 

然后保存到可执行test4.exe文件,如何保存在上一贴有描述;

 

image-20210407014745311

 

准备工作做了那么多,我们要开始实验了;

 

4、准备工作做了那么多,我们要开始实验了(使用WinHex);

 

(1)看0x00000020+0x20000000,代码段可执行,使用test2.exe

 

image-20210407023535229

 

image-20210407023559049

 

可执行!

 

(2)看0x00000020+0x40000000,代码段可读,使用test2.exe

 

image-20210407023656305

 

image-20210407023716811

 

可执行!

 

(3)看0x00000020+0x80000000,代码段可写,使用test2.exe

 

image-20210407023813798

 

image-20210407023840286

 

可执行!

 

(4)看0x00000040+0x20000000,已初始化数据区可执行,使用test3.exe

 

image-20210407024107593

 

image-20210407024127084

 

可执行!

 

(5)看0x00000040+0x40000000,已初始化数据区可读,使用test3.exe

 

image-20210407024235660

 

image-20210407024251105

 

可执行!

 

(6)看0x00000040+0x80000000,已初始化数据区可写,使用test3.exe

 

image-20210407024343154

 

image-20210407024400948

 

可执行!

 

(7)看0x00000080+0x20000000,未初始化数据区可执行,使用test4.exe

 

image-20210407024603711

 

image-20210407024619077

 

可执行!

 

(8)看0x00000080+0x40000000,未初始化数据区可读,使用test4.exe

 

image-20210407024658428

 

image-20210407024712319

 

可执行!

 

(9)看0x00000080+0x80000000,未初始化数据区可写,使用test4.exe

 

image-20210407024753667

 

image-20210407024809252

 

可执行!


总结

由此可见,的确如此呀。

 

由此可以看出,操作系统在加载PE文件的细节问题;

 

我想起在C/C++中,对于const *str="hello world"定义声明后,对于原位置不能更改(通过debug修改段属性可以更改),现在看来并不影响执行指令;

 

大概这也就是为啥看别人写的shellcode放在数组里却依旧能执行的原因吧;

 

实验文件我放在附件了,欢迎下载论证;

 

有大佬指出有环境的特殊性,我准备在后续写到内核时,续写这个话题;
感谢各位大佬指正;

 

欢迎大佬讨论指点;


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2021-4-8 15:41 被平头猿小哥编辑 ,原因: 上传文件
上传的附件:
收藏
点赞3
打赏
分享
最新回复 (4)
雪    币: 5734
活跃值: (1737)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
blindtiger 1 2021-4-7 03:36
2
1
以后在x64平台上测试, 32位pte长度 不够用 有bug。
雪    币: 2428
活跃值: (2287)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dearfuture 2021-4-7 06:55
3
1
没开dep?
雪    币: 789
活跃值: (1494)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
のばら 2021-4-7 10:26
4
1
64位哪怕没开DEP也会裂开,只有在32位,并且没开DEP的时候才可以执行
雪    币: 258
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
绝对正确 2021-4-7 11:05
5
1
清晰详细, 谢谢
游客
登录 | 注册 方可回帖
返回