利用masm32输出PE文件头的基本属性

文章目录

    • 利用masm32输出PE文件头的基本属性
  • 一、masm32中的INVOKE
  • 二、PE头格式
  • 三、读取代码

注:本文章作者水平较低,本文仅为作者自主实验时的学习笔记,如有不妥之处,还请指正,文中斜体皆为参考权威书籍
参考:《X86汇编语言》王爽
《加密与解密》第四版
《逆向工程核心原理》
工具:PEView,ollydbg,masm32环境

一、masm32中的INVOKE

INVOKE伪指令仅在32位的情况下使用,将参数逆序(与声明参数顺序相反)入栈,它是call的方便替代品,在一行代码内就可以传送多个参数,例如:

;原型声明
Print PROTO stdcall:DWORD,:DWORD,:DWORD,:DWORD
;.....
.code
;过程定义
Print PROC res:DWORD,blank:DWORD,blank1:DWORD,t:DWORD;......ret
Print ENDP

在该例中,Print函数接收四个Dword类型参数:res,blank,blank1,t
其中 PROTO是原型伪指令,stdcall是调用约定,PROC和ENDP中间夹着的是过程的程序指令
1、PROTO
PROTO伪指令为现有的过程创建原型(名称和参数列表),MASM要求所有INVOKE调用的过程都有原型,所以,标准格式如下

func PROTO
;原型声明
INVOKE func
;过程调用
;实现
func PROC
;.....
func ENDP

2、调用约定
我们先来看看invoke调用过程的具体汇编代码:

.data
str1 BYTE "abcde",0
num1 DWORD 66h
func1 PROTO :DWORD,:DWORD
func2 PROTO stdcall :DWORD,:DWORD
.codefunc1 PROC n1:DWORD,n2:DWORD
MOV eax,n1
ret
func1 ENDPfunc2 PROC n1:DWORD,n2:DWORD
MOV eax,n2
ret
func2 ENDPmain PROC
INVOKE func1 ,num1,addr str1
INVOKE func2 ,num1,addr str1
INVOKE ExitProcess,0
main ENDP
END main

汇编以后放入OLLYDBG中
可以看到,在INVOKE经过汇编器后,转化成了正常的函数调用,即
①将参数和返回地址入栈②将程序流程转到对应函数

看到函数内部,INVOKE自动帮我们完成了栈帧的建立(每个函数前两句汇编),并且
①加入leave②将ret变成retn,帮助我们清除了栈帧
下面陈述栈帧与调用约定的关系

①在函数调用开始前,调用函数的程序将参数(arguments)压入栈中
call指令执行,栈中压入call下一条指令的地址,并将EIP设置成函数第一条指令的地址
③那么函数是怎么描述自己参数的呢?答案是靠相对位置,栈底位置(地址)保存在ebp中,而栈顶位置保存在esp中,在新的函数中有新的临时变量和参数,程序需要利用参数和ebp相对的位置[ebp+x]描述参数或者变量所以需要更新旧的ebp。故,将last ebp入栈保存->push ebp。并将ebp设置为现在的栈底->mov ebp,esp(还没有往新的函数栈里面添加临时变量,所以栈顶栈底同位置)
④返回时,将ebp赋给esp,将栈顶瞬间缩至栈底,并且将旧ebp的值弹出至ebp,这两步在leave中实现
最后retn是将返回地址弹出给EIP,再将栈缩小操作数个字节,把栈顶调到参数之下(图上的下)
至此:栈在函数调用前后保持一致,可继续工作!
而这种由被调用函数进行栈清空的方式叫做stdcall!

(摘自百度百科)__stdcall表示
1.参数从右向左压入堆栈
2.函数被调用者修改堆栈
3.函数名(在编译器这个层次)自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸

二、PE头格式


从上到下从左到右除蓝黑色以外的部分分别是(图中为小端序)
IMAGE_DOS_HEADER:
e_magic: 5a4d
e_lfanew:000000e8
IMAGE_NT_HEADER:
Signature:00004550
IMAGE_FILE_HEADE:
NumberOfSections: 0003
TimeDateStamp:45d69be5
Characteristic: 010f
IMAGE_OPTIONAL_HEADER:
AddressOfEntryPoint:000073a5
ImageBase:01000000
SectionAligment:00001000
FileAligment:00000200

