>

AddressOfFunctions 所指向内容是以 澳门博发娱乐官网

- 编辑:澳门博发娱乐官网 -

AddressOfFunctions 所指向内容是以 澳门博发娱乐官网

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;    // 未使用,总为0 

    DWORD   TimeDateStamp;      // 文件创建时间戳
    WORD    MajorVersion;       // 未使用,总为0 

    WORD    MinorVersion;       // 未使用,总为0
    DWORD   Name;               // 指向一个代表此 DLL名字的 ASCII字符串的 RVA
    DWORD   Base;               // 函数的起始序号
    DWORD   NumberOfFunctions;  // 导出函数的总数

    DWORD   NumberOfNames;      // 以名称方式导出的函数的总数

    DWORD   AddressOfFunctions;     // 指向输出函数地址的RVA
    DWORD   AddressOfNames;         // 指向输出函数名字的RVA
    DWORD   AddressOfNameOrdinals;  // 指向输出函数序号的RVA

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

[PE结构深入分析] 9.导出表 IMAGE_EXPORT_DIRECTORY,dockerexportimage

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;    // 未使用,总为0 

    DWORD   TimeDateStamp;      // 文件创建时间戳
    WORD    MajorVersion;       // 未使用,总为0 

    WORD    MinorVersion;       // 未使用,总为0
    DWORD   Name;               // 指向一个代表此 DLL名字的 ASCII字符串的 RVA
    DWORD   Base;               // 函数的起始序号
    DWORD   NumberOfFunctions;  // 导出函数的总数

    DWORD   NumberOfNames;      // 以名称方式导出的函数的总数

    DWORD   AddressOfFunctions;     // 指向输出函数地址的RVA
    DWORD   AddressOfNames;         // 指向输出函数名字的RVA
    DWORD   AddressOfNameOrdinals;  // 指向输出函数序号的RVA

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

AddressOfFunctions 所指向内容是以 4 字节为一个单位的数组成分,各类成分代表函数入口

AddressOfNames 所指向内容是以 4 字节为八个单位的数组元素,每一个成分代表二个针对字符串的 SportageVA

AddressOfNamesOrdinals 所指向内容是以 2 字节为二个单位的数组成分,每一种成分代表对应名字在 AddressOfFunctions 中的序号数。

AddressOfNames 和 AddressOfNamesOrdinals 的数据确定是均等的,不是一样那么就出错了。

主要要精晓三种检索函数入口地址的章程:

ELF&PE 文件结构剖判

说简练点,ELF 对应于UNIX 下的公文,而PE 则是Windows 的可实施文件,剖判ELF 和 PE 的文件结构,是逆向工程,或许是做调节和测试,乃至是付出所应具备的为主技能。在开展逆向工程的发端,大家得到ELF 文件,或然是PE 文件,首先要做的正是分析文件头,通晓消息,进而逆向文件。不说废话,起头深入分析:

ELF和PE 文件都以基于Unix 的 COFF(Common Object File Format) 退换而来,特别具体的来讲,他是来自当时盛名的 DEC(Digital Equipment Corporation) 的VAX/VMS 上的COFF文件格式。咱们从ELF 谈起。

【pker / CVC.GB】 
5、关于FASM 
----------- 
上边大家用FASM来编排大家的首先个程序。我们能够编写制定如下代码: 
format  PE GUI 4.0 
entry   __start 
section '.text' code    readable executable 
    __start: 
            ret 
