• 标 题:[原创]■■易格式初步研究笔记■■
  • 作 者:monkeycz
  • 时 间:004-11-01,08:26
  • 链 接:http://bbs.pediy.com

易格式初步研究笔记


作者:monkeycz
电子信箱:coffin13@183.ha.cn
QQ:53719349

如有任何问题,请与我联系。仓促之作,必有不少错误,等待您的釜正,谢谢。

====================================================================

10月15日
1。凌晨的时候终于完成0.50版。顺手传到了易语言论坛。
2。休息休息,测试测试。
3。开始研究常量数据段的结构。
4。稍微研究了一下代码数据段,感觉能够在较高的抽象上反编译出来。

10月16日
1。继续研究常量数据段的结构。感觉不是很复杂。
2。稍微看了一看窗口数据段的内容,感觉——满头浆糊,一点都不明白。

10月17日
1。DllCmd在编译为易格式的时候,并不保存参数,根据代码进行调用。也就是说调用的时候没有在易格式内部进行参数检查,只是编译的时候进行检查。
2。没有在程序中被调用的DllCmd,编译的时候并不封装到易格式内,只保存在源代码中。
3。在常量数据段中,所有的文本常量以文本内容起始,以0x00结尾。
4。在常量数据段中,所有的文件常量以0x0001起始,后面跟着文件长度数据(DWord),然后是文件的内容。没有结尾。
5。被调用的DllCmd,如果没有库名,m_nDllFileNameConstOffset项为空。
6。被调用的DllCmd,如果没有库中的对应名称,m_nDllCmdNameConstOffset项为命令名。
7。发布了0.52版。同时又传到了看雪论坛一份。
8。努力研究窗口数据段,搞不明白。今天估计是没戏了。
9。关于窗口数据段的一点想法:没有被调用的窗体不会被记录到窗口数据段(和DllCmd一样,这也能算是“全编译”的一个侧面证据吧);没有在设计中改变的属性的窗体被保存到数据段中,好像不保存属性数据(待证)。

10月18日
1。研究窗体数据段毫无头绪。
2。换换口味,研究一下重定位信息。

10月19日
1。继续研究重定位信息。

10月20日
1。似乎明白了编译后的代码对支持库中的命令的调用方式。
2。@hlpfn数据段是运行时从核心支持库中加载进来的(REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]),应该在核心支持库中是一张表。然后通过重定位在运行的时候作为服务调用。
3。我也应该能写一个易格式的可执行文件编译器。
4。还是不明白重定位的方法。
5。领养了一只小猫(说是偷的也行,说是抢的也行),可爱的小家伙。

10月21日
1。今天真是美妙的一天。套用金田一著名的台词:“一切迷底都解开了”。
2。昨天关于@hlpfn的推测是正确的。@hlpfn数据段正如其名,接口数据段。所有运行时调用的服务函数地址全部是在这张表中记录的。服务的调用方式应该是这样的:EAX中放置支持库、DllCmd顺序编号,EBX放置调用的命令编号(由服务提供)。然后Call一个地址,这个地址中放置有服务调用语句(类似于jmp dword ptr [0000000C]),其中的间接转跳地址在装载的时候经过重定位,调用接口数据段中的服务地址。接口数据段中不同的地址指针之指向的服务如下(重定位之前指向@hlpfn数据段的偏移):
-----------------------------------------------------------------------
0C     | krnln内部调用
-----------------------------------------------------------------------
08     | 调用其他支持库中的命令
-----------------------------------------------------------------------
20     | 销毁从系统申请到的自由内存,内存地址一般置入EBX后压栈
-----------------------------------------------------------------------
04     | 调用DllCmd
-----------------------------------------------------------------------
2C     | 创建窗口
-----------------------------------------------------------------------
30     | 把一处地址压栈(多是指向ret指令),供24号服务调用
-----------------------------------------------------------------------
24     | 结束当前进程
-----------------------------------------------------------------------
28     | 进入消息循环
-----------------------------------------------------------------------

例如:

