首页
社区
课程
招聘
[2005.1月话题]保护模式与 PE Loader 行为研究
2005-1-6 00:42 24671

[2005.1月话题]保护模式与 PE Loader 行为研究

2005-1-6 00:42
24671
厌烦 Reversing Engine 了吗?来看看这个问题吧!
   Win32世界里,PE 文件的执行都是通过 PE Loader 加载并执行的,这是操作系统的行为,现在讨论一下更深层次的问题。本次讨论的重点以最简单的不需要重定位的 EXE 类型 PE 文件为讨论模型,探讨一下 PE Loader 如何将 PE 文件 image 定位到具体的物理内存中。这涉及到保护模式、多任务、进程等多方面的知识!

   先问一个相关问题:
我们知道  EXE 基本上都是从4GB的线性地址(Linear Address)空间的 0x00400000 处装入内存,那么不同的进程如何根据保护模式下的GDT、LDT、Segmentation、Paging机制以及相应操作系统机制定位到具体的物理内存位置?

   请坛内资深人士尽情畅言。讨论请以win9x和NT为内核分别讨论!谢谢!

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞7
打赏
分享
最新回复 (41)
雪    币: 159
活跃值: (339)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
Lenus 3 2005-1-6 01:00
2
0
这个问题太高深,我就先抢个位置,准备学习了。:D
雪    币: 153
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Phoenix 2005-1-6 07:23
3
0
我也关注支持一下,准备学习!:p
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dlk0222 2005-1-6 07:28
4
0
嘿嘿我也学习一下
尽管才学完操作系统--内核与设计
不过感觉没有怎么讲
一笔带过而已
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4x9 2005-1-6 08:07
5
0
好像绿盟有个人发表了许多这方面的东西
雪    币: 16
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
great1234 2005-1-6 08:50
6
0
一句话能说清楚吗?
再说了,操作系统的课程不是讲的很清楚吗?
再不行,你自己买一本<<windows95程序设计奥秘>>看看
雪    币: 333
活跃值: (369)
能力值: ( LV12,RANK:490 )
在线值:
发帖
回帖
粉丝
FlyToTheSpace 12 2005-1-6 10:55
7
0
呵呵!我正准备研究这方面问题,软件的运行,从读取硬盘数据开始
可是我的资力不够:( :(

支持中;) ;)
雪    币: 236
活跃值: (155)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
nOpnOp 2 2005-1-6 12:09
8
0
最初由 dREAMtHEATER 发布
厌烦 Reversing Engine 了吗?来看看这个问题吧!
Win32世界里,PE 文件的执行都是通过 PE Loader 加载并执行的,这是操作系统的行为,现在讨论一下更深层次的问题。本次讨论的重点以最简单的不需要重定位的 EXE 类型 PE 文件为讨论模型,探讨一下 PE Loader 如何将 PE 文件 image 定位到具体的物理内存中。这涉及到保护模式、多任务、进程等多方面的知识!

先问一个相关问题:
我们知道 EXE 基本上都是从4GB的线性地址(Linear Address)空间的 0x00400000 处装入内存,那么不同的进程如何根据保护模式下的GDT、LDT、Segmentation、Paging机制以及相应操作系统机制定位到具体的物理内存位置?
........


Win32系统隔离进程内存空间使用的是分页技术。
进程切换的同时也切换x86系统CR3寄存器所指向的页目录的地址,从而达到将不同的物理内存映射到每个进程中相同的虚拟线性地址上的效果。Win32和Linux都没有使用Intel基于LDT的任务(进程)切换技术,为什么不采用我就不知道了,那位大侠知道原因的话,请指点一下。
雪    币: 255
活跃值: (165)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dREAMtHEATER 2005-1-6 19:55
9
0
坛子里的专家都哪里去了?
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
firstrose 16 2005-1-6 20:11
10
0
给你推荐一个地方:www.xfocus.net