条件一:其中,除了蓝黑色的DOS存根以外,IMAGE_DOS_HEADER,IMAGE_NT_HEADER,IMAGE_FILE_HEADER是的长度是定长的

条件二:IMAGE_OPTINONAL_HEADER中显示的几项距离IMAGE_OPTINONAL_HEADER起始的偏移也是一定的

所以仅仅需要用CreateFile SetFilePointer ReadFile将文件读入,按照先后顺序利用基址变址寻址即可实现文件任意部分的读取
例如读入文件数据的首地址为buf,则WORD PTR [buf+esi] (esi此时为0)读取的就是4D 5A即e_magic,后只需要改变esi和取值时PTR类型即可读取文件的后续部分

解决DOS存根:在DOS头中,红色部分为e_lfanew其中存储的是NT头的文件偏移,正因为DOS存根不定长,所以需要此属性,在读取该属性后,赋给存变址的寄存器,加上基址就是程序中读入的NT头偏移了

三、读取代码

读一个文件用到的Windows API函数有CreateFile、SetFilePointer、ReadFile、CloseHandle。
CreateFile的MSDN文档地址添加链接描述

SetFilePointer函数的MSDN文档地址 添加链接描述

ReadFile函数的MSDN文档地址添加链接描述

CloseHandle函数的MSDN文档地址
添加链接描述
通过路径得到句柄,打开程序和文件的联系->通过句柄得到指向文件的指针->通过句柄读取文件内容->关闭文件和程序的连接

