深入浅出PE文件格式---自己动手打造PE Show

VC超级加壳机完整源码解析与实战 加壳技术(Packing)是一种将可执行程序代码进行压缩或加密,并在运行时由“壳”负责解密并还原原始代码的技术。它起源于20世纪90年代初期,最初用于减小程序体积,后逐渐演变为一种软件保护机制。在本章节中,我们深入探讨了原始程序数据注入技术的核心方法与实现细节。包括:注入方式:空白节、新增节、堆栈区域等。内存映射与重定位:确保注入数据在内存中能被正确访问。加密与解密机制:使用异或、AES等算法提升安全性。兼容性与稳定性处理:适配不同PE结构,处理异常与资源释放。 阅读详情

                深入浅出PE文件格式---自己动手打造PE Show
                                                            作者:廉明
////////////////////////////////////////////////////////////////////
//                            开篇                               //
///////////////////////////////////////////////////////////////////
   大家好!我一位菜鸟,学习加密解密已经有一段时间了,可是对于脱壳总是似懂非懂,心中甚是不爽。
于是就从PE结构开始,在学习的过程中我发现要真正了解PE文件结构就必须动手,只有动手您才能看懂他,
感受他,直到你应用他………………这是我的一点废话希望大家不要嫌烦。下面是是我的学习笔记,希望能给大家
带来一点提示,文中有不对的地方请各位大虾指正。谢谢!
//////////////////////////////////////////////////////////////////
//                            准备                             //
/////////////////////////////////////////////////////////////////
开篇之前我想大家起码要有几点准备:
1。Iczelion's Win32 Assembly的教程我们主要是围绕他的PE教程来实现我们的函数功能。
    (其实Win32ASM Tutorial Resource Kit v1.00 Collected and packed by dREAMtHEATER就包含这些
    还是翻译过的。下载地址WWW.PEDIY.COM)
    下载回来希望您能看一下,这样大家就好交流:-)

2。一个开发环境。(我用的是VC++6.0)
3。一个适合你研究东西的环境。
////////////////////////////////////////////////////////////////
//                           正文                            //
///////////////////////////////////////////////////////////////

     “ PE 的意思就是 Portable Executable(可移植的执行体)。它是 Win32环境自身所带的执行体文件格
式。它的一些特性继承自 Unix的 Coff (common object file format)文件格式。"portable executable"
(可移植的执行体)意味着此文件格式是跨win32平台的 :
即使Windows运行在非Intel的CPU上,任何win32平台的PE装载器都能识别和使用该文件格式。当然,移植到不
同的CPU上PE执行体必然得有一些改变。所有 win32执行体
(除了VxD和16位的Dll)都使用PE文件格式,包括NT的内核模式驱动程序(kernel mode
drivers)。因而研究PE文件格式给了我们洞悉Windows结构的良机。“
      好了,上面这段话就是我们为什么要研究PE文件结构。
      看图1,

这张图我相信大家不陌生,第一块是DOS MZ header这是什么呢?
      这张图的每一块都是什么意思呢?
      从编程这方面说图中的每一块都代表着一个结构体,这些小块都包含有不同的子块,也是些结构体。
每个小块都有他自己的功能,我相信Iczelion's的教程中已经表达得很明白了。
那么我们就来开始动手。
 我们要设计我们自己的PE TOOLS----PE Show
 主要功能:1判断文件是否是PE文件。
           2显示pe文件的相关信息。

1.打开文件代码如下:
if(FALSE==PEfile.Open(m_filename,CFile::typeBinary|CFile::shareDenyNone))
 {
  MessageBox("文件打不开!");
  return;
 }
CFile类的使用方法希望大及自己去查找msdn
2。文件我们打开了而且是以Binary方式打开的,下面我们该干什么了?

  编写第一个功能-----检验PE文件的有效性
在Iczelion's的教程中有这样一段话:
“1。首先检验文件头部第一个字的值是否等于 IMAGE_DOS_SIGNATURE,是则 DOS MZ header 有效。
 2。一旦证明文件的 DOS header 有效后,就可用e_lfanew来定位 PE header 了。
 3。比较 PE header 的第一个字的值是否等于 IMAGE_NT_HEADER。
    如果前后两个值都匹配,那我们就认为该文件是一个有效的PE文件。
