首页
社区
课程
招聘
[原创]PEDIY技术之新思路(二)_用'高级'编译器MASM实现自定义PE文件结构
发表于: 2009-4-19 15:57 12264

[原创]PEDIY技术之新思路(二)_用'高级'编译器MASM实现自定义PE文件结构

2009-4-19 15:57
12264

【文章标题】: PEDIY技术之新思路(二)_用'高级'编译器MASM实现自定义PE文件结构
【文章作者】: moonife
【作者邮箱】: moonife@163.com
【作者QQ号】: 765496322
【下载地址】: 附件 
【编写语言】: win32 asm
【使用工具】:MASM 
【操作平台】: xp-sp3
【作者说明】:这两天被一个不知道是加了什么壳的东西搞郁闷了,所以一直想找个有意思的东东爽一下心情 ,把乐趣融入到学习当中,这个很重要!还有就是我写了 PEDIY技术之新思路(一),怎么说都得在表示一下吧!今天学习了xfish的《PE结构,SEH相关知识掌握》一文,心理面就特痒痒,也想完整自定义一个PE程序,但是我习惯的MASM却没有FASM那样可以自定义PE结构(一般高级编译器都是编译好的PE头部,例如MASM,TASM等,一直都说NASM,FASM是低级编译器,可以自定义PE结构)的功能,想过装一个FASM,但是很多习惯就得改,这样的话,我就不想干了,那我可不可以用MASM实现这样的定义呢?当然可以了,事实上,是上一篇文章给了我这样的思路,就是利用MASM编译器变通的编译二进制型汇编代码来实现,自觉还有点新意,所以就拿出来分享一下!好了,不说了,下面看实现过程,不足的地方还请高手指正,谢谢!
***************************************************实现过程*******************************************************
一:定义PE文件结构程序的实现

**************************************pe.asm*************************************************
REMOTE_CODE_START  equ this BYTE 
;****************************PE_HEADER_START*******************************
PE_HEADER_START equ this BYTE     
DOS_HEADER:                   ;>>>>>>>>>>>>>DOS头部
e_magic    db  'MZ'               ;-----------------------------说明---------------------------------------------
e_cblp           dw      0        ;事实上,从这里到e_res2无用部分可以用一句DUP(0)来完成,在这里编译器不会检查
e_cp             dw      0        ;你结构的定义是否正确,这些变量名也是没有意义的,这样写只是有利于我们认识
e_crlc           dw      0        ;PE结构而已,除了关键字,你可以任意写,因为它相当于写二进制型汇编代码
e_cparhdr        dw      0        ;事实上,和直接写二进制是一样一样的,只是这样就轻松多了。当然了,
e_minalloc       dw      0        ;这种方式的定义给我们带来的问题就是重定位,所以需要重定位的地方要小心了,
e_maxalloc       dw      0        ;你也可以把PE头部提上来到DOS头部里面来变形PE头,或者整个最小PE什么的,
e_ss             dw      0        ;随你怎么高兴怎么玩,但是要保证e_lfanew定位的正确,你想怎么来就怎么来,你自由了!
e_sp             dw      0        ;但是,没有绝对的自由,俗话说得好,任悟空本领再高,他也跳不出如来佛(OS)的手掌心啊
e_csum           dw      0        ;------------------------------------------------------------------------------
e_ip             dw      0
e_cs             dw      0
e_lfarlc           dw      0
e_ovno           dw      0
e_res            dw   4 dup(0)
e_oemid          dw      0
e_oeminfo        dw      0
e_res2           dw  10 dup(0)
e_lfanew         dd  NT_HEADERS-401000h

Dos_Stub:                   ;>>>>>>>>>>>>>>>>>>DOS小程序,这个写不写都行
  mov ah, 4ch              
  int 21h