大家把那么些文件存为test.asm并编写翻译它: 
fasm test.asm test.exe 
尚未任何烦人的参数,很有益,不是么? :P 
大家先来看一下以此顺序的构造。第一句是format提示字,它钦赐了程序的类别,PE表示自身 
们编写的是三个PE文件,前边的GUI提示编译器大家将动用Windows图形分界面。假使要编写制定一 
个调整台应用程序则能够内定为CONSOLE。假使要写贰个基石驱动,能够钦点为NATIVE,表示 
无需子系统帮忙。最后的4.0钦赐了子系统的版本号(还记得前边的MajorSubsystemVersion 
和MinorSubsystemVersion么?)。 
下边一行钦点了前后相继的入口为__start。 
section提示字表示大家要初始一个新节。大家的顺序独有八个节,即代码节,大家将其命名 
为.text,并钦命节属性为只读(readable)和可实行(executable)。 
从此就是我们的代码了,大家独有用一条ret指令回到系统,那时宾馆里的归来地址为Exit- 
Thread,所以程序直接退出。 
上面运转它,程序只是轻便地淡出了,大家中标地用FASM编写了四个程序!大家已经迈出了 
先是步,上面要让大家的次序能够做点什么。我们想要调用三个API,我们要怎么办吧?让 
咱俩再来充充电吧 :D 

AddressOfFunctions 所指向内容是以 4 字节为三个单位的数组成分,每一种成分代表函数入口

A. 从序号查找函数入口地址

  1. 定位到PE 文件头
  2. 从PE 文件头中的 IMAGE_OPTIONAL_HEADE牧马人32 结构中收取数据目录表,并从第三个数据目录中得到导出表的奇骏VA
  3. 从导出表的 Base 字段获得早先序号
    4. 将须要寻觅的导出序号减去早先序号Base,获得函数在入口地址表中的索引,检查实验索引值是或不是高于导出表的 NumberOfFunctions 字段的值,若是超过后面一个的话,表达输入的序号是没用的
  4. 用这几个索引值在 AddressOfFunctions 字段指向的导出函数入口地址表中抽取相应的种类,这正是函数入口地址的福特ExplorerVA 值,当函数棉被服装入内部存款和储蓄器的时候,那么些EvoqueVA 值加上模块实际装入的营地址,就收获了函数真正的进口地址

ELF

ELF 文件标准里把系统中利用ELF 格式的文本归类为各种:

  • 可重一直文件,Relocatable File ,这类文件包含代码和数量,可用来一连成可试行文件或分享目的文件,静态链接库归为此类,对应于Linux 中的.o ,Windows 的 .obj.
  • 可实践文件,Executable File ,那类文件富含了足以平素施行的次第,它的表示正是ELF 可推行文书,他们一般没有扩展名。比方/bin/bash ,Windows 下的 .exe
  • 分享指标文件,Shared Object File ,这种文件包含代码和数据,链接器可以行使这种文件跟别的可重一直文件的共享指标文件链接,产生新的靶子文件。别的是动态链接器能够将几个这种分享目标文件与可实施文件结合,作为进度印象来运维。对应于Linux 中的 .so,Windows 中的 DLL
  • 宗旨转储文件,Core Dump File,当进度意外终止,系统可以将该进程地址空间的原委及结束时的部分新闻转存到焦点转储文件。 对应 Linux 下的core dump。

ELF 文件的完好协会大要上是这么的:

ELF Header
.text
.data
.bss
... other section
Section header table
String Tables, Symbol Tables,..
  • ELF 文件头放在最前端,它满含了方方面面文件的主干品质,如文件版本,指标机器型号,程序入口等等。
  • .text 为代码段,也是反汇编管理的一对,他们是以机器码的样式储存,未有反汇编的进度基本不会有人读懂那一个二进制代码的。
  • .data 数据段,保存的那多少个曾经起头化了的全局静态变量部分静态变量
  • .bss 段,寄存的是未早先化的全局变量一对静态变量,那几个很轻易驾驭,因为在未早先化的情事下,我们单独用一个段来保存,可以不在一发端就分配空间,而是在终极总是成可施行文件的时候,再在.bss 段分配空间。
  • 任何段,还应该有部分可选的段,比如.rodata 表示这里存款和储蓄只读数据, .debug 代表调节和测验消息等等,具体境遇可以查阅相关文书档案。
  • 自定义段,这一块是为着兑现客商极其功效而存在的段,方便扩大,比方大家应用全局变量或许函数从前增加 **attribute(section('name'))** 就足以吧变量可能函数放到以name 作为段名的段中。
  • 段表,Section Header Table ,是贰个最首要的部分,它呈报了ELF 文件包涵的富有段的新闻,比如各个段的段名,段长度,在文件中的偏移,读写权限和一部分段的另外质量。