这就是检验PE文件有效性的流程。
从上面那段话我们看出判断的关键是PE header 的第一个字的值是否等于 IMAGE_NT_HEADER
直到这些我们就倒着找。
PE header 的第一个字的值是什么?
我么就来看一下IMAGE_NT_HEADERS的结构:(查看WINNT.H就找到了)
typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
Signature 一dword类型,值为50h, 45h, 00h, 00h(PE/0/0)。 本域为PE标记,我们可以此识别给定文件是否为有效PE文件。
FileHeader 该结构域包含了关于PE文件物理分布的信息, 比如节数目、文件执行机器等。
OptionalHeader 该结构域包含了关于PE文件逻辑分布的信息,虽然域名有"可选"字样,但实际上本结构总是存在的。
我们目的很明确。如果IMAGE_NT_HEADERS的signature域值等于"PE/0/0",那么就是有效的PE文件。实际上,为了比较方便,Microsoft已定义了常量IMAGE_NT_SIGNATURE供我们使用。
IMAGE_DOS_SIGNATURE equ 5A4Dh
IMAGE_OS2_SIGNATURE equ 454Eh
IMAGE_OS2_SIGNATURE_LE equ 454Ch
IMAGE_VXD_SIGNATURE equ 454Ch
IMAGE_NT_SIGNATURE equ 4550h

判断的问题我们解决了,新的问题又来了我们如何定位IMAGE_NT_HEADERS结构的位置。
MS肯定有办法,PE文件的开头是什么?DOS MZ 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;
  看一下最后一项!!!!!
  发现了吗?他指向的就是PE header
  那么DOS MZ header的位置怎么确定呢?呵呵,他就是文件的开始
  看代码:
        PEfile.Read(&stPEDosHeader,sizeof(_IMAGE_DOS_HEADER));
 if(stPEDosHeader.e_magic!=IMAGE_DOS_SIGNATURE)//"MZ"
 {
  MessageBox("DOS MZ header无效!");
  PEfile.Close();
  return;
 }
 else
 {
  //-----------------------
  //显示DOS Header
  //-----------------------
  UpdateData(true);
  m_Magicnumber.Format(_T("0x%.4X"),stPEDosHeader.e_magic);
  m_cblp.Format(_T("0x%.4X"),stPEDosHeader.e_cblp);
  m_cp.Format(_T("0x%.4X"),stPEDosHeader.e_cp);
  m_crlc.Format(_T("0x%.4X"),stPEDosHeader.e_crlc);
  m_cparhdr.Format(_T("0x%.4X"),stPEDosHeader.e_cparhdr);
  m_minalloc.Format(_T("0x%.4X"),stPEDosHeader.e_minalloc);
  m_maxalloc.Format(_T("0x%.4X"),stPEDosHeader.e_maxalloc);
  m_ss.Format(_T("0x%.4X"),stPEDosHeader.e_ss);
  m_sp.Format(_T("0x%.4X"),stPEDosHeader.e_sp);
  m_csum.Format(_T("0x%.4X"),stPEDosHeader.e_csum);
  m_ip.Format(_T("0x%.4X"),stPEDosHeader.e_ip);
  m_cs.Format(_T("0x%.4X"),stPEDosHeader.e_cs);
  m_lfarlc.Format(_T("0x%.4X"),stPEDosHeader.e_lfarlc);
  m_ovno.Format(_T("0x%.4X"),stPEDosHeader.e_ovno);
  m_oemid.Format(_T("0x%.4X"),stPEDosHeader.e_oemid);
  m_oeminfo.Format(_T("0x%.4X"),stPEDosHeader.e_oeminfo);
  m_lfanew.Format(_T("0x%.8X"),stPEDosHeader.e_lfanew);
  UpdateData(false);
 }


 buf=stPEDosHeader.e_lfanew;  //确定_IMAGE_DOS_HEADER偏移
 try{PEfile.Seek(buf,CFile::begin);}
 catch(...)
 {
  MessageBox("_IMAGE_DOS_HEADER.e_lfanew不对!");
  PEfile.Close();
  return;
 }
 PEfile.Read(&stPEHeader,sizeof(_IMAGE_NT_HEADERS));//----------NT头
 if(stPEHeader.Signature!=IMAGE_NT_SIGNATURE)//"PE/0/0"
 {
  MessageBox("该文件不是PE格式!");
  PEfile.Close();
  return;
 }
 else
       {
          MessageBox("该文件是PE格式!");
          PEfile.Close();
  return;
        } 