.386
.model flat, stdcall
option casemap:none
include D:\masm32\include\windows.inc
include D:\masm32\include\kernel32.inc
include D:\masm32\include\masm32.inc
includelib D:\masm32\lib\kernel32.lib
includelib D:\masm32\lib\masm32.lib
include D:\masm32\include\user32.inc
includelib D:\masm32\lib\user32.lib
ExitProcess PROTO, dwEXITCODE: DWORD.data
;待处理文件绝对路径
path BYTE "C:\Users\Em1ya\Desktop\Re\NOTE.exe",0;存放待处理文件的句柄
filehandle DWORD ?;以下数据全为显示字符,没有实际含义
str0 BYTE "    ",0
str1 BYTE "IMAGE_DOS_HEADER:",0
str2 BYTE "IMAGE_NT_HEADER:",0
str3 BYTE "IMAGE_FILE_HEADE:",0
str4 BYTE "IMAGE_OPTIONAL_HEADER:",0
str5 BYTE "e_magic:",0
str6 BYTE "e_lfanew:",0
str7 BYTE "Signature:",0
str8 BYTE "NumberOfSections:",0
str9 BYTE "TimeDateStamp:",0
stra BYTE "Characteristic:",0
strb BYTE "AddressOfEntryPoint:",0
strc BYTE "ImageBase:",0
strd BYTE "SectionAligment:",0
stre BYTE "FileAligment:",0
strn BYTE 0ah,00hfilebuf BYTE 4000 DUP(0)
filebase DWORD ?
var DWORD ?
;下面声明的是把十六进制值转为字符串输出的函数
Print PROTO stdcall:DWORD,:DWORD,:DWORD
Res BYTE "00000000",0
table BYTE "0123456789ABCDEF",0.code
Print PROC res:DWORD,hexdw:DWORD,t:DWORD;参数res待写缓冲区,hexdw待转换十六进制值,t数据种类,控制最后输出的字符个数MOV edx,0MOV edi,hexdwMOV ecx,8hMOV eax,res;edi指向待转换的值,ecx为循环变量,eax指向待写的缓冲区字符串;循环将最高位保留做与运算,拿到最低位作为索引在table里面拿值
L2:MOV ebx,ediAND ebx,0f0000000hSHR ebx,28MOV dl,BYTE PTR [table+ebx]MOV BYTE PTR[eax],dlINC eaxSHL edi,4
LOOP L2;将res的前t位变成空格MOV ecx,tMOV eax,res
L1: CMP ecx,0hJE L999MOV BYTE PTR[eax],20hINC eaxDEC ecxJMP L1
L999:;输出INVOKE StdOut, resMOV eax,hexdwret
Print ENDPmain PROC
INVOKE CreateFile,addr path,\GENERIC_READ,\FILE_SHARE_READ,\0,\OPEN_EXISTING,\FILE_ATTRIBUTE_ARCHIVE,\0
MOV filehandle,eax
INVOKE SetFilePointer, filehandle,\0,\0,\FILE_BEGIN
INVOKE ReadFile, filehandle,\addr filebuf,\3900,\0,\0
MOV esi,OFFSET filebuf
;以上操作将文件的内容写到了filebuf,之后读取filebuf就可以拿到PE文件的内容
;以下所有,esi为目标量在内存中的地址,eax为该地址对应值,print函数把eax传入,输出对应8-t个字符串
INVOKE StdOut,addr str1
INVOKE StdOut,addr strn
MOV eax,0h
INVOKE StdOut,addr str0
INVOKE StdOut,addr str5
;读第一个量
MOV ax,WORD PTR [esi]
MOV filebase,esi
INVOKE Print,addr Res,\eax,\4
INVOKE StdOut,addr strnADD esi,3ch
INVOKE StdOut,addr str0
INVOKE StdOut,addr str6
;读第二个量
MOV eax,DWORD PTR [esi]
INVOKE Print,addr Res,\eax,\0
;此处要注意,该数据为NT头的偏移量,所以将esi调整至NT头->内存基址加上NT头偏移
ADD eax,filebase
MOV esi,eax
INVOKE StdOut,addr strnINVOKE StdOut,addr str2
INVOKE StdOut,addr strn
INVOKE StdOut,addr str0
INVOKE StdOut,addr str7
;读第三个量
MOV eax,DWORD PTR [esi]
INVOKE Print,addr Res,\eax,\0
INVOKE StdOut,addr strnINVOKE StdOut,addr str3
INVOKE StdOut,addr strn
ADD esi,6h
INVOKE StdOut,addr str0
INVOKE StdOut,addr str8
;读第四个量
MOV eax,0
MOV ax,WORD PTR [esi]
INVOKE Print,addr Res,\eax,\4
INVOKE StdOut,addr strnADD esi,2h
INVOKE StdOut,addr str0
INVOKE StdOut,addr str9
;读第五个量
MOV eax,DWORD PTR [esi]
INVOKE Print,addr Res,\eax,\0
INVOKE StdOut,addr strnADD esi,0Eh
INVOKE StdOut,addr str0
INVOKE StdOut,addr stra
MOV eax,0
;读第六个量
MOV ax,WORD PTR [esi]
INVOKE Print,addr Res,\eax,\4
INVOKE StdOut,addr strnINVOKE StdOut,addr str4
INVOKE StdOut,addr strn
ADD esi,18
INVOKE StdOut,addr str0
INVOKE StdOut,addr strb
;读第七个量
MOV eax,DWORD PTR [esi]
INVOKE Print,addr Res,\eax,\0
INVOKE StdOut,addr strnADD esi,0ch
INVOKE StdOut,addr str0
INVOKE StdOut,addr strc
;读第八个量
MOV eax,DWORD PTR [esi]
INVOKE Print,addr Res,\eax,\0
INVOKE StdOut,addr strnADD esi,4h
INVOKE StdOut,addr str0
INVOKE StdOut,addr strd
;读第九个量
MOV eax,DWORD PTR [esi]
INVOKE Print,addr Res,\eax,\0
INVOKE StdOut,addr strnADD esi,4h
INVOKE StdOut,addr str0
INVOKE StdOut,addr stre
;读第十个量
MOV eax,DWORD PTR [esi]
INVOKE Print,addr Res,\eax,\0
INVOKE StdOut,addr strn
INVOKE CloseHandle,filehandle
INVOKE ExitProcess,0
main ENDP
END main

读取->转化->变址->读取


对照PEView验证