5.1、导入表 
----------- 
笔者们编辑如下代码并用TASM编写翻译: 

; tasm32 /ml /m5 test.asm 
; tlink32 -Tpe -aa test.obj ,,, import32.lib 

        ideal 
        p586 
        model   use32 flat 
extrn   MessageBoxA:near 
        dataseg 
str_hello       db      'Hello',0 
        codeseg 
__start: 
        push    0 
        push    offset str_hello 
        push    offset str_hello 
        push    0 
        call    MessageBoxA 
        ret 
        end     __start 
下边大家用w32dasm反汇编,得到: 
:00401000   6A00                    push    00000000 
:00401002   6800204000              push    00402000 
:00401007   6800204000              push    00402000 
:0040100C   6A00                    push    00000000 
:0040100E   E801000000              call    00401014 
:00401013   C3                      ret 
:00401014   FF2530304000            jmp     dword ptr [00403030] 
能够看到代码中的call MessageBoxA被翻译成了call 00401014,在那么些地点处是一个跳转 
指令jmp dword ptr [00403030],我们可以规定在地址00403030处寄存的是MessageBoxA的 
的确地址。 
实质上那几个地址是放在PE文件的导入表中的。上边大家后续我们的PE文件的求学。大家先来看 
转眼导入表的组织。导入表是由一类别的IMAGE_IMPORT_DESC福睿斯IPTO索罗德结构构成的。结构的个 
数由文件援用的DLL个数调节,文件援引了略微个DLL就有微微个IMAGE_IMPORT_DESCRIPTOR 
组织,最终还会有四个全为零的IMAGE_IMPORT_DESCENCOREIPTO奥德赛作为实现。 
typedef struct _IMAGE_IMPORT_DESCRIPTOR { 
    union { 
        DWORD   Characteristics; 
        DWORD   OriginalFirstThunk; 
    }; 
    DWORD   TimeDateStamp; 
    DWORD   ForwarderChain; 
    DWORD   Name; 
    DWORD   FirstThunk; 
} IMAGE_IMPORT_DESCRIPTOR; 
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR; 
Name字段是叁个本田CR-VVA,钦定了引进的DLL的名字。 
OriginalFirstThunk和FirstThunk在贰个PE未有加载到内部存款和储蓄器中的时候是同样的,都以指向一 
个IMAGE_THUNK_DATA结构数组。最后以多少个剧情为0的构造结束。其实那一个结构正是多个双 
字。那么些结构很风趣,因为在分歧的时候那么些协会意味着着不相同的含义。当以此双字的最高 
位为1时,表示函数是以序号的章程导入的;当最高位为0时,表示函数是以名称格局导入的, 
那是其一双字是叁个EnclaveVA,指向一个IMAGE_IMPORT_BY_NAME结构,那个协会用来指定导入函数 
名称。 
typedef struct _IMAGE_IMPORT_BY_NAME { 
    WORD    Hint; 
    BYTE    Name[1]; 
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; 
Hint字段表示三个序号,可是因为是按名称导入,所以这几个序号一般为零。 
Name字段是函数的称呼。 
上面大家用一张图来注明这些复杂的经过。假使一个PE引用了kernel32.dll中的LoadLibraryA 
和GetProcAddress,还会有八个按序号导入的函数800一千2h。 
IMAGE_IMPORT_DESCRIPTOR                                  IMAGE_IMPORT_BY_NAME 
+--------------------+   +--> +------------------+     +-----------------------+ 
| OriginalFirstThunk | --+    | IMAGE_THUNK_DATA | --> | 023B |  ExitProcess   | <--+ 
+--------------------+        +------------------+     +-----------------------+    | 
|   TimeDataStamp    |        | IMAGE_THUNK_DATA | --> | 0191 | GetProcAddress | <--+--+ 
+--------------------+        +------------------+     +-----------------------+    |  | 
|   ForwarderChain   |        |     80010002h    |                                  |  | 
+--------------------+        +------------------+    +---> +------------------+    |  | 
|        Name        | --+    |         0        |    |     | IMAGE_THUNK_DATA | ---+  | 
+--------------------+   |    +------------------+    |     +------------------+       | 
|     FirstThunk     |-+ |                            |     | IMAGE_THUNK_DATA | ------+ 
+--------------------+ | |    +------------------+    |     +------------------+ 
                       | +--> |   kernel32.dll   |    |     |     80010002h    | 
                       |      +------------------+    |     +------------------+ 
                       |                              |     |         0        | 
                       +------------------------------+     +------------------+ 
还记得前面大家说过在二个PE未有被加载到内部存款和储蓄器中的时候IMAGE_IMPORT_DESCRIPTOR中的 
OriginalFirstThunk和FirstThunk是平等的,那么为何Windows要侵夺三个字段呢?其实 
是这般的,在PE文件被PE加载器加载到内部存款和储蓄器中的时候这么些加载器会自动把FirstThunk的值替 
换为API函数的的确入口,也便是相当前边jmp的真正地址,而OriginalFirstThunk只但是是 
用来反向查找函数名而已。 
好了,又讲了如此多是要做哪些吧?你当时就能够看到。下边大家就来布局大家的导入表。 
作者们用来下代码来起始大家的引进节: 
section '.idata' import data    readable 
section提示字表示大家要最初三个新节。.idata是其一新节的名目。import data表示那是 
多个引进节。readable表示那些节的节属性是只读的。 
假定大家的次第只须要引进user32.dll中的Message博克斯A函数,那么大家的引进节唯有二个 
陈诉这么些dll的IMAGE_IMPORT_DESC陆风X8IPTO中华V和五个全0的布局。思考如下代码: 
    dd      0                   ; 大家并无需OriginalFirstThunk 
    dd      0                   ; 大家也无需管那一个小时戳 
    dd      0                   ; 大家也不关怀这几个链 
    dd      RVA usr_dll         ; 指向大家的DLL名称的HighlanderVA 
    dd      RVA usr_thunk       ; 指向咱们的IMAGE_IMPORT_BY_NAME数组的RVA 
                                ; 注意那个数组也是以0末段的 
    dd      0,0,0,0,0           ; 甘休标记 
地点用到了贰个EscortVA伪指令,它钦点的地址在编写翻译时被活动写为对应的劲客VA值。上面定义我们 
要引进的动态链接库的名字,那是贰个以0最终的字符串: 
    usr_dll     db      'user32.dll',0 
再有我们的IMAGE_THUNK_DATA: 
    usr_thunk: 
        MessageBox      dd      RVA __imp_MessageBox 
                        dd      0                   ; 甘休标识 
上面的__imp_MessageBox在编写翻译时由于前边有GranCabrioVA提示,所以表示是IMAGE_IMPORT_BY_NAME的 
RAV4VA。上面我们定义那些结构: 
    __imp_MessageBox    dw      0                   ; 大家不按序号导入,所以能够 
                                                    ; 轻松地置0 
                        db      'MessageBoxA',0     ; 导入的函数名 
好了,大家完毕了导入表的确立。上面大家来看三个一体化的程序,看看叁个完整的FASM程序 
是何其的爱不释手 :P 
format  PE GUI 4.0 
entry   __start 

AddressOfNames 所指向内容是以 4 字节为一个单位的数组成分,各种成分代表八个针对字符串的 QashqaiVA

B. 从函数名称查找入口地址

自己想通的地点,记录下来:用函数名来寻觅的话,Base 的值今后从未有过其余意义

  1. 率先获得导出表的地点
  2. 从导出表的 NumberOfNames 字段获得已命名函数的总额,并以这一个数字作为循环的次数来协会二个循环,从 AddressOfNames 字段指向获得的函数名称地址表的率先项开首,在循环元帅每一种定义的函数名与要物色的函数名相相比,若无别的二个函数名是符合的,表示文件中从不点名名称的函数。
    3. 假如某一项定义的函数名与要物色的函数名符合,那么记下这一个函数名在字符串地址表中的索引值,然后在AddressOfNamesOrdinals 指向的数组中以同等的索引值收取数组项的值,大家那边要是这么些值是 x
  3. 末尾,以 x 的值作为索引值在 AddressOfFunctions  字段指向的函数入口地址表中得到 TiguanVA 。此 CRUISERVA 正是函数的入口地址。

附上图片:

] 9.导出表 IMAGE_EXPORT_DIRECTORY,dockerexportimage typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; // 未使用,总为0 DWORD TimeDateStamp;...

