Win32病毒入门(二)

下边只摘录相比根本的字段:

在这几个IID数组中,并不曾指出有微微个项(正是从未强烈指明有个别许个链接文件),但它最后是以三个全为NULL(0)
的 IID 作为完毕的标志。


; data section… 

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

原稿链接地址:

FirstThunk

它包含由IMAGE_THUNK_DATA定义的 first
thunk数组的虚地址,通过loader用函数虚地址初阶化thunk。

在Orignal First Thunk缺席下,它指向first thunk:Hints和The Function
names的thunks。

 

上面来分解下OriginalFirstThunk和FirstThunk。就个人知道而言:

1.
在文书中时,他们都分别针对一个陆风X8VA地址。那几个地址转换来文件中,分别对应八个以
IMAGE_THUNK_DATA 为成分的的数组,那四个数组是以2个填写为 0
的IMAGE_THUNK_DATA作为落成标识符。即使她们那多个表地点差别,但实际内容是一模一样的。此时,每一种IMAGE_THUNK_DATA 成分指向的是3个记下了函数名和相呼应的DLL文件名的
IMAGE_IMPORT_BY_NAME结构体。

  1. 何以会有四个相同的数组呢?是有原因的:

OriginalFirstThunk 指向的数组经常称为  hint-name table,即 HNT ,他在 PE
加载到内部存储器中时被保存了下来且永远不会被改动。可是在 Windows 加载过 PE
到内部存款和储蓄器之后,Windows 会重写 FirstThunk
所指向的数组元素中的内容,使得数组中各类 IMAGE_THUNK_DATA
不再代表针对带有函数描述的 IMAGE_THUNK_DATA
成分,而是直接指向了函数地址。此时,FirstThunk
所指向的数组就叫做输入地址表(Import Address Table ,即日常说的
IAT)。

重写前:

365bet体育在线网投 1

重写后:

 365bet体育在线网投 2

(以上两张图纸源于:)

typedef struct _IMAGE_THUNK_DATA32 {
    union {
        DWORD ForwarderString;      // PBYTE  指向一个转向者字符串的RVA
        DWORD Function;             // PDWORD 被输入的函数的内存地址
         DWORD Ordinal;              // 被输入的 API 的序数值
         DWORD AddressOfData;        // PIMAGE_IMPORT_BY_NAME   指向 IMAGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

根据 _IMAGE_THUNK_DATA32 所指虚拟地址转到文件地方能够获得实质上的
_IMAGE_IMPORT_BY_NAME 数据

typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD   Hint;     // 序号 

    CHAR   Name[1];  // 实际上是一个可变长的以0为结尾的字符串

} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

 

比如说有程序:

365bet体育在线网投 3

文字版:

#include <windows.h>
int WINAPI WinMain(_In_ HINSTANCE hInstance, 
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR lpCmdLine,
    _In_ int nShowCmd)
{
    MessageBoxA(0, "hello", "my message", MB_OK);
    SetWindowTextA(0, "Si Wang");

    return 0;
}

此程序行使了四个 Windows API : MessageBoxA 和 SetWindowTextA

编写翻译获得程序(为简化表达,区段地方由软件总结出):

365bet体育在线网投 4

365bet体育在线网投 5

大家试着找出 MessageBoxA。首先分析 PE 头文件,找到导出表在文书中的地方:

365bet体育在线网投 6

输入表位置在 .rdata 区段内, 0x2264 – 0x三千 = 0x0264
获得偏移量。加上文件地方 0x0E00 得到实际文件偏移量(0x0E00 + 0x264 =
0x1064):0x1064。

接下去查看 0x1064 处:

365bet体育在线网投 7

能够取得两个 DLL 的叙说,最终1个_IMAGE_IMPORT_DESCENVISIONIPTO福睿斯以0填充表示截止:

那么一旦一个个查看各类DLL对应的数量就能找到,但是从前自个儿把全数的数目都看了下,在首先个DLL中

听大人说第3个DLL描述的 OriginalFirstThunk 的 0x2350
转换能够精晓,_IMAGE_THUNK_DATA32 在文书的 0x1150处,FirstThunk
指向的数目一致:

365bet体育在线网投 8

于是乎就获取了文件中的 MessageBoxA 的音讯。

末段,在内部存款和储蓄器中 FirstThunk 所指位置上的_IMAGE_THUNK_DATA32 数组被
Windows 加载后被重写后就成了典故中的 IAT ,Import Address
Table,输入地址表。使用 OllyDbg 查看运维时情状:

365bet体育在线网投 9

Name

它象征DLL
名称的相对虚地址(译注:相对一个用null作为实现符的ASCII字符串的3个凯雷德VA,该字符串是该导入DLL文件的名号。如:KE奥德赛NEL32.DLL)。


; code section… 

section ‘.text’ code    readable executable 
    _foo: 
            push    0 
            push    pszCaption 
            push    pszText 
            push    0 
            call    [MessageBox] 
            ret 
    _dll_entry: 
            xor     eax,eax 
            inc     eax 
            ret     0ch 

2) SizeOfCode: 代码段的轻重,假如有四个代码段则为总数