那里讨论OS内核挺不错的。
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bjork 2005-1-6 20:25
11
0
好开心啊!D老大终于又重出江湖了!:o
怎么还是和以前一样,讨论来讨论去还是你自己的老本行,PE的东西。你不腻的吗,没有新的技术可讨论吗,难道你的技术还是停留在PE那里?:(
雪    币: 258
活跃值: (230)
能力值: ( LV12,RANK:770 )
在线值:
发帖
回帖
粉丝
qiweixue 19 2005-1-6 20:39
12
0
逆逆 ICE loader TRW loader 能发现很多东东的!
雪    币: 85496
活跃值: (198820)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
linhanshi 2005-1-6 21:25
13
0
学习!!!
雪    币: 213
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
d1y2j3 2005-1-6 23:33
14
0
可以跟踪一下CreateProcessInternalA
雪    币: 213
活跃值: (96)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
云重 1 2005-1-7 00:57
15
0
WINDOWS 2000 的地址转换机构不同与传统的页面地址转换机构,它采用二级页表结构,第1级叫做页目录,每个进程一个页目录.    每个页目录包含1024个表目,每个表目指向第二级页表的启始地址(页表地址),第2级页表也包括1024个表目,每个表目指向实际的页桢(错字,我用智能abc没找的这个字)//(就是内存块),每个表目的大小4B,因此,第二级页表均为4KB大小,恰好占一个页桢,当给一个虚拟地址后,他自动被分3个部分,:页内转移(第0-22位,功12位),页表位移(第12-21共10位),目录位移(第22-31共10位).地址转换机构将页目录地址与页目录位移拼接成页目录所在地址,该表目中包含相应页表地址;然后将此页表地址与页表位移拼接成页表目地址,其中包含该页的所在页桢号;最后将此页桢号与页内位移拼接成 内存物理地址,从而得到物理地址.
windows 2000采用2级页表结构的目的是减少每个进程页表所占用的内存空间.虚拟储存管理程序并不把所有页表都放在内存,而是根据需要把这些页表换入,换出内存,

为了解决2级页表访问速度慢,windows 2000采用使用快表,即利用高速联想存储器存放经常使用的页表表目.
使用高速度缓冲存储器,使大部分指令和数据直接存取自高速缓存.

抛块砖头,继续引玉
雪    币: 213
活跃值: (96)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
云重 1 2005-1-7 01:00
16
0
dREAMtHEATER 大哥可能的话告诉加我QQ,我的19226491
雪    币: 213
活跃值: (96)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
云重 1 2005-1-7 01:14
17
0
每个操作系统都有自己的保存页表的方式,大多是为每个进程分配一个页表,在进程控制块(PCB)中存放指向该页表的指针.当调度一个进程令其运行时,就必须从新加载各个寄存器(地球人都知道),且使硬件页表取得正确值.
    硬件页表实现方式很多,简单的方式是又一组专门的寄存器来实现.如果页表较小(256项)整个页表都由寄存器实现,多数现代计算机页表很多(100万项).就将页表保存在内存中,又一个页表基址寄存器PTBR指向该表页,整个系统只一个PTBR,当方式进程切换时,只需改变PTBR的指向.使它指向选中进程的页表,但是回代来速度问题,为了解决这个问题.使用了专用的高速小容量的联想存储器 也叫 快表(或Translation Lookaside Buffer ,TLB)
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
nbw 24 2005-1-7 10:15
18
0
jiurl写过几篇关于win2k内存的。回头转过来
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
firstrose 16 2005-1-7 12:53
19
0
雪    币: 213
活跃值: (96)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
云重 1 2005-1-7 13:20
20
0
没必要对细节知道那么多吧,大家都准备改行写操作系统了?:D
雪    币: 6073
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
forgot 26 2005-1-8 07:58
21
0
前言:
  本文旨在加强理解,实际情况并非如此。这是简化版。

1. 基本概念  
  虚拟地址=逻辑地址=[段选择子]:[线形地址],利用段选择子找到描述符,描述符有字段表示段的基
地址(在Win32中都是0,所以线形地址就是真正地址)还有字段表示段属性,实际上起到保护作用。   
  事实上,在Win32中,其他地址已经不重要了。关键还是线形地址。
  我们在程序中使用的都是线形地址,我们完全可以忘记虚拟内存的概念,认为每个进程确实具有4G的
物理内存,OS和CPU屏蔽了这个细节。不考虑它,也不会影响病毒的编写。程序在执行时,cpu会将我们
使用的地址(可能是硬编码或寄存器)转换为物理地址。

2. 虚拟内存原理
  但是,喜欢探索本质的人还是想了解细节,下面形象的解释一下:
  1)硬件时钟中断,转中断处理程序,程序进行一些必要工作后,取出调度程序的pcb(进程控制块),
设置寄存器数值,调度进程得到运行,按照某中算法选择一个进程P执行。cpu切换为P的环境。
  与寻址关系最密切的是eip和CR3.   
  CR3的内容是物理地址,这在寻址过程中是很特殊的,因为Win32在保护模式下,感觉上都是虚拟地址,
但是,如果真的都是虚拟地址,可就真的没办法定位到物理内存了。   
  cpu对以上发生的事一无所知,只是根据eip的值一条一条的执行。   
  此时访问的地址就是P的4G空间,执行P的指令。
  如何实现的呢?关键是页表。
  2)映射的本质
  内存通过主板连接到cpu,之间有一个MMU部件(Memory Management Unit),cpu执行时,把eip高20