NT_HEADERS:                            ;>>>>>>>>>>>>>PE文件头
Signature    dd  4550h     ;'PE'
Machine    dw  14ch     ;.Inten I386   
NumberOfSections   dw  2  ;定义了两个节区
TimeDateStamp    dd  0
PointerToSymbolTable  dd  0
NumberOfSymbols  dd  0  
SizeOfOptionalHeader  dw  0E0h
Characteristics  dw  010fh    ;.exe Signature
Magic      dw  10Bh   ;.exe file
MajorLinkerVersion  db  0
MinorLinkerVersion  db  0
SizeOfCode    dd  200h
SizeOfInitializedData  dd  0
SizeOfUninitializedData dd  0
AddressOfEntryPoint  dd  1000h ;oep
BaseOfCode    dd  1000h  ;Code Section Rva
BaseOfData     dd  0    ;Data Section Rva
ImageBase    dd  400000h
SectionAlignment  dd  1000h  ;Section Mem Align
FileAlignment    dd  200h  ;Section Disk Align
MajorOperSystemVersion dw  0    ;system version 主
MinorOperSystemVersion dw  0    ;system version 次
MajorImageVersion  dw  0    ;user version   主
MinorImageVersion  dw  0    ;user version   次
MajorSubsystemVersion  dw  4
MinorSubsystemVersion  dw  0
Win32VersionValue  dd  0    ;Reserved 0
SizeOfImage    dd  3000h     ;pe加载到内存后的映像大小
SizeOfHeaders    dd  200h  ;DosHeader + DosStub + NtHeader + Section Header
_CheckSum    dd  0
SubSystem    dw  2    ;Gui
DllCharacteristics  dw  0
SizeOfStackReserve  dd  100000h    
SizeOfStackCommit  dd  1000h    ;Stack = 4kb
SizeOfHeapReserve  dd  100000h
SizeOfHeapCommit  dd  1000h    ;Heap = 4kb
LoaderFlags    dd  0
NumberOfRvaAndSizes  dd  10h    ;16
DirectoryData1 dq 0       ;输出表填0
ImportTableAdress dd  IMPORT_START-401000h-400h+2000h ;定义输入表,这里的重定位稍微复杂,结合MakeData.asm,读者自己思考为什么!
ImportTableSize  dd  IMPORT_LENGTH
DirectoryData2 dq 14 dup(0)     ;剩下的数据目录表成员统统填0,

SECTION_HEADER1:                 ;>>>>>>>>>>>>块表1
Name1      db  'CODE', 0, 0, 0,0             ;节区名,八个字节大小
VirtualSize    dd  CODE_LENGTH
VirtualAddress    dd  1000h
SizeOfRawData    dd  200h
PointerToRawData  dd  CODE_START-401000h        ;也可以直接写成是200h,因为定义的pe头大小为200h
PointerToRelocations   dd   0
PointerToLinenumbers   dd   0
NumberOfRelocations    dw   0
NumberOfLinenumbers    dw   0
_Characteristics  dd    0E0000020h

SECTION_HEADER2:                  ;>>>>>>>>>>>>>>>>>>块表2,为了自建输入表,再定义一个块
Name2      db  'IMPORT', 0, 0               ;可不可以去掉这个块,把输入表放到代码块里面呢?可以,自己玩玩吧       
VirtualSize2    dd  IMPORT_LENGTH           ;当然了,也可以不建输入表,直接用PEB结构查找API也是可以的
VirtualAddress2    dd  2000h
SizeOfRawData2    dd  200h
PointerToRawData2  dd  IMPORT_START-401000h        ;也可以直接写成是400h
PointerToRelocations2   dd   0
PointerToLinenumbers2   dd   0
NumberOfRelocations2    dw   0
NumberOfLinenumbers2    dw   0
_Characteristics2  dd    0E0000020h
PE_HEADER_END equ this BYTE 
PE_HEADER_LENGTH equ offset PE_HEADER_END - offset PE_HEADER_START
ZeroSpace1 db 200h-PE_HEADER_LENGTH dup(0)           ;>>>>空白部分填充0,这个是必须的,这里的编译器不管这事,自己动手丰衣足食!
;**********************CODE_SECTION_START*******************************
CODE_START  equ this BYTE 
                     lea eax, [szContextR-200h]             ;想一下,这里为什么可以这样定位呢?
                     lea ebx,[szCpationR-200h]
                     push MB_OK
                     push  ebx
                     push eax
                     push 0
                     call DWORD ptr [IAT_1-1000h-400h+2000h]    ;CALL PE加载器填好的地址,我们在做应该是编译器做的工作
                     push 0
                     call DWORD ptr  [IAT_2-1000h-400h+2000h]
                      szContextR db 'Congratulations! You make it!',0dh,0ah
                                db '           By:moonife',0
                      szCpationR db 'OK',0
