首页
社区
课程
招聘
《逆向工程核心原理》9-14章总结
2022-10-25 17:56 5713

《逆向工程核心原理》9-14章总结

2022-10-25 17:56
5713

Process Explorer是一款优秀的进程管理工具,可以查看进程和DLL等,但火绒剑似乎功能与其相差无几,先代替其用着吧。


 

cdecl和stdcall两种函数调用约定的区别在于由谁来负责处理栈。

  • cdecl方式的好处在于可以向被调用的函数传递长度可变的参数,由调用者main()函数直接清理栈。
  • stdcall方式常用于Win32 API,由被调用者函数内部清理栈,可以获得更好的兼容性。
  • 另外fastcall与stdcall基本类似,但通常会使用寄存器传递部分参数(前2个)。

 

x86系统中使用EAX寄存器传递函数的返回值。


 

PE头内部信息大多以RVA(相对虚拟地址)形式存在,原因在于DLL的重定位。
PE头由DOS头、DOS存根(可选)、NT头、节区头组成。

DOS头(IMAGE_DOS_HEADER)

  • 为了兼容DOS系统
  • e_magic表示DOS签名(4D5A->ascci"MZ")
  • e_lfanew(000000E0)指示NT头(IMAGE_NT_HEADER)的偏移

DOS存根(stub)

  • 是个可选项,大小不固定,代码与数据混合而成
  • Windows 32位环境下不执行

NT头(IMAGE_NT_HEADERS)

  • 第一个成员为Signature(50450000h->"PE"00)
  • 还有文件头和可选头

NT头:文件头(IMAGE_FILE_HEADER)

  • Machine指示CPU的machine码(1对1)
  • NumberOfSections用来指出文件中存在的节区数量(一定要大于0)
  • SizeOfOptionalHeader用来指出IMAGE_OPTIONAL_HEADER32结构体的长度
  • Characteristics用于标识文件属性(0002h代表EXE,2000h代表是DLL)

NT头:可选头(IMAGE_OPTIONAL_HEADER32)

  • Magic值为10B时为IMAGE_OPTIONAL_HEADER32结构体,Magic值为20B时为IMAGE_OPTIONAL_HEADER64结构体
  • AddressOfEntryPoint持有EP的RVA值,指出程序最先执行的代码起始地址
  • ImageBase指出文件的优先装入地址,开始执行时EIP = ImageBase + AddressOfEntryPoint
  • SectionAlignment指定了节区在内存中的最小单位,FileAlignment指定了节区在磁盘文件中的最小单位
  • SizeOfImage指定了PE Image在虚拟内存中所占空间的大小
  • SizeOfHeaders用来指出整个PE头的大小
  • Subsystem的值用来区分系统驱动文件(.sys)与普通的可执行文件(.exe,*.dll)
  • NumberOfRvaAndSizes用来指定DataDirectory数组的个数
  • DataDirectory是由IMAGE_DATA_DIRECTORY结构体组成的数组,数组的每项都有被定义的值

节区头(IMAGE_SECTION_HEADER)

  • VirtualSize指定了内存中节区所占大小
  • VirtualAddress指定了内存中节区起始地址(RVA)
  • SizeOfRawData指定了磁盘文件中节区所占大小
  • PointerToRawData指定了磁盘文件中节区起始位置
  • Characteristic指定了节区属性
  • Name成员不像C语言中的字符串以NULL结束,也没有“必须使用ASCII值”的限制,节区的Name仅供参考,数据节区的Name也可以是.code

 

“映像”(Image):磁盘文件中的PE与内存中的PE具有不同的形态,将装载到内存中的形态称为“映像”以示区别。


 

RVA to RAW:

1
2
RAW - PointerToRawData = RVA - VirtualAddress
                   RAW = RVA - VirtualAddress + PointerToRawData

 

