用16进制编辑器编写一个DLL文件

【文章标题】: 用16进制编辑器编写一个DLL文件
【文章作者】: newjueqi  
【作者邮箱】: [email protected]
【作者QQ号】:190678908

【软件名称】: Hello  
【软件大小】:4K
【编写语言】: 机器码
【使用工具】: WinHex
【操作平台】: xpSp2
【作者声明】: 手写DLL一方面为了体会一下最早期程序员一个二进制一个二进制地写程序的感觉,另一方面加强对 PE文件的认识,失误之处敬请诸位大侠赐教!


  
 

*****************************************************************************

    PE文件格式是Windows下可执行文件的格式,熟悉PE文件将对操作系统和编译器工作原理的深刻理解。
    本人之所以选择手写DLL而不是手写EXE主要原因是DLL文件比起EXE文件多了输出表和重定位表的处理,手写DLL可以对PE的理解更深刻,有关手写EXE的可参考dncwbc大大写的文章:http://bbs.pediy.com/showthread.php?t=48590

  本次手写DLL是输出一个函数显示一个对话框,对话框标题是“hello”,内容是“hello,pediy!!!”。由以上可知道,DLL文件涉及到的区块如下

                                        表1

   本文的重点是上图所示的几个区块的构建,其它部分如果比较重要的会加说明,如果不重要的就略过,需要详细了解的请参考相关资料。
   那么,就从DOS部首开始分析,DOS部首是一个IMAGE_DOS_ HEADER,结构如下:

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

MS_DOS头部我们关心的只有两个字段:e_magic 和 e_lfanew。e_magic需要被设置成5A4Dh,这个值有个宏是IMAGE_DOS_SIGNATURE,翻译成相应的ASCⅡ码就是“MZ”,是某位大牛名字的缩写(至于是哪位大牛,请翻看《加密与解密3》P266),另外一个关键的字段是e_lfanew,这个字段指出了真正PE文件头的偏移量,当PE加载器加载文件后,用基址加上e_lfanew的偏移量,就可得到PE文件的指针。
 接着是DOS stud部分,在windows下用不到,预留80字节的空间。
 现在来计算一下,MS_DOS头部共19个字段值,占64个字节,80+64=144转化为16进制就是90,所以PE文件头在整个文件里的偏移量为90,e_lfanew设置为90 00 00 00( 因为Intel CPU 字符存储是低位在前,高位在后,要把00 00 00 90 写成90 00 00 00 )。
 在DOS头部分,需要设置 e_magic 为4D5A, e_lfanew 为90 00 00 00。
完成后内容如下:

00000000   4D 5A 00 00 00 00 00 00  00 00 00 00 00 00 00 00   MZ..............
00000010   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00  00 00 00 00 90 00 00 00   ............?..
00000040   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000050   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000060   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000070   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000080   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

紧接着DOS文件头是PE文件头(PE Header ),是PE相关结构NT映像头(IMAGE_NT_HEADERS)的简称,内容如下: 

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
IMAGE_NT_HEADERS结构中第一个字段Signature被设置成00004550h,转化成ASCⅡ码就是“PE00”,在#define IMAGE_NT_SIGNATURE中定义,这个字段标志着PE文件头的开始。
IMAGE_FILE_HEADER( 映像文件头)中包含了PE文件的一些基本信息,结构如下:

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

(1)  Machine:两个字节,可执行文件的目标CPU类型,几种常见的CPU类型如下表:
  

                        表2


     对于我们常用的Intel平台,我们选择设置为014Ch,在16进制编辑器里输入“4C 01”
(2)  NumberOfSections:两个字节,区块的数目,紧接着IMAGE_NT_HEADERS后面,从表1可看到我们选择创建了5个区块,所以应该设置成“00 05”, 在16进制编辑器里输入“05 00”。
(3)  TimeDateStamp:四个字节,文件的创建的时间,设置为“00 00 00 00”, 在16进制编辑器里输入“00 00 00 00”。
(4)  PointerToSymbolTable:四个字节,COFF符号表的文件偏移位置,设置为“00 00 00 00”, 在16进制编辑器里输入“00 00 00 00”。
(5)  NumberOfSymbols:四个字节,如果有COFF符号表,就表示符号表的数目,设置为“00 00 00 00”, 在16进制编辑器里输入“00 00 00 00”。
(6)  SizeOfOptionalHeader:两个字节,紧接着IMAGE_FILE_HEADER后面的IMAGE_OPTIONAL_HEADER32的数据大小,通常对于32位系统,通常设置为00 E0h,对于64位的PE32+文件,通常是00 F0h,设置为“00 E0”, 在16进制编辑器里输入“E0 00”。
(7)  Characteristics:两个字节,表示文件的属性,各个位的含有如下:
Bit 0:没有重定位信息的话就置1
Bit 1:是可执行文件就置1,表示不是一个目标文件或库文件。这里说明一下,所谓的可执行文件不单单指EXE文件,更包括了编译成功的文件。
Bit 2:行号信息被移去就置1。
Bit 3:符号信息被移去就置1。
Bit 4:应用程序可处理超过2G的地址时就置1。
Bit 7:处理器的低字节是相反的就置1。
Bit 8:目标平台是32位机器就置1。
Bit 9:如果没有调试信息在内就置1。
Bit 10:如果程序不能从移动磁盘或多媒体光盘执行就置

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

newjueqi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值