RAW:经过文件对齐处理后大小(PE文件中的大小)

365bet体育在线网投 10

365bet体育在线网投 11

在 PE文件头的 IMAGE_OPTIONAL_HEADERAV4 结构中的 DataDirectory(数据目录表)
的第一个分子正是指向输入表的。每一个被链接进来的 DLL文件都分别对应1个IMAGE_IMPORT_DESC猎豹CS6IPTOCR-V (简称IID) 数组结构。

FirstThunk

它包括由IMAGE_THUNK_DATA定义的 first
thunk数组的虚地址,通过loader用函数虚地址初始化thunk。

在Orignal First Thunk缺席下,它指向first thunk:Hints和The Function
names的thunks。

 

下边来解释下OriginalFirstThunk和FirstThunk。就个人理解而言:

1.
在文书中时,他们都分别针对一个PRADOVA地址。那么些位置转换来文件中,分别对应七个以
IMAGE_THUNK_DATA 为要素的的数组,那三个数组是以三个填写为 0
的IMAGE_THUNK_DATA作为完毕标识符。尽管她们那三个表地方差异,但实质上内容是一模一样的。此时,各个IMAGE_THUNK_DATA 成分指向的是三个笔录了函数名和相呼应的DLL文件名的
IMAGE_IMPORT_BY_NAME结构体。

  1. 怎么会有五个一律的数组呢?是有缘由的:

OriginalFirstThunk 指向的数组经常号称  hint-name table,即 HNT ,他在 PE
加载到内部存款和储蓄器中时被保留了下来且永远不会被涂改。但是在 Windows 加载过 PE
到内部存款和储蓄器之后,Windows 会重写 FirstThunk
所指向的数组成分中的内容,使得数组中每种 IMAGE_THUNK_DATA
不再代表针对带有函数描述的 IMAGE_THUNK_DATA
成分,而是平素针对了函数地址。此时,FirstThunk
所指向的数组就称为输入地址表(Import Address Table ,即常常说的
IAT)。

重写前:

365bet体育在线网投 12

重写后:

 365bet体育在线网投 13

(以上两张图片来源于:)