利用masm32输出PE文件头的基本属性相关推荐

  1. PE详解 - DOS文件头、PE文件头、节表和表详解

    原文地址:http://www.blogfshare.com/pe-header-one.html PE(Portable Executeable File Format,可移植的执行体文件格式),使 ...

  2. 怎样修改PE文件头大小

    转载请注明版权:http://a1pass.blog.163.com/    作者:A1Pass 黑客反病毒论坛 http://bbs.hackav.com 不知道通过上一节的学习与大家自己的努力,许 ...

  3. PE学习(三)第三章:PE文件头

    第三章:PE文件头 PE中涉及的地址有四类,它们分别为: 虚拟内存地址(VA) 相对虚拟内存地址(RVA) 文件偏移地址(FOA) 特殊地址  没有物理内存对应的页面被标记为dirty的页面,一般存储 ...

  4. UPack的PE文件头分析与OEP查找

    UPack(Ultimate PE压缩器),是一种PE文件的运行时压缩器,特点是使用独特的方法对PE头进行变形.UPack会使许多的PE分析程序无法正常运行,因此很多恶意代码都是通过UPack进行压缩 ...

  5. 直接修改PE文件头PE标识字段的实验

    PE是Microsoft为了让程序在Windows上可移植而做的一种文件格式规定. Windows在执行exe程序的时候,PE文件加载器会按照约定加载exe程序,所以程序就正常地运行起来了. 比如像E ...

  6. python 修改PE文件头

    在研究恶意软件分析时找到一个数据集,发现网上公开的能用的数据集不太好找,其中一篇论文声称提供了20m的巨量恶意软件样本 github链接: https://github.com/sophos-ai/S ...

  7. PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头3

    <PE2>中介绍了一些可选文件头中重要的属性,为了全面起见,本文将会讲解那些不是那么重要的属性.虽然不重要,但是还是可以发现很多好玩的情况.首先看一下32位的可选文件头详细定义.(转载请指 ...

  8. PE文件解析-文件头与整体介绍

    一.PE的基本概念 PE(Portable Execute)文件是Windows下可执行文件的总称,常见的有DLL,EXE,OCX,SYS等,事实上,一个文件是否是PE文件与其扩展名无关,PE文件可以 ...

  9. PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头2

    之前的博文中介绍了IMAGE_FILE_HEADER结构,现在来讨论比较复杂的"可选文件头"结构体.(转载请指明来自breaksoftware的csdn博客)先看下其声明 type ...

  10. 程序的本质之二ELF文件的文件头、section header和program header

    操作系统:CentOS Linux release 7.7.1908 内核版本:3.10.0-1062.1.1.el7.x86_64 运行平台:x86_64 参考文献:http://refspecs. ...

最新文章

  1. 2022-2028年中国公路客运行业市场研究及前瞻分析报告
  2. easyui使用ajax获取json文件,easyui 加载本地json 文件的方法
  3. AAAI 2021 | 语义解析最新进展解读
  4. Intel Realsense D435 测试摄像头在不同曝光值下的帧生成时间(防止曝光时间过长导致fps下降)auto_exposure_priority(没成功)
  5. 百度地图SDK v3.6.0以上版本找不到PoiOverlay类的解决方法
  6. Android SDK Manager 加载不出tools解决办法
  7. 前端那些年----Webstream快捷键备忘(mac)
  8. Codeforces Beta Round #51 D. Beautiful numbers 数位dp + 状态优化
  9. 找出一个字符串中出现次数最多的字_海量数据中找出前k大数(topk问题)
  10. 【hibernate merge】session1.merge(T entity)方法的含义和update方法的区别
  11. 关于虚拟机linux密码的那点事
  12. Python logging模块切分和轮转日志
  13. kafka版本_Apache Kafka 版本演进及特性介绍
  14. JVM内存分配与垃圾回收
  15. ASP.NET MVC5+EF6+EasyUI 后台管理系统(27)-权限管理系统-分配用户给角色
  16. OpenAI重磅开源多智能体博弈环境Neural MMO
  17. WinPmem:跨平台内存采集工具
  18. 高阶系统设计优化-----Bloom Filter
  19. crtlc不能复制文件_win10系统按ctrl+c快捷键无法复制文件的操作方法
  20. mediasoup 管道通信类UnixStreamSocket分析

热门文章

  1. 音视频格式.mp4和编码格式MPEG4以及ffmpeg转码
  2. 矢量控制——SVPWM
  3. 破解windows7系统密码
  4. Unity 安装失败原因
  5. 华为各系列数通网络产品介绍
  6. java 数组有序_Java有序数组
  7. kwgt公式代码大全_电脑文字识别ocr 数学公式 识别 mathtype
  8. 像中文的罗马音字体复制_罗马音大全可复制汉字下载
  9. 操作系统关闭透明大页指南
  10. python os创建txt文件,python创建txt文件方法详解