好了现在我们已经确定了文件是否是有效的PE文件。顺便我们把IMAGE_DOS_HEADER的结构成员都显示出来了。
我们已经写了一个功能。
下面我们继续顺着往下看:
IMAGE_DOS_HEADER结构结束那么就是IMAGE_NT_HEADERS开始。结构体的成员情况前面我们已经介绍过了
下面我们来提取他们:
                //---------------------------
  //显示IMAGE_FILE_HEADER结构
  //---------------------------
  UpdateData(true);
  m_Machine.Format(_T("0x%.4X"),stPEHeader.FileHeader.Machine);
  m_NumberOfSections.Format(_T("0x%.4X"),stPEHeader.FileHeader.NumberOfSections);
  m_TimeDateStamp.Format(_T("0x%.8X"),stPEHeader.FileHeader.TimeDateStamp);
      m_PointerToSymbolTable.Format(_T("0x%.8X"),stPEHeader.FileHeader.PointerToSymbolTable);
  m_NumberOfSymbols.Format(_T("0x%.8X"),stPEHeader.FileHeader.NumberOfSymbols);
  m_SizeOfOptionalHeader.Format(_T("0x%.4X"),stPEHeader.FileHeader.SizeOfOptionalHeader);
  m_Characteristics.Format(_T("0x%.4X"),stPEHeader.FileHeader.Characteristics);
  UpdateData(false);      
这是IMAGE_FILE_HEADER FileHeader的成员,我们已经将他们提取出来。
看教程我们继续寻找IMAGE_OPTIONAL_HEADER的成员,他是结构体中的结构体我们就顺着找。
typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //

    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    //
    // NT additional fields.
    //

    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

 

看到这些成员将他们全部显示出来


                 //--------------------------------
  //显示IMAGE_OPTIONAL_HEADER
  //--------------------------------
  UpdateData(true);
  m_Magic.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.Magic);
  m_MajorLinkerVersion.Format(_T("0x%.2X"),stPEHeader.OptionalHeader.MajorLinkerVersion);
  m_MinorLinkerVersion.Format(_T("0x%.2X"),stPEHeader.OptionalHeader.MinorLinkerVersion);
  m_SizeOfCode.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfCode);
  m_SizeOfInitializedData.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfInitializedData);
  m_SizeOfUninitializedData.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfUninitializedData);
  m_AddressOfEntryPoint.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.AddressOfEntryPoint);
  m_BaseOfCode.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.BaseOfCode);
  m_BaseOfData.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.BaseOfData);
  m_ImageBase.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.ImageBase);
  m_SectionAlignment.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SectionAlignment);
  m_FileAlignment.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.FileAlignment);
  m_MajorOperatingSystemVersion.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.MajorOperatingSystemVersion);
  m_MinorOperatingSystemVersion.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.MinorOperatingSystemVersion);
  m_MajorImageVersion.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.MajorImageVersion);
  m_MinorImageVersion.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.MinorImageVersion);
  m_MajorSubsystemVersion.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.MajorSubsystemVersion);
  m_MinorSubsystemVersion.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.MinorSubsystemVersion);
  m_Win32VersionValue.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.Win32VersionValue);
  m_SizeOfImage.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfImage);
  m_SizeOfHeaders.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfHeaders);
  m_CheckSum.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.CheckSum);
  m_Subsystem.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.Subsystem);
  m_DllCharacteristics.Format(_T("0x%.4X"),stPEHeader.OptionalHeader.DllCharacteristics);
  m_SizeOfStackReserve.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfStackReserve);
  m_SizeOfStackCommit.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfStackCommit);
  m_SizeOfHeapReserve.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfHeapReserve);
  m_SizeOfHeapCommit.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.SizeOfHeapCommit);
  m_LoaderFlags.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.LoaderFlags);
  m_NumberOfRvaAndSizes.Format(_T("0x%.8X"),stPEHeader.OptionalHeader.NumberOfRvaAndSizes);
  UpdateData(false);
  

我们已经学了许多关于 DOS header 和 PE header 的知识。接下来就该轮到 section table(节表)了。
节表其实就是紧挨着 PE header 的一结构数组。该数组成员的数目由 file header (IMAGE_FILE_HEADER)
结构中 NumberOfSections 域的域值来决定。节表结构又命名为 IMAGE_SECTION_HEADER。
typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER

Name     这儿的节名长不超过8字节。记住节名仅仅是个标记而已,我们选择任何名字甚至空着也行,注意这里不用null结束。命名不是一个ASCIIZ字符串,所以不用null结尾。
VirtualAddress 本节的RVA(相对虚拟地址)。PE装载器将节映射至内存时会读取本值,因此如果域值是1000h,而PE文件装在地址400000h处,那么本节就被载到401000h。
SizeOfRawData 经过文件对齐处理后节尺寸,PE装载器提取本域值了解需映射入内存的节字节数。(译者注: 假设一个文件的文件对齐尺寸是0x200,如果前面的 VirtualSize域指示本节长度是0x388字节,则本域值为0x400,表示本节是0x400字节长)。
PointerToRawData 这是节基于文件的偏移量,PE装载器通过本域值找到节数据在文件中的位置。
Characteristics 包含标记以指示节属性,比如节是否含有可执行代码、初始化数据、未初始数据,是否可写、可读等。


现在我们已知晓 IMAGE_SECTION_HEADER 结构,再来模拟一下 PE装载器的工作吧:

1 读取 IMAGE_FILE_HEADER 的 NumberOfSections域,知道文件的节数目。
2 SizeOfHeaders 域值作为节表的文件偏移量,并以此定位节表。
3 遍历整个结构数组检查各成员值。
4 对于每个结构,我们读取PointerToRawData域值并定位到该文件偏移量。然后再读取SizeOfRawData域值来决定映射内存的字节数。将VirtualAddress域值加上ImageBase域值等于节起始的虚拟地址。然后就准备把节映射进内存,并根据Characteristics域值设置属性。
5 遍历整个数组,直至所有节都已处理完毕。
代码如下:
                //------------------------------
  //显示Section结构
  //------------------------------
  nSection=stPEHeader.FileHeader.NumberOfSections;
  stSectionHeader=new _IMAGE_SECTION_HEADER[nSection];
  m_ListCtrl.DeleteAllItems();
  for(int i=0;i
  {
   
   PEfile.Read(&stSectionHeader[i],sizeof(_IMAGE_SECTION_HEADER));//-----节表
   //NO
   szTemp.Format(_T("%.2d"), i+1);
   m_ListCtrl.InsertItem(i,szTemp,i);
   //SectionName
   strcpy(chSectionName,(LPCSTR)stSectionHeader[i].Name);
           m_ListCtrl.SetItemText(i,1,chSectionName);
   //VirtualSize
   szTemp.Format(_T("0x%.8X"),stSectionHeader[i].Misc.VirtualSize);
              m_ListCtrl.SetItemText(i,2,szTemp);
   //VirtualAddress
   szTemp.Format(_T("0x%.8X"),stSectionHeader[i].VirtualAddress );
              m_ListCtrl.SetItemText(i,3,szTemp);
   //SizeOfRawData
   szTemp.Format(_T("0x%.8X"),stSectionHeader[i].SizeOfRawData );
   m_ListCtrl.SetItemText(i,4,szTemp);
   //SizeOffset
   szTemp.Format(_T("0x%.8X"),stSectionHeader[i].PointerToRawData );
   m_ListCtrl.SetItemText(i,5,szTemp);
   //Characteristics
   szTemp.Format(_T("0x%.8X"),stSectionHeader[i].Characteristics );
   m_ListCtrl.SetItemText(i,6,szTemp);
   
   
  }
  delete stSectionHeader;
好了,我们计划的两个功能已经写完,下面来看一下运行情况
图2
不早了,我要睡觉了(2003-12-18 2:02)其他的功能下一篇再说吧,下一篇主要是提取Import Table大家先看看教程把
哈哈,对了差点忘了
所有完整代码我都放在压缩文件里了自己看看代码应该对pe有个大概的了解,另外送大家一个我在网上收集的pe结构图。
大家在写的时候别忘了#include
睡了睡了,,,,困死了!
886
                                                                             廉明
                                                                       2003-12-18 2:07

//感谢老罗修正chSectionName数组定义错误引起程序终止的BUG。
//请下载过源代码的兄弟从新下载

程序和源代码下载:http://winroot.shyper.com/bbs/attachment.php?aid=5
 

   

ExeinfoPE:识别与分析加壳技术 ExeinfoPE 是一个非常流行的可执行文件分析工具,它允许用户获取一个 PE 文件的详细信息,包括但不限于文件属性、版本信息、入口点、资源、签名和调试信息。此外,它还提供了一个直观的界面来检查文件是否经过加壳处理,并尝试识别使用的加壳工具。这对于寻找和理解恶意软件以及进行逆向工程尤其有用。加壳技术,又称压缩技术或保护技术,是指对可执行文件进行编码或加密以隐藏其原始代码,防止被轻易逆向工程分析或修改的技术。它是软件保护的一个分支,旨在维护软件开发者知识产权和提高软件的防破解能力。 阅读详情

相关推荐

ExeinfoPe:PE文件深度分析与逆向工程利器

某些高级打包器(如Enigma Protector)或恶意软件生成器会替换默认DOS存根为自定义功能代码,例如:显示虚假错误消息误导分析人员;执行初步解密操作;实现多阶段加载逻辑。可以通过以下Python脚本提取并保存DOS存根:# 读取DOS头获取 e_lfanew# 从0x40读取到 e_lfanew 之前的内容即为DOS存根参数说明file_path: 输入PE文件路径;: 输出存根文件名;0x3C: 固定偏移,指向e_lfanew。

weixin_34779181的博客 1640

【2024最新】PE工具箱【下载安装】零基础到大神【附下载链接】

网络安全行业产业以来,随即新增加了几十个网络安全行业岗位︰网络安全专家、网络安全分析师、安全咨询师、网络安全工程师、安全架构师、安全运维工程师、渗透工程师、信息安全管理员、数据安全工程师、网络安全运营工程师、网络安全应急响应工程师、数据鉴定师、网络安全产品经理、网络安全服务工程师、网络安全培训师、网络安全审计员、威胁情报分析工程师、灾难恢复专业人员、实战攻防专业人员…网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

资深程序员,曾自学JAVA,C#,如今从业于网安行业 1696

PECompact exe/PE压缩工具

PECompact exe/PE压缩工具

【C++】逆向与反汇编实战--PEiD分析复现

文章目录准备文件判断分析函数定位文件判定函数分析OEP检查错误和编译器判断真文件分析函数特征码分析PEID解析流程开发环境伪造 准备 PEiD(PE Identifier)是一款著名的查壳工具,其功能强大,几乎可以侦测出所有的壳,其数量已超过470 种PE 文档 的加壳类型和签名。 整个过程需要测试文件成品:https://www.lanzous.com/b07r7qu0d 首先使用PEiD检测之前做的一个异常捕捉测试程序。源码在下面,编译器为VC++ 6.0,编译方法为 Win32 Release #in

qq_45587822的博客 1354

portable-executable

便携式可执行 解析可移植可执行文件 例子 解析可移植的可执行文件并转储到json。 var fs = require ( 'fs' ) var PE = require ( 'portable-executable' ) var pe = PE . PortableExecutable ( fs . readFileSync ( YOUR_FILE_EXE ) ) console . log ( JSON . stringify ( pe ) ) 可移植可执行文件是一种有趣的复杂格式。 示例输出可能类似于: {"magicNumber":{ "type":"Buffer","data":[77,90]}, "bytesOnLastPageOfFile":144,"pagesInFile":3, "relocations":0,"sizeOfHeaderInParagra

EPLAN二次开发实战指南:从API接口到定制化界面

本文为EPLAN二次开发实战指南,详细介绍了从搭建C#开发环境、理解API接口到创建定制化插件的完整流程。通过实战案例,如批量修改设备属性和设计交互式界面,帮助电气工程师利用EPLAN二次开发实现工作流程自动化与深度定制,从而显著提升设计效率。

weixin_29246195的博客 803

Python深度学习:从入门到实战

亲爱的读者,欢迎您翻开这本书。我们即将探索的,是深度学习的宇宙——一个由数据、算法与算力构筑的奇妙世界。它既是严谨的科学,也是创造的艺术,更是一条通往未来智慧的修行之路。本书将带您从最基础的数学原理出发,亲手搭建神经网络,驾驭Transformer等前沿模型,最终将智慧转化为现实世界的价值。请放下畏惧,保持好奇。这不仅是一次知识的学习,更是一场思维的远行。来,随我一起,开启这趟非凡的旅程吧。

weixin_45747731的博客 296

通过JLink下载实现工控MCU批量烧录实战案例

利用JLink下载工具实现高效稳定的工控MCU批量烧录,提升产线效率。案例详细解析了脚本配置与自动化流程,突出jlink下载的可靠性和可扩展性,适用于大规模嵌入式部署场景。

weixin_30205153的博客 812

VC++中的DUMPBIN 工具用来查看PE(可移植执行体)文件(EXE、dll。。。)

Visual C++ 附有一个DUMPBIN 工具软件,可以观察PE 文件格式。

ylwdi的专栏 899

一、永磁同步电机矢量控制——电机数学模型

本文介绍了永磁同步电机(PMSM)的数学模型构建方法,重点分析了不同坐标系(三相静止、α-β静止、d-q旋转)下的电压方程、磁链表达式及电磁转矩计算方法。通过Clark和Park变换简化非线性耦合系统,推导了表贴式(SPMSM)与内置式(IPMSM)电机的电压方程差异,并给出α-β和d-q坐标系下的转矩公式,强调磁链与电流的正交性对转矩的影响。全文基于理想假设,为后续电机控制算法(如FOC、DTC)提供理论基础。

惊鸿一现 1927

ESXI 与 OPNSense 配合

国庆期间在家里更新曾经购买的设备,将曾经的单系统,加固为防火墙,多系统的网络架构,如下图: 网络架构 在 ESXI 系统中默认存在一个 vSwitch0 交换机,且其不能被修改名称,因此在此通过修改其对应绑定的上行网卡即可,具体如下: 设置 vSwitch0 上行链路 将 vmnic 0 (网口...

weixin_34050389的博客 2313

windows PE Image 文件分析

转自:http://www.mouseos.com/windows/PE_image1.html 上面是 windows PE 可执行文件格式的结构图,分为 4 个部分:DOS 文件头、NT 文件头、Section 表以及 Directory 表格。 windows 的 executable image 文件使用的是这种 PE 格式,而 object 文件使用的是 COFF 文件格式。

ymzhou117的专栏 3777

innovus实战攻略 | 用setUsefulSkewMode解锁时序优化的“隐藏技能”!

就像时序优化的“瑞士军刀”,参数虽多,但掌握了分类逻辑后,用起来其实很简单!如果你有更绝的用法,欢迎在评论区分享,大家一起卷起来!简单来说,它就是时序优化的“乾坤大挪移”。通过调整触发器的时钟到达时间,把关键路径的建立时间“借”给非关键路径,从而实现全局时序收敛。别急,这个命令就是你的“时序救星”!(工具最多只能借1.2ns的裕量,防止“借过头”导致新问题!这个参数能帮你兜底!(对关键路径“下死手”,确保优化到位!(设置上限,给工具套上“紧箍咒”!(直接跳过边界,避免优化反噬!(全局管理,防止“借过头”!

weixin_50820814的博客 1354

滴水逆向三期实践1:PE头字段解析,附PE结构下载

视频资源详见网盘搜索 或 在线的B站滴水逆向三期 其课件也能在优快云或百度搜索到,以下部分为课件内容摘要,部分为自己的理解 最后附上详细注释的自写代码 PE(Portable Executable)文件,是windows上的可移植的可执行文件,常见的 .exe .dll .sys 等都是PE文件。那么PE文件和计算机网络的各种包头一样,都有自己独特的格式。 这里有张PE格式图的部分截图,完整版链接:https://pan.baidu.com/s/1ToG2wc_qOi0BfrLTe...

Rivival_S 的博客 2684

NX二次开发PK获取对象类型

PK_ENTITY_ask_class(),获取对象类型建议用这个函数,比较通用,包含所有对象类型,可以替代UF_MODL_ask_edge_type(),UF_MODL_ask_body_type(),UF_MODL_ask_face_type()等函数。

qq_39541524的博客 827

Qt视频播放器项目(打开文件,视频的播放与停止,进度条与视频进度绑定,调整音量,设置按钮图标,将槽函数与按钮绑定等功能)完整代码地址在末尾

【代码】Qt视频播放器项目。

分享计算机视觉,C++,网络摄像头研发,音视频开发,嵌入式等知识。 755

如何确定程序是否加壳:全面指南

在二进制逆向领域,识别程序是否加壳是关键的第一步。加壳的目的通常是保护程序代码不被轻易反编译或破解,而准确判断程序是否加壳,有助于后续的逆向分析工作。下面就为大家详细介绍几种常见且有效的确定程序是否加壳的方法,并附上相关代码示例辅助理解。

m0_57836225的博客 2694

产品缺陷检测:表面缺陷检测_(1).产品缺陷检测基础理论

确定像素之间的相似性准则,如灰度值的差异。

zhubeibei168的博客 832
上一篇: 最近流行建论坛我也弄了一个
下一篇: 偶像的签名
winroot
博客等级 码龄25年 2粉丝 7原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值