位作为一个索引,再将[index+CR3]的作为高20位,eip的低12位作为低12位组合在一起,形成新的32
位地址,这就是物理地址.
  把页表想象成一个数组,个数为2^20(1M),大小为4M,页表当然存储在物理内存中,CR3就是数组首地址。
数组的每一项为一个DWORD,双字的前20位表示一个物理页面。形象地:
 
               页号(0~19)  ...页属性  保留(30)   提交(31)
   CR3 -->     00100             rw       1            1
               01001              r       1            0
               01010              0       0            0
               00111              0       0            0
               ...
               10011              0       0            0
               
   这表明,物理内存的第4个物理页面提交,第9个保留.
   每个进程都含有这样一个页表,其中的页号可能一样,就是对应相同的物理页面,比如内存映射文件。
此时一个进程修改的数据,其他进程访问时也会改变。每个进程都有4G的内存可以使用,只是很多页面
没有提交而已,这就是每个进程有4G的原理。
   再来想象,当我们使用VirtualAlloc请求4k内存时。
   VirtualAlloc(0,4*1024,PAGE_READWRITE,MEM_RESERVE or MEM_COMMIT)
函数内部搜索页表,找到第一个空闲页,这里是01010h,根据参数设置相应项,如果没有MEM_COMMIT,
则‘保留’设为1,‘提交’为0,就是这个原理。
   那么,VirtualFree就不言而喻了。
   在看看MapViewOfFile,就是把文件从硬盘读到物理内存页面M中,比如M=00111h,这一项在页表中的
索引等于3,再加上页内偏移000h,返回00003000h (pMapping=00003000h),以后用这个值访问这块内
存,如何访问,则会访问到00111h这个物理页面,前面已经说了,自己可以分析一遍。
   那么UnmapViewOfFile的作用相反了。
   所谓映射,简单的说,就是将页表项的保留和提交设置为1而已。
   解除映射则置0。
   解除后,再使用pMapping(线形地址)访问内存时,找到页表相应项,发现此页面没有保留,就会发生
内存错误。   值得注意的是,即使使用MapViewOfFile,页表中‘提交’字段也未必是1,只是作了保留
标志,其他函数请求内存时就不会重复分配了,真正访问这个页面时再产生页错误而真正分配物理页。

3. 应用
  自删除程序就是一个典型例子。
  为什么要在堆栈中执行,而不是直接在代码段写呢。因为如果这样写,那么执行UnmapViewOfFile后,
页表相应项(保留)置0,下一条指令就会发生内存错误。可是,如果把代码放在堆栈中,exe映射虽然解
除,但堆栈对应的页表项仍在,所以可以继续执行,当然,也可以动态分配内存,将删除代码拷贝其中来
执行,原理一样了,归根结底,就看页表的保留位是否是1,也就是是否映射
雪    币: 6073
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
forgot 26 2005-1-8 07:58
22
0
即使是DT,也不能用激将法
雪    币: 257
活跃值: (369)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
newsearch 9 2005-1-8 16:53
23
0
最初由 great1234 发布
一句话能说清楚吗?
再说了,操作系统的课程不是讲的很清楚吗?
再不行,你自己买一本<<windows95程序设计奥秘>>看看


不要把楼主的问题想得那么简单。
实际上在http://webster.cs.ucr.edu/(汇编站点)里面的
http://webster.cs.ucr.edu/Page_TechDocs/index.html(其它汇编资源)

有些好东东。Intel的原版资料,应该可以解决你的提问,确实非常好。我不知道目前国内有没有这些资料的中文翻译,如果需要的话,可以找TT翻译部分。

我才下载看了一部分,这已经不仅仅是汇编或程序开发了。我以前看到的基本上都是8086/8088/80386的汇编资料,而这里已经有Pentium Pro了。不仅仅限于Win9X/NT平台。
雪    币: 255
活跃值: (165)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dREAMtHEATER 2005-1-8 20:04
24
0
呵呵,我的讨论置顶了,我现在正在看相关资料,不敢有任何有鲁莽的回复
雪    币: 3686
活跃值: (1036)
能力值: (RANK:760 )
在线值:
发帖
回帖
粉丝
cnbragon 18 2005-1-8 22:37
25
0
最初由 dREAMtHEATER 发布
呵呵,我的讨论置顶了,我现在正在看相关资料,不敢有任何有鲁莽的回复


值得偶学习这种治学严谨的态度......
游客
登录 | 注册 方可回帖
返回