CODE_END  equ this BYTE 
CODE_LENGTH  equ  offset CODE_END - offset  CODE_START
ZeroSpace2 db 200h-CODE_LENGTH  dup(0)            ;空白部分填充0
;************************IMPORT_SECTION_START***************************
IMPORT_START  equ this BYTE 
IID_1:
OriginalFirstThunk  dd IAT_1-401000h-400h+2000h
TimeDateStemp   dd  0
ForwarderChain  dd  0
DllName         dd  DllName1-401000h-400h+2000h
FirstThunk      dd  IAT_1-401000h-400h+2000h     ;这里为了方便,把它和OriginalFirstThunk指向同一个地址的IAT结构
IID_2:
OriginalFirstThunk2  dd IAT_2-401000h-400h+2000h
TimeDateStemp2   dd  0
ForwarderChain2  dd  0
DllName2         dd  _DllName2-401000h-400h+2000h
FirstThunk2      dd  IAT_2-401000h-400h+2000h
IID_END:
IIDEND  dd 5 dup(0)
IAT_1:
AddressOfData1  dd  IIBN_1-401000h-400h+2000h
AddressOfDataEnd1  dd  0
IAT_2:
AddressOfData2  dd  IIBN_2-401000h-400h+2000h
AddressOfDataEnd2  dd  0
IIBN_1:
Hint1  dw  0
Nama1  db  'MessageBoxA',0
DllName1 db  'user32.dll',0,0
IIBN_2:
Hint2  dw  0
Nama2  db  'ExitProcess',0
_DllName2  db  'kernel32.dll',0,0
IMPORT_END   equ  this BYTE 
IMPORT_LENGTH  equ offset IMPORT_END - offset IMPORT_START 
ZeroSpace3 db 200h- IMPORT_LENGTH dup(0)            ;空白部分填充0,我也学学小鱼哥,问句:这个PE大小是多少BYTE呢?贼简单!嘿嘿!@
;***********************THE_PE_END****************************
REMOTE_CODE_END    equ this byte
REMOTE_CODE_LENGTH  equ offset REMOTE_CODE_END - offset REMOTE_CODE_START
*************************************THE_DEFINE _END***************************************************************

二:编译产生PE文件

**************************************MakeData.asm*************************************************
.586
.model flat,stdcall
option casemap:none
;***********************************************************************
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
;***********************************************************************
.data
hOutFile dd 0
BytesWritten dd 0
.const
szCaption db 'Info',0
szContext db 'success',0
szOutFileName  db 'pe.exe',0
;***********************************************************************
.code
include   pe.asm  ;这里把实现PE数据代码引入,编译并产生pe.exe文件,下面的就应该都看懂,就不讲了
start:
invoke  CreateFile,offset szOutFileName,GENERIC_READ or GENERIC_WRITE,\
          FILE_SHARE_READ,\
          NULL,CREATE_ALWAYS,\
          FILE_ATTRIBUTE_NORMAL,NULL
   mov  hOutFile,eax
