`
cfree
  • 浏览: 17897 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
社区版块
存档分类
最新评论

压缩与脱壳-PE文件格式 七

阅读更多
Export Table(引出表)


  上一课我们已经学习了动态联接中关于引入表那部分知识,现在继续另外一部分,那就是引出表。

理论 :
  当PE装载器执行一个程序,它将相关DLLs都装入该进程的地址空间。然后根据主程序的引入函数信息,查找相关DLLs中的真实函数地址来修正主程序。PE装载器搜寻的是DLLs中的引出函数。

  DLL/EXE要引出一个函数给其他DLL/EXE使用,有两种实现方法: 通过函数名引出或者仅仅通过序数引出。比如某个DLL要引出名为"GetSysConfig"的函数,如果它以函数名引出,那么其他DLLs/EXEs若要调用这个函数,必须通过函数名,就是GetSysConfig。另外一个办法就是通过序数引出。什么是序数呢? 序数是唯一指定DLL中某个函数的16位数字,在所指向的DLL里是独一无二的。例如在上例中,DLL可以选择通过序数引出,假设是16,那么其他DLLs/EXEs若要调用这个函数必须以该值作为GetProcAddress调用参数。这就是所谓的仅仅靠序数引出。

我们不提倡仅仅通过序数引出函数这种方法,这会带来DLL维护上的问题。一旦DLL升级/修改,程序员无法改变函数的序数,否则调用该DLL的其他程序都将无法工作。

  现在我们开始学习引出结构。象引出表一样,可以通过数据目录找到引出表的位置。这儿,引出表是数据目录的第一个成员,又可称为IMAGE_EXPORT_DIRECTORY。该结构中共有11 个成员,常用的列于下表。



上面也许无法让您完全理解引出表,下面的简述将助您一臂之力。

  引出表的设计是为了方便PE装载器工作。首先,模块必须保存所有引出函数的地址以供PE装载器查询。模块将这些信息保存在 AddressOfFunctions 域指向的数组中,而数组元素数目存放在 NumberOfFunctions 域中。 因此,如果模块引出40个函数,则 AddressOfFunctions 指向的数组必定有40个元素,而 NumberOfFunctions 值为40。现在如果有一些函数是通过名字引出的,那么模块必定也在文件中保留了这些信息。这些 名字的RVAs存放在一数组中以供PE装载器查询。该数组由 AddressOfNames 指向, NumberOfNames 包含名字数目。考虑一下PE装载器的工作机制,它知道函数名,并想以此获取这些函数的地址。至今为止,模块已有两个模块: 名字数组和地址数组,但两者之间还没有联系的纽带。因此我们还需要一些联系函数名及其地址的东东。PE参考指出使用到地址数组的索引作为联接,因此PE装载器在名字数组中找到匹配名字的同时,它也获取了 指向地址表中对应元素的索引 。 而这些索引保存在由 AddressOfNameOrdinals 域指向的另一个数组(最后一个)中。由于该数组是起了联系名字和地址的作用,所以其元素数目必定和名字数组相同,比如,每个名字有且仅有一个相关地址,反过来则不一定: 每个地址可以有好几个名字来对应。因此我们给同一个地址取"别名"。为了起到连接作用,名字数组和索引数组必须并行地成对使用,譬如,索引数组的第一个元素必定含有第一个名字的索引,以此类推。




下面举一两个例子说明问题。如果我们有了引出函数名并想以此获取地址,可以这么做:

定位到PE header。 从数据目录读取引出表的虚拟地址。 定位引出表获取名字数目( NumberOfNames )。 并行遍历 AddressOfNames 和 AddressOfNameOrdinals 指向的数组匹配名字。如果在 AddressOfNames 指向的数组中找到匹配名字,从 AddressOfNameOrdinals 指向的数组中提取索引值。例如,若发现匹配名字的RVA存放在 AddressOfNames 数组的第77个元素,那就提取 AddressOfNameOrdinals 数组的第77个元素作为索引值。如果遍历完 NumberOfNames 个元素,说明当前模块没有所要的名字。 从 AddressOfNameOrdinals 数组提取的数值作为 AddressOfFunctions 数组的索引。也就是说,如果值是5,就必须读取 AddressOfFunctions 数组的第5个元素,此值就是所要函数的RVA。
现在我们在把注意力转向 IMAGE_EXPORT_DIRECTORY 结构的 nBase 成员。您已经知道 AddressOfFunctions 数组包含了模块中所有引出符号的地址。当PE装载器索引该数组查询函数地址时,让我们设想这样一种情况,如果程序员在.def文件中设定起始序数号为200,这意味着 AddressOfFunctions 数组至少有200个元素,甚至这前面200个元素并没使用,但它们必须存在,因为PE装载器这样才能索引到正确的地址。这种方法很不好,所以又设计了 nBase 域解决这个问题。如果程序员指定起始序数号为200, nBase 值也就是200。当PE装载器读取 nBase 域时,它知道开始200个元素并不存在,这样减掉一个 nBase 值后就可以正确地索引 AddressOfFunctions 数组了。有了 nBase ,就节约了200个空元素。

  注意 nBase 并不影响 AddressOfNameOrdinals 数组的值。尽管取名" AddressOfNameOrdinals ",该数组实际包含的是指向 AddressOfFunctions 数组的索引,而不是什么序数啦。

  讨论完nBase的作用,我们继续下一个例子。

  假设我们只有函数的序数,那么怎样获取函数地址呢,可以这么做:

定位到PE header。 从数据目录读取引出表的虚拟地址。 定位引出表获取 nBase 值。 减掉nBase值得到指向 AddressOfFunctions 数组的索引。 将该值与 NumberOfFunctions 作比较,大于等于后者则序数无效。 通过上面的索引就可以获取 AddressOfFunctions 数组中的RVA了。
  可以看出,从序数获取函数地址比函数名快捷容易。不需要遍历 AddressOfNames 和 AddressOfNameOrdinals 这两个数组。然而,综合性能必须与模块维护的简易程度作一平衡。

  总之,如果想通过名字获取函数地址,需要遍历 AddressOfNames 和 AddressOfNameOrdinals 这两个数组。如果使用函数序数,减掉nBase值后就可直接索引 AddressOfFunctions 数组。

  如果一函数通过名字引出,那在 GetProcAddress 中可以使用名字或序数。但函数仅由序数引出情况又怎样呢? 现在就来看看。

  "一个函数仅由序数引出"意味着函数在 AddressOfNames 和 AddressOfNameOrdinals 数组中不存在相关项。记住两个域, NumberOfFunctions 和 NumberOfNames 。这两个域可以清楚地显示有时某些函数没有名字的。函数数目至少等同于名字数目,没有名字的函数通过序数引出。比如,如果存在70个函数但 AddressOfNames 数组中只有40项,这就意味着模块中有30个函数是仅通过序数引出的。现在我们怎样找出那些仅通过序数引出的函数呢?这不容易,必须通过排除法,比如, AddressOfFunctions 的数组项在 AddressOfNameOrdinals 数组中不存在相关指向,这就说明该函数RVA只通过序数引出。

示例 :
  本例类似上课的范例。然而,在显示 IMAGE_EXPORT_DIRECTORY 结构一些成员信息的同时,也列出了引出函数的RVAs,序数和名字。注意本例没有列出仅由序数引出的函数

.386
.model flat,stdcall
option casemap:none
include masm32includewindows.inc
include masm32includekernel32.inc
include masm32includecomdlg32.inc
include masm32includeuser32.inc
includelib masm32libuser32.lib
includelib masm32libkernel32.lib
includelib masm32libcomdlg32.lib
IDD_MAINDLG equ 101
IDC_EDIT equ 1000
IDM_OPEN equ 40001
IDM_EXIT equ 40003
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
ShowExportFunctions proto :DWORD
ShowTheFunctions proto :DWORD,:DWORD
AppendText proto :DWORD,:DWORD
SEH struct
PrevLink dd ?
CurrentHandler dd ?
SafeOffset dd ?
PrevEsp dd ?
PrevEbp dd ?
SEH ends
.data
AppName db "PE tutorial no.7",0
ofn OPENFILENAME <>
FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0
db "All Files",0,"*.*",0,0
FileOpenError db "Cannot open the file for reading",0
FileOpenMappingError db "Cannot open the file for memory mapping",0
FileMappingError db "Cannot map the file into memory",0
NotValidPE db "This file is not a valid PE",0
NoExportTable db "No export information in this file",0
CRLF db 0Dh,0Ah,0
ExportTable db 0Dh,0Ah,"======[ IMAGE_EXPORT_DIRECTORY ]======",0Dh,0Ah
db "Name of the module: %s",0Dh,0Ah
db "nBase: %lu",0Dh,0Ah
db "NumberOfFunctions: %lu",0Dh,0Ah
db "NumberOfNames: %lu",0Dh,0Ah
db "AddressOfFunctions: %lX",0Dh,0Ah
db "AddressOfNames: %lX",0Dh,0Ah
db "AddressOfNameOrdinals: %lX",0Dh,0Ah,0
Header db "RVA Ord. Name",0Dh,0Ah
db "----------------------------------------------",0
template db "%lX %u %s",0
.data?
buffer db 512 dup(?)
hFile dd ?
hMapping dd ?
pMapping dd ?
ValidPE dd ?
.code
start:
invoke GetModuleHandle,NULL
invoke DialogBoxParam, eax, IDD_MAINDLG,NULL,addr DlgProc, 0
invoke ExitProcess, 0
DlgProc proc hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
.if uMsg==WM_INITDIALOG
invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETLIMITTEXT,0,0
.elseif uMsg==WM_CLOSE
invoke EndDialog,hDlg,0
.elseif uMsg==WM_COMMAND
.if lParam==0
mov eax,wParam
.if ax==IDM_OPEN
invoke ShowExportFunctions,hDlg
.else ; IDM_EXIT
invoke SendMessage,hDlg,WM_CLOSE,0,0
.endif
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
SEHHandler proc uses edx pExcept:DWORD,
pFrame:DWORD, pContext:DWORD, pDispatch:DWORD
mov edx,pFrame
assume edx:ptr SEH
mov eax,pContext
assume eax:ptr CONTEXT
push [edx].SafeOffset
pop [eax].regEip
push [edx].PrevEsp
pop [eax].regEsp
push [edx].PrevEbp
pop [eax].regEbp
mov ValidPE, FALSE
mov eax,ExceptionContinueExecution
ret
SEHHandler endp
ShowExportFunctions proc uses edi hDlg:DWORD
LOCAL seh:SEH
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or
OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile, addr buffer,
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
.if eax!=INVALID_HANDLE_VALUE
mov hFile, eax
invoke CreateFileMapping, hFile, NULL, PAGE_READONLY,0,0,0
.if eax!=NULL
mov hMapping, eax
invoke MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0
.if eax!=NULL
mov pMapping,eax
assume fs:nothing
push fs:[0]
pop seh.PrevLink
mov seh.CurrentHandler,offset SEHHandler
mov seh.SafeOffset,offset FinalExit
lea eax,seh
mov fs:[0], eax
mov seh.PrevEsp,esp
mov seh.PrevEbp,ebp
mov edi, pMapping
assume edi:ptr IMAGE_DOS_HEADER
.if [edi].e_magic==IMAGE_DOS_SIGNATURE
add edi, [edi].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
.if [edi].Signature==IMAGE_NT_SIGNATURE
mov ValidPE, TRUE
.else
mov ValidPE, FALSE
.endif
.else
mov ValidPE,FALSE
.endif
FinalExit:
push seh.PrevLink
pop fs:[0]
.if ValidPE==TRUE
invoke ShowTheFunctions, hDlg, edi
.else
invoke MessageBox,0, addr NotValidPE, addr AppName, MB_OK+MB_ICONERROR
.endif
invoke UnmapViewOfFile, pMapping
.else
invoke MessageBox, 0, addr FileMappingError, addr AppName, MB_OK+MB_ICONERROR
.endif
invoke CloseHandle,hMapping
.else
invoke MessageBox, 0, addr FileOpenMappingError, addr AppName, MB_OK+MB_ICONERROR
.endif
invoke CloseHandle, hFile
.else
invoke MessageBox, 0, addr FileOpenError, addr AppName, MB_OK+MB_ICONERROR
.endif
.endif
ret
ShowExportFunctions endp
AppendText proc hDlg:DWORD,pText:DWORD
invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_REPLACESEL,0,pText
invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_REPLACESEL,0,addr CRLF
invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETSEL,-1,0
ret
AppendText endp
RVAToFileMap PROC uses edi esi edx ecx pFileMap:DWORD,RVA:DWORD
mov esi,pFileMap
assume esi:ptr IMAGE_DOS_HEADER
add esi,[esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
mov edi,RVA ; edi == RVA
mov edx,esi
add edx,sizeof IMAGE_NT_HEADERS
mov cx,[esi].FileHeader.NumberOfSections
movzx ecx,cx
assume edx:ptr IMAGE_SECTION_HEADER
.while ecx>0
.if edi>=[edx].VirtualAddress
mov eax,[edx].VirtualAddress
add eax,[edx].SizeOfRawData
.if edi <eax
mov eax,[edx].VirtualAddress
sub edi,eax
mov eax,[edx].PointerToRawData
add eax,edi
add eax,pFileMap
ret
.endif
.endif
add edx,sizeof IMAGE_SECTION_HEADER
dec ecx
.endw
assume edx:nothing
assume esi:nothing
mov eax,edi
ret
RVAToFileMap endp
ShowTheFunctions proc uses esi ecx ebx hDlg:DWORD, pNTHdr:DWORD
LOCAL temp[512]:BYTE
LOCAL NumberOfNames:DWORD
LOCAL Base:DWORD
mov edi,pNTHdr
assume edi:ptr IMAGE_NT_HEADERS
mov edi, [edi].OptionalHeader.DataDirectory.VirtualAddress
.if edi==0
invoke MessageBox,0, addr NoExportTable,addr AppName,MB_OK+MB_ICONERROR
ret
.endif
invoke SetDlgItemText,hDlg,IDC_EDIT,0
invoke AppendText,hDlg,addr buffer
invoke RVAToFileMap,pMapping,edi
mov edi,eax
assume edi:ptr IMAGE_EXPORT_DIRECTORY
mov eax,[edi].NumberOfFunctions
invoke RVAToFileMap, pMapping,[edi].nName
invoke wsprintf, addr temp,addr ExportTable,
eax, [edi].nBase, [edi].NumberOfFunctions, [edi].NumberOfNames, [edi].AddressOfFunctions, [edi].AddressOfNames, [edi].AddressOfNameOrdinals
invoke AppendText,hDlg,addr temp
invoke AppendText,hDlg,addr Header
push [edi].NumberOfNames
pop NumberOfNames
push [edi].nBase
pop Base
invoke RVAToFileMap,pMapping,[edi].AddressOfNames
mov esi,eax
invoke RVAToFileMap,pMapping,[edi].AddressOfNameOrdinals
mov ebx,eax
invoke RVAToFileMap,pMapping,[edi].AddressOfFunctions
mov edi,eax
.while NumberOfNames>0
invoke RVAToFileMap,pMapping,dword ptr [esi]
mov dx,[ebx]
movzx edx,dx
mov ecx,edx
shl edx,2
add edx,edi
add ecx,Base
invoke wsprintf, addr temp,addr template,dword ptr [edx],ecx,eax
invoke AppendText,hDlg,addr temp
dec NumberOfNames
add esi,4
add ebx,2
.endw
ret
ShowTheFunctions endp
end start



分析 :
mov edi,pNTHdr
assume edi:ptr IMAGE_NT_HEADERS
mov edi, [edi].OptionalHeader.DataDirectory.VirtualAddress
.if edi==0
invoke MessageBox,0, addr NoExportTable,addr AppName,MB_OK+MB_ICONERROR
ret
.endif

程序检验PE有效性后,定位到数据目录获取引出表的虚拟地址。若该虚拟地址为0,则文件不含引出符号。

mov eax,[edi].NumberOfFunctions
invoke RVAToFileMap, pMapping,[edi].nName
invoke wsprintf, addr temp,addr ExportTable,
eax, [edi].nBase, [edi].NumberOfFunctions, [edi].NumberOfNames, [edi].AddressOfFunctions, [edi].AddressOfNames, [edi].AddressOfNameOrdinals
invoke AppendText,hDlg,addr temp


在编辑控件中显示 IMAGE_EXPORT_DIRECTORY 结构的一些重要信息。
push [edi].NumberOfNames
pop NumberOfNames
push [edi].nBase
pop Base


由于我们要枚举所有函数名,就要知道引出表里的名字数目。 nBase 在将 AddressOfFunctions 数组索引转换成序数时派到用场。
invoke RVAToFileMap,pMapping,[edi].AddressOfNames
mov esi,eax
invoke RVAToFileMap,pMapping,[edi].AddressOfNameOrdinals
mov ebx,eax
invoke RVAToFileMap,pMapping,[edi].AddressOfFunctions
mov edi,eax

将三个数组的地址相应存放到esi,,ebx,edi中。准备开始访问。

  .while NumberOfNames>0

  直到所有名字都被处理完毕。

  invoke RVAToFileMap,pMapping,dword ptr [esi]

  由于esi指向包含名字字符串RVAs的数组,所以[esi]含有当前名字的RVA,需要将它转换成虚拟地址,后面wsprintf要用的。

mov dx,[ebx]
movzx edx,dx
mov ecx,edx
add ecx,Base

 ebx指向序数数组,值是字类型的。因此我们先要将其转换成双字,此时edx和ecx含有指向 AddressOfFunctions 数组的索引。我们用edx作为索引值,而将ecx加上nBase得到函数的序数值。=
shl edx,2
add edx,edi
索引乘以4 ( AddressOfFunctions 数组中每个元素都是4字节大小) 然后加上数组首地址,这样edx指向的就是所要函数的RVA了。

invoke wsprintf, addr temp,addr template,dword ptr [edx],ecx,eax
invoke AppendText,hDlg,addr temp
  在编辑控件中显示函数的RVA, 序数, 和名字。

dec NumberOfNames
add esi,4
add ebx,2
.endw
  修正计数器, AddressOfNames 和 AddressOfNameOrdinals 两数组的当前指针,继续遍历直到所有名字全都处理完毕。
  • 大小: 77.6 KB
  • 大小: 26.1 KB
分享到:
评论

相关推荐

    PE文件的UPX脱壳算法的实现

    都会使计算机产生安全隐患或者使软件的核心技术被窃取,所以保护PE文件不被修改是一件很重要的工作,当前通常采用加壳的方法对PE文件进行保护,这其中UPX是具有代表性的压缩类外壳。 本文首先对PE文件格式进行了全面...

    .Net 脱壳 反混淆神器De4dot-3.1.41592最新版

    有些模糊处理一个Win32 PE等包装.NET程序集里面的.NET反编译器无法读取该文件。 移除大多数/所有的垃圾类添加混淆。 修复了一些的peverify错误。许多混淆器是马车和创建无法验证的代码错误。 还原类型的方法的参数和...

    红黑全能自动脱壳机——全能脱壳机

    这个工具的工作原理,它的壳特征和编译器特征保存在HackFans.txt里面,能识别出来的壳,基本上都有对应的脱壳函数,用壳特征脱壳,可以脱壳,对于一些不好特殊的壳你可以用OEP侦测来脱壳,这要依赖编译器特征,你也可以自己...

    脱壳AspackDie

    - 询问用户是否继续解压缩不能解压缩的文件 (不知道是谁提的建议) 1.3d: (2002.3.26) --------------------- - 支持另外的一个未知的 Aspack 版本 (感谢: Proggi Killa) 1.3c: (2002.3.21) --------------------- ...

    脱壳入门初级教学(CHM格式)

    第一课 PE格式 第二课 SEH技术 第三课 认识壳 第四课 常见压缩壳与加密壳 第五课 文件类型分析 第六课 寻找OEP 第七课 Dump内存映像 第八课 重建输入表 第九课 手动确定IAT的地址与大小 第十课 DLL文件脱壳 第十一课...

    软件脱壳破解工具

    AspackDie——AsPack的脱壳利器, 这是一个小小的PE 文件解压缩器 (EXE, DLL, ...) 她可以解压缩自Aspack 2000 以后的任何Aspack 版本. 包括: - Aspack 2000 - Aspack 2001 - Aspack 2.1 - Aspack 2.11 - Aspack 2.11...

    ASPack脱壳

    这是一个小小的 PE 文件解压缩器 (EXE, DLL, ...) 她可以解压缩 自 Aspack 2000 以后的任何 Aspack 版本. 包括: - Aspack 2000 - Aspack 2001 - Aspack 2.1 - Aspack 2.11 - Aspack 2.11c/d - Aspack 2.12 - Aspack...

    rordbg辅助脱壳工具

    答:点击“打开被分析文件”,出现Windows标准的文件打开对话框,选择欲分析的文件(必须是PE格式的EXE文件), 这时,被调试程序已经加载,可以先设置断点等调试条件,如果希望研究壳的技术,可以点选“遇到异常...

    软件加密技术内幕 chm

    第1章 PE文件格式深入研究 1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions) 1.2 PE文件结构 ...

    全能脱壳机

    这个工具的工作原理,它的壳特征和编译器特征保存在HackFans.txt里面,能识别出来的壳,基本上都有对应的脱壳函数,用壳特征脱壳,可以脱壳,对于一些不好特殊的壳你可以用OEP侦测来脱壳,这要依赖编译器特征,你也可以自己...

    多种脱壳软件

    现在为了适应脱壳的需要,发现原来的代码对非标准格式的PE文件的处理有些小问题, 所以代码基本都重写过了,但是基本处理步骤还是一致的,外表上看不出来 3.cooldebugger plugin(调试插件) 完全自主开发的插件,说是调试...

    软件加密技术内幕

    1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions) 1.2 PE文件结构 1.2.1 The MS-DOS头部 1.2.2 IMAGE...

    加密解密.技术内幕.chm

    第1章 PE文件格式深入研究1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions)1.2 PE文件结构 1.2.1 The MS-...

    强大UPX加壳压缩工具(Free UPX) v1.7汉化版.rar

    UPX 加壳压缩工具绿色版本,无需安装,Free UPX1.4,在编程开发过程中我们可以利用其对EXE, DLL, OCX, BPL, CPL 等格式文件加壳,使用方便快速、而且是免费的! UPX(the Ultimate Packer for eXecutables)是一个...

    软件破解入门教程.txt

    PE文件格式 认识脱壳 自动脱壳 手动脱壳 脱壳高级篇 第9章 注册机和补丁制作 概念介绍 补丁制作 注册机制作工具 rufeng教程 第一章 如何成为一个Cracker 第二章 破解软件的基础 第三章 破解windows 95...

    Windows应用程序捆绑核心编程光盘代码

    2.2 PE文件格式概述 28 2.2.1 PE文件结构布局 28 2.2.2 PE文件内存映射 30 2.2.3 Big-endian和Little-endian 31 2.2.4 3种不同的地址 31 2.3 PE文件结构 32 2.3.1 MS-DOS头部 32 2.3.2 IMAGE_NT_HEADER头部 ...

    完全掌握加密解密实战超级手册.z01

    462.1.3 PE文件格式的头结构 462.1.4 设置Optional Header可执行信息 492.1.5 Section Table结构数组 512.1.6 Import Table输入表 522.1.7 Export Table输出表 532.1.8 重定位表 542.2 简述代码分析实战 552.2.1 ...

    易语言程序免安装版下载

    注意:静态编译后常量数据位于PE文件的.rdata段中,只可读不可写,编程时请避免修改它们。譬如以下的代码,静态编译后就可能会出现问题: a = " " GetWindowTextA(hWnd, a, 20) 正确的代码为: a = 取空白文本 ...

Global site tag (gtag.js) - Google Analytics