DLL的优势:

  • 不需要把库包含到程序中,只要单独组成DLL文件,需要时调用即可
  • 内存映射技术使加载后的DLL代码、资源在多个进程中实现共享(内存映射?知识盲区了
  • 更新库时只要替换相关的DLL文件即可,简单易行

IMAGE_IMPORT_DESCRIPTOR

  • 导入多少个库就存在多少个IMAGE_IMPORT_DESCRIPTOR结构体,这些结构体形成了数组,且结构体数组最后以NULL结构体结束。
  • OriginalFirstThunk指定了INT的地址(RVA)
  • Name指出了库名称字符串的地址(RVA),是一个字符串指针,指向导入函数所属的库文件名称
  • FirstThunk指定了IAT的地址(RVA)
  • IAT与INT是长整型(long)数组,以NULL结束,两者大小应相同
  • INT中各元素的值为IMAGE_IMPORT_BY_NAME结构体指针
  • IMAGE_OPTIONAL_HEADER32.DataDirectory[1].VirtualAddress的值即是IMAGE_IMPORT_DESCRIPTOR结构体数组的起始地址

IAT输入顺序:

  1. 读取IID(IMAGE_IMPORT_DESCRIPTOR)的Name成员,获取库名称字符串(“kernel32.dll”)
  2. 装载相应库
    ->LoadLibrary("kernel32.dll")
  3. 读取IID的OriginalFirstThunk成员,获取INT地址
  4. 逐一读取INT中数组的值,获取相应IMAGE_IMPORT_BY_NAME地址
  5. 使用IMAGE_IMPORT_BY_NAME的Hint(ordinal)或Name项,获取相应函数的起始地址
    ->GetProcAddress("GetCurrentThreadld")
  6. 读取IID的FirstThunk(IAT)成员,获取IAT地址
  7. 将上面获得的函数地址输入相应的IAT数组值
  8. 重复以上步骤4-7,直到INT结束(遇到NULL时)

IMAGE_EXPORT_DIRECTORY

  • IMAGE_OPTINAL_HEADER32.DataDirectory[0].VirtualAddress的值即是IMAGE_EXPORT_DIRECTORY结构体数组的起始地址。
  • NumberOfFunctions指定了实际Export函数的个数
  • NumberOfNames指定了Export函数中具名的函数个数
  • AddressOfFunctions指示了Export函数地址数组
  • AddressOfNames指示了函数名称地址数组
  • AddressOfNameOrdinals指示了Ordinal地址数组
  • 从库中获得函数地址的API为GetProcAddress()函数

GetProcAddress()操作原理

  1. 利用AddressOfNames成员转到“函数名称数组”
  2. “函数名称数组”中存储着字符串地址。通过比较(strcmp)字符串,查找指定的函数名称(此时数组的索引称为name_index)
  3. 利用AddressOfNameOrdinals成员,转到ordinal数组
  4. 在ordinal数组中通过name_index查找相应ordinal值
  5. 利用AddressOfFunctions成员转到“函数地址数组”(EAT)
  6. 在“函数地址数组”中将刚刚求得的ordinal用作数组索引,获得指定函数的起始地址

对于没有函数名称的导出函数,可以通过Ordinal查找到它们的地址。从Ordinal值中减去IMAGE_EXPORT_DIRECTORY.Base成员后得到一个值,使用该值作为“函数地址数组”的索引,即可查找到相应函数地址。


 

运行时压缩器是针对可执行文件而言的,可执行文件内部含有解压缩代码,文件在运行瞬间于内存中解压缩后执行。


 

notepad.exe与notepad_upx.exe的比较项目:

  1. PE头的大小一样
  2. 节区名称改变(“.text”->“UPX0”,“.data”->“UPX1”)
  3. 第一个节区的RawDataSize=0(文件中大小为0)
  4. EP位于第二个节区
  5. 资源节区(.rsrc)大小几乎无变化

notepad_upx.exe其第一个节区的的VirtualSize值被设置为10000(而SizeOfRawData值为0)。这就是说,经过UPX压缩后的PE文件在运行瞬间将文件中的压缩的代码解压到内存中的第一个节区。更详细一些,解压缩代码与压缩的源代码都在第二个节区,文件运行时首先执行解压缩代码,把处于压缩状态的源代码解压到第一个节区,解压结束后即运行源文件的EP代码。


 

至此把9-14章重新回顾了一遍,特别是PE文件结构这一块在过了一遍之后见解加深不少,之前还有点迷糊,现在感觉像是豁然开朗一般,有点爽。


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

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回