typedef struct _IMAGE_THUNK_DATA32 {
    union {
        DWORD ForwarderString;      // PBYTE  指向一个转向者字符串的RVA
        DWORD Function;             // PDWORD 被输入的函数的内存地址
         DWORD Ordinal;              // 被输入的 API 的序数值
         DWORD AddressOfData;        // PIMAGE_IMPORT_BY_NAME   指向 IMAGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

根据 _IMAGE_THUNK_DATA32 所指虚拟地址转到文件地方能够博得实在的
_IMAGE_IMPORT_BY_NAME 数据

typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD   Hint;     // 序号 

    CHAR   Name[1];  // 实际上是一个可变长的以0为结尾的字符串

} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

 

譬如说有先后:

365bet体育在线网投 14

文字版:

#include <windows.h>
int WINAPI WinMain(_In_ HINSTANCE hInstance, 
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR lpCmdLine,
    _In_ int nShowCmd)
{
    MessageBoxA(0, "hello", "my message", MB_OK);
    SetWindowTextA(0, "Si Wang");

    return 0;
}

此程序选拔了八个 Windows API : Message博克斯A 和 SetWindowTextA

编写翻译获得程序(为简化表明,区段位置由软件总结出):

365bet体育在线网投 15

365bet体育在线网投 16

我们试着找出 Message博克斯A。首先分析 PE 头文件,找到导出表在文书中的地点:

365bet体育在线网投 17

输入表地点在 .rdata 区段内, 0x2264 – 0x3000 = 0x0264
获得偏移量。加上文件地点 0x0E00 获得实质上文件偏移量(0x0E00 + 0x264 =
0x1064):0x1064。

接下去查看 0x1064 处:

365bet体育在线网投 18

能够得到多少个 DLL 的讲述,最终1个_IMAGE_IMPORT_DESC奥迪Q3IPTO奇骏以0填充表示截至:

那么一旦二个个查看各样DLL对应的数码就能找到,不过之前作者把富有的多少都看了下,在率先个DLL中

遵照第③个DLL描述的 OriginalFirstThunk 的 0x2350
转换能够通晓,_IMAGE_THUNK_DATA32 在文件的 0x1150处,FirstThunk
指向的多少一致:

365bet体育在线网投 19

于是乎就拿走了文本中的 MessageBoxA 的新闻。

最终,在内部存款和储蓄器中 FirstThunk 所指地点上的_IMAGE_THUNK_DATA32 数组被
Windows 加载后被重写后就成了旧事中的 IAT ,Import Address
Table,输入地址表。使用 OllyDbg 查看运维时情况:

365bet体育在线网投 20

5.三 、强大的宏 
————- 
至于FASM,还有3个有力的作用正是宏。大家对宏一定都不生疏,下边大家来探视在FASM中 
何以定义宏。假若大家要编写制定一个复制字符串的宏,个中源、指标串由ESI和EDI内定,我们 
可以: 
macro @copysz 

        local   next_char 
    next_char: 
        lodsb 
        stosb 
        or      al,al 
        jnz     next_char 

上边大家再来看3个带参数的宏定义: 
macro @stosd _dword 

    mov     eax,_dword 
    stosd 

如果大家要反复存入多少个分裂的双字大家得以归纳地在概念宏时把参数用中括号括起来,比 
如: 
macro @stosd [_dword] 

    mov     eax,_dword 
    stosd 

这么当我们调用@stosd 1,2,3的时候,大家的代码被编写翻译成: 
mov     eax,1 
stosd 
mov     eax,2 
stosd 
mov     eax,3 
stosd 
对于那种多参数的宏,FASM提供了多少个伪指令common、forward和reverse。他们把宏代码分 
成块并分别处理。上边作者分别来介绍: 
forward限定的块象征指令块对参数进行依次处理,比如上面的宏,如若把地方的代码定义在 
forward块中,大家能够取得平等的结果。对于forward块大家得以如此定义 
macro @stosd [_dword] 

    forward 
        mov     eax,_dword 
        stosd 

reverse和forward正好相反,表示指令块对参数举办反向处理。对于地方的命令块要是用 
reverse限定,那么大家的参数将被依照相反的顺序存入内部存款和储蓄器。 
macro @stosd [_dword] 

    reverse 
        mov     eax,_dword 
        stosd 

那会儿当大家调用@stosd 1,2,3的时候,我们的代码被编写翻译成: 
mov     eax,3 
stosd 
mov     eax,2 
stosd 
mov     eax,1 
stosd 
common限定的块将仅被处理处理一回。大家今日编写3个调用API的宏@invoke: 
macro @invoke _api,[_argv] 

    reverse 
        push    _argv 
    common 
        call    [_api] 

现行反革命我们得以行使这些宏来调用API了,比如: 
@invoke     MessageBox,0,pszText,pszCaption,0 
对此宏的应用我们就介绍那个,越多的代码能够参见笔者的useful.inc(其中有那个29A的宏, 
tnx 29a :P)

放另一张图:

365bet体育在线网投 21

再放一张:

365bet体育在线网投 22

Name

它代表DLL
名称的相对虚地址(译注:相对一个用null作为完毕符的ASCII字符串的1个PRADOVA,该字符串是该导入DLL文件的称呼。如:KETucsonNEL32.DLL)。

OriginalFirstThunk

它指向first thunk,IMAGE_THUNK_DATA,该 thunk 拥有 Hint 和 Function
name 的地址。


; import section… 

section ‘.idata’ import data    readable 
    ; image import descriptor 
    dd      0,0,0,RVA usr_dll,RVA usr_thunk 
    dd      0,0,0,RVA krnl_dll,RVA krnl_thunk 
    dd      0,0,0,0,0 
    ; dll name 
    usr_dll     db      ‘user32.dll’,0 
    krnl_dll    db      ‘kernel32.dll’,0 
    ; image thunk data 
    usr_thunk: 
        MessageBox      dd      RVA __imp_MessageBox 
                        dd      0 
    krnl_thunk: 
        ExitProcess     dd      RVA __imp_ExitProcess 
                        dd      0 
    ; image import by name 
    __imp_MessageBox    dw      0 
                        db      ‘MessageBoxA’,0 
    __imp_ExitProcess   dw      0 
                        db      ‘ExitProcess’,0 
总的来看那里本人信任大家都对FASM这些编写翻译器有了二个从头的认识,也迟早有很多读者会说:“ 
这么劳累啊,干啊要用这一个编写翻译器呢?”。是的,大概上边的代码看起来很复杂,编写起来 
也很费劲,但FASM的3个利益在于大家可以更积极地操纵我们转变的PE文件结构,同时能对 
PE文件有更理性的认识。不过每种人的气味不一,嘿嘿,大概上边的理由还不够说服各位读 
者,没提到,选取一款适合您的编译器吧,它们都如出一辙能够 😛 

3)       TimeDataStamp: 申明文件的缔造时间