:004031C9 55                      push ebp
:004031CA 8BEC                    mov ebp, esp       ;为申请局部变量做准备。易语言从栈中分配内存。
:004031CC 6A00                    push 00000000
:004031CE 6A00                    push 00000000
:004031D0 6A00                    push 00000000
:004031D2 6801030080              push 80000301
:004031D7 6A00                    push 00000000
:004031D9 6800000000              push 00000000
:004031DE 6804000080              push 80000004
:004031E3 6A00                    push 00000000
:004031E5 6800000000              push 00000000      ;重定位信息框提示信息的常量
:004031EA 6803000000              push 00000003
:004031EF BB00030000              mov ebx, 00000300  ;命令序号,300在这里是消息框的序号,2FC是输入框,168是到文本,等等
:004031F4 E852000000              call 0040324B      ;转跳到服务调用命令

……

:0040324B FF250C000000            jmp dword ptr [0000000C]  ;重定位到接口数据段,调用krnln内部服务。


3。发现了EcE的一个很低级的Bug,居然在计算m_aryReLocationItem中的成员的时候,拔高低位弄反了。结果前几天我根据错误的结果死活都搞不明白究竟是如何重定位的。真是失败!因为这样一个错误浪费好些天的时间。不过因祸得福,如果不是一开始没有搞明白如何重定位,估计线在我对@hlpfn数据段还不是很明白。立即修改EcE,终于计算出正确的结果,看起来舒服多了,和预想中的一样。如果是在@code数据段中的重定位信息,低三位记录了当前重定位项在重定位的时候的基址,高29位记录了当前重定位项记录的需要重定位的数据在当前数据段中的偏移。重定位后的地址=[[头信息偏移+SECTION_INFO[当前段].m_nRecordOffset+RELOCATION_INF.m_dwOffset]+SECTION_INFO[m_btType].m_nRecordOffset]。
4。EcE更新到0.53版了,唯一更新的内容就是计算重定位信息的Bug。
5。这样的话,一切都很明了了,除了窗口数据段外。
6。现在应该可以写一个非官方的易格式可执行文件编译器了,可以是完全不同的开发方式,完全不同的编译方式,但是生成的可执行文件是易格式的,同时还需要支持库中的命令和核心支持库的装载。
7。如果要写一个反编译器的话,虽然不能反汇编到源代码的样子,但只要对调用了支持库中的什么命令、怎么调用的、参数是什么,已经可以知道了。反编译后的代码应该抽象度比较高,更容易被看懂,因为应易语言编写的程序的几乎所有功能都是通过调用支持库来实现的。
8。一个非技术性的问题:如果写出了非官方的编译器和反编译器,不知道吴涛会有什么想法,更不知道对易语言的发展有何影响。我不希望有坏的方面的影响,毕竟易语言是个好东西,我喜欢它,希望能够继续发展下去。但是经过分析,总觉得如果这样的话,也许会有坏的影响,所以还是先考虑一下再说,或者问问公司里的人的意思。
9。熄灯了,昨天领养回来的小猫也爬在我的棉拖鞋上睡着了。睡觉去,终于可以安心的睡个好觉了。至于窗口数据段的问题和其他非技术性的问题,明天再说吧。

10月22号
1。@hlpfn里面的服务指针是动态从装载器中载入的,所有命令全部是支持库提供的(DllCmd除外),也就是说,易格式的跨平台还是很有道理的。不过这个“平台”应该是指操作系统,跨硬件平台就现在的技术是不行了。如果从Windows移植到Linux中,应该只需要通过一个转换器转换一下就可以了,不需要重新编译。当然如果使用了外部的DllCmd,就不一定了。

10月23号
1。易格式对支持库(核心支持库)的依赖太密切了,几乎任何操作(除了数值操作和逻辑操作)都是通过调用核心支持库中的服务来实现的,连调用DllCmd也要(把参数压栈,把DllCmd命令名称对EAX赋值)通过服务,这必然会造成速度上的滞缓(虽然可能感觉不出来)。这种方法对于程序在操作系统间的移植很有好处,不过付出的代价也不小。
2。易语言编译究竟能否算是全编译呢?的确它编译出的程序的运行不是通过解释源代码或者中间代码来实现的,所有的命令被全部编译为机器代码,这应该就算是全编译了。但是它生成的程序我认为不能算是原生应用程序。毕竟里面到处充斥着对核心支持库服务的调用。同样是调用,这就和原生应用程序对系统API的调用性质不同。它属于更高级抽象的调用。不是和操作系统紧密结合的,而是独立于操作系统的。从另一种意义上来说,核心支持库的服务也算是一种解释执行,不过它是更低级的解释(相比于其他通过解释执行的程序),只独立与操作系统,没有抽象到虚拟执行。不过这显然是为了在操作系统间移植而做出的一种选择,并非技术上的不成熟。
3。又发现了一个EcE的Bug。真是疏忽,居然在读取DataDirectory的成员VirtualAddress和isize的时候相互弄反了。修改了一下,现在是0.54版。
4。那只小猫居然不会自己洗脸,真是崩溃!脏死了,难道要我给他洗澡?现在它吃的比我还好,太不公平了。还没想好给它起什么名字,叫猫仔?是不是难听了点?我一向不会起名字。