invoke  WriteFile,hOutFile,offset REMOTE_CODE_START,REMOTE_CODE_LENGTH,addr BytesWritten,NULL
invoke  MessageBox,0,offset szContext,offset szCaption,MB_OK
invoke ExitProcess,0
end start
**********************************************MakeData_END************************************************************
三:至此,一个干干净净的PE就新鲜出炉了,来个成功截图:
                                                    
Oh!ye!还等什么,赶紧自己弄一个吧!
*************************************************THE_END*****************************************************************
附件清单:pe.asm,MakeData.asm,pe.exe,本文档
PS:感谢小鱼哥给我们带来了这么精彩的系列文章,特别感谢kanxue大哥和pediy团队已经各位版主辛勤的奉献给我们带来了这么好的交流平台!

重要更正:小鱼不是哥,是姐!


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (22)
雪    币: 288
活跃值: (212)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
,这样PE DIY方便多了,Thanks
2009-4-19 17:25
0
雪    币: 1564
活跃值: (3572)
能力值: ( LV13,RANK:420 )
在线值:
发帖
回帖
粉丝
3
厉害,佩服!
2009-4-19 17:44
0
雪    币: 264
活跃值: (11)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
4
很精彩的文章 LZ的妙文我都有拜读

BTW 小鱼难道不是MM??
2009-4-19 20:50
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
5
xfish是女的吗?我真真是不知道,猜的!
2009-4-19 20:58
0
雪    币: 133
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
啊啊啊,这样也行啊
2009-4-19 21:22
0
雪    币: 315
活跃值: (23)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
7
include   pe.asm  ;
start:
invoke  CreateFile,offset szOutFileName,GENERIC_READ or GENERIC_WRITE,\
          FILE_SHARE_READ,\
          NULL,CREATE_ALWAYS,\
          FILE_ATTRIBUTE_NORMAL,NULL
   mov  hOutFile,eax
invoke  WriteFile,hOutFile,offset REMOTE_CODE_START,REMOTE_CODE_LENGTH,addr BytesWritten,NULL
invoke  MessageBox,0,offset szContext,offset szCaption,MB_OK
invoke ExitProcess,0

哈哈不错,利用masm32的include语句针对包含文件的二进制数据编译来进行读取,写入。。
支持个

女的..
2009-4-19 21:50
0
雪    币: 264
活跃值: (11)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
8
不是单纯的女的 是美眉喔~
2009-4-19 22:15
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
9
那就小鱼姐了,再次膜拜!
2009-4-19 22:27
0
雪    币: 239
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
最后是否加多一句
invoke CloseHandle,hOutFile;

这样更完美一点

再次感谢楼主为我们提供一个新的PEDIY思路
2009-4-20 06:44
0
雪    币: 315
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
非常之强大,学习了~
2009-4-20 07:10
0
雪    币: 193
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
自己创建pe文件,受教了!
2009-4-20 10:34
0
雪    币: 307
活跃值: (575)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
楼主
牛!
2009-4-20 13:16
0
雪    币: 181
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
xfish
mermaid

oh~~ yeah~
2009-4-20 17:23
0
雪    币: 181
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
MASM
PE DIY

oh~~ YEAH~~
2009-4-20 17:25
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
16
可否提供小鱼哥联系方式
2009-4-24 22:40
0
雪    币: 167
活跃值: (1574)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
17
谢谢鱼姐和楼主的文章
2009-4-24 23:10
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
18
小鱼姐好几天不见了呀,我也在急啊...............
2009-4-25 00:01
0
雪    币: 2548
活跃值: (965)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
19
学到新东西了。。。
2009-4-25 14:30
0
雪    币: 140
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
先顶下,有空学习
2009-4-25 14:48
0
雪    币: 215
活跃值: (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
据说fasm 可以简单点?
2009-4-26 18:24
0
雪    币: 88
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
拜读强文。。。
2009-9-7 19:13
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
强啊 要好好学习
2009-9-8 20:12
0
游客
登录 | 注册 方可回帖
返回
//