ELF Header

ELF 文件音信的查阅利器在Linux 下是是objdump, readelf, 相关命令相当多,可查。下边大家从ELF 文件头提及。

文本头包蕴的内容比较多,大家在Ubuntu 系统下使用 readelf 命令来查看ELF 文件头:

澳门博发娱乐官网 1

大家以bash 那些可实践文件为例,我们得以看看ELF 文件头定义了ELF 魔数,文件机器字节长度,数据存储格局,版本,运维平台,ABI版本,ELF 重定位类型,硬件平台,硬件平台版本,入口地址,程序头入口和尺寸,段表的地点和尺寸,段的数码。

ELF 文件头的构造和有关常数一般定义在了 /usr/include/elf.h 中,大家能够步向查看一下:

澳门博发娱乐官网 2

除却第二个,其余都以逐个对应的,第二个是三个优孟衣冠了Magic number, Class, Data, Version, OS/ABI, ABI version.

出现在最发轫的ELF Magic number, 16字节是用来标志ELF 文件的平台属性,比如字长,字节序,ELF 文件版本。在加载的时候,首先会确认魔数的没有错,不得法的话就不肯加载。

另贰个要害的事物是段表(Section Header Table) ,保存了熟视无睹段的着力质量,比如段名,段长度,文件中的偏移,读写权限,段的别样质量。而段表本身在ELF 文件中的地点是在ELF 头文件 e_shoff 决定的。