10月24日
1。看了几段易语言浮点运算的汇编代码。
2。修正了前面写的几处原先判断错误的地方。比如20服务的功能以前就判断错了。
3。托人给猫仔洗了澡,从灰猫变成白猫了。晚上抱它去一个朋友家,回来的时候它居然尿在我身上了。又要洗衣服了,苦啊!

10月25日
1。碌碌无为的一天。好像唯一干的正事,就是在写易盟的一个模块。

10月26日——10月27日
1。帮别人脱了个壳,好像叫什么“软件保护神”的。感觉现在流行的加壳工具对易格式可执行文件除了压缩方面还有用外,保护方面就差多了。易格式作为一个整体是不可分割的。并且仅仅是借住在PE格式里面的。所以即使PE原体被加壳软件压缩加密过了,但是易格式的装载器还是需要一份完整的易格式镜像来装载执行的。也就是说,在装载器准备装载的时候,当前被加壳保护的易格式可执行文件的易格式部分已经有一份完整的镜像在内存中等待装载了。否则它不可能被执行。所以只要在这个时候把这份镜像从内存中复制出来就可以了。这样我们就有了程序的“核心”。剩下要做的工作就是要给他找一副“骨骼”——生成一个.ecode段足以放下被复制出来的易格式的易语言编译出来PE原体,并把我们的植入到“骨骼”中的相应位置(.ecode段中),然后再给他正一正血脉——修复重定位信息和装载信息(因为一般我们提取易格式的时候,它已经被装载器装入过了,也就是说已经经过重定位了),包括PE部分的装载信息(这个一般不用改),易格式头部分的装载信息(一般也不用改)和各数据段中的重定位信息(这个手工做起来可是一项浩繁的工程,如果你面对的是一个大程序的成千上万条的重定位信息,你需要做的就是,高喊一声“My God!”,然后慢慢一个个的核对修改那些淘气的东西)。经过这番大手术,我们终于有了——一只没壳的——乌龟:)
2。计划有空再写一些东西,计划中的有:易格式动/静态提取器,PE骨骼生成器,易格式合成器,易格式重定位自动修复器。反正都是一些相关的软件。
3。26日黄昏的时候,大概5点左右吧,我同寝室的一个同学因为和老师发生矛盾,被那个老师伙同其他的几个老师殴打后,送到了保卫处。等我得到消息赶去,那群学校保安极度猖狂,对我们大肆辱骂挑衅,最后数十名保安当着我们学校老师的面把我们给殴打了。我还没有太大的事,但是我的同学却受伤严重,被送到了医院。据检查,身上多处外伤,包括眼睛,满脸都是淤血,更惨的是,鼻骨多处骨折,鼻中隔被撕裂了一个洞,还少了一块软骨。其情惨不忍睹。据医生说,从未见有人下手这样狠的。学校保安真不是东西!据说这样的事情以前也屡有发生,只是未有过这么严重的。现在我那个同学还在医院里痛苦的躺着。据说学校竟然要开除那位同学!…………我无话可说!实在是无话可说!这还是一所代表着知识与文明高等学府的所作所为么!不知道事情明天会怎样。最近很多时间要处理这件事了,笔记估计会断断续续的。严重鄙视那些缺乏做人最基本的良知,疯狂残暴,心理扭曲变态的狗一样的东西。没想到平日里只是在报纸和电视上当作股市看的事情,有一天就会突然的发生在我身边的同学的身上。希望我的朋友能尽快好起来,同时不受处分,而凶手也要受到应有的制裁!
4。26日晚上我在医院陪了一个晚上,今天基本上又都奔波于学校和医院之间,所以两天的笔记就合起来写了。


====================================================================

(未完待续)

后记:

不好意思浪费了大家宝贵的时间看完了这么长的一篇东西,说了很多废话,内容也不是太实用,只是希望能有人用的上。几天里断断续续写的,词不达意,错误多多,希望有达人予以指正,谢谢。