在这几个IID数组中,并不曾提议有微微个项(正是没有理解指明有个别许个链接文件),但它说到底是以一个全为NULL(0)
的 IID 作为达成的标志。

在 PE文件头的 IMAGE_OPTIONAL_HEADELacrosse 结构中的 DataDirectory(数据目录表)
的第②个成员就是指向输入表的。各样被链接进来的 DLL文件都各自对应1个IMAGE_IMPORT_DESC奇骏IPTOPAJERO (简称IID) 数组结构。


; data section… 

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

2.2.IMAGE_FILE_365bet体育在线网投 ,HEADER(20 bytes)

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;                //运行平台
    WORD    NumberOfSections;        //文件区块数目
    DWORD   TimeDateStamp;            //文件创建日期和时间
    DWORD   PointerToSymbolTable;    //指向符号表(主要用于调试)
    DWORD   NumberOfSymbols;        //符号表中符号个数
    WORD    SizeOfOptionalHeader;        //IMAGE_OPTIONAL_HEADER32 结构大小
    WORD    Characteristics;            //文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

IMAGE_FILE_HEADE普拉多结构体成员解析:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;            // 0 for terminating null import descriptor
        DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
    } DUMMYUNIONNAME;
    DWORD   TimeDateStamp;                  // 0 if not bound,
                                            // -1 if bound, and real date\time stamp
                                            // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                            // O.W. date/time stamp of DLL bound to (Old BIND)

    DWORD   ForwarderChain;                 // -1 if no forwarders
    DWORD   Name;
    DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;            // 0 for terminating null import descriptor
        DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
    } DUMMYUNIONNAME;
    DWORD   TimeDateStamp;                  // 0 if not bound,
                                            // -1 if bound, and real date\time stamp
                                            // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                            // O.W. date/time stamp of DLL bound to (Old BIND)

    DWORD   ForwarderChain;                 // -1 if no forwarders
    DWORD   Name;
    DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;


; export section… 

section ‘.edata’ export data    readable 
    ; image export directory 
    dd      0,0,0,RVA dll_name,0,1,1 
    dd      RVA addr_tab 
    dd      RVA name_tab 
    dd      RVA ordinal_tab 
    ; dll name 
    dll_name        db      ‘foo.dll’,0 
    ; function address table 
    addr_tab        dd      RVA _foo 
    ; function name table 
    name_tab        dd      RVA ex_foo 
    ; export name table 
    ex_foo          db      ‘_foo’,0 
    ; ordinal table 
    ordinal_tab     dw      0 

3) SizeOfInitializedData: 初叶化数据段大小.假诺三个则为总数

365bet体育在线网投 23

365bet体育在线网投 24

发表评论

电子邮件地址不会被公开。 必填项已用*标注