大家可以使用 objdump -h 的一声令下来查看ELF 文件中带有哪些段,以bash 这一个可进行为例,其实除了大家前边说的什么样基本协会,他带有众多其余的结构:

澳门博发娱乐官网 3

一样的,大家接纳readelf -S 的吩咐也得以进行查看。

上边我们来看一下布局,照旧到elf.h 中去查看,他的结构体名字叫 Elf32_Shdr,64位对应Elf64_Shdr,结构如下:

澳门博发娱乐官网 4

以上结构中,分别对应于:

  • 段名
  • 段类型
  • 段标识位
  • 段虚构地址
  • 段偏移
  • 段长度
  • 段链接
  • 段对齐
  • 项,一些轻重缓急固定的项,如符号表等。

那些品种,在使用readelf -S 指令时一一对应。

别的还会有二个十分重要的表,叫重定位表,一般段名称叫.rel.text, 在上头未有现身,链接器在管理指标文件时,需求对目的文件中的有个别地方实行重一直,便是代码段和数据段中那三个对相对地址引用的岗位,这一年就要求使用重定位表了。


; data section... 

section '.data' data    readable 
    pszText         db      'Hello, FASM world!',0 
    pszCaption      db      'Flat Assembler',0 

本文由胜博发-操作发布,转载请注明来源:AddressOfFunctions 所指向内容是以 澳门博发娱乐官网