抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Golang内存分配机制

Go语言内置运行时(就是runtime), 抛弃了传统的内存分配方式, 改为自主管理。这样可以自主实现更好的内存使用模式, 比如内存池、预分配等等。这样, 不会每次内存分配都需要系统调用;

什么是内存逃逸

在程序中, 每个函数块都会有自己的内存区域来存自己的局部变量(内存占用少)、返回地址、返回值之类的数据, 这一块内存区域有特定的结构和寻址方式, 寻址起来十分迅速, 开销很少。这一块内存地址称为栈, 栈是线级别的, 大小在创建的时候已经确定, 当变量太大的时候, 会”逃逸”到堆上, 这种现象称为内存逃逸, 简单来说, 局部变量通过堆分配和回收, 就叫内存逃逸。

记录Golang面试八股文

为什么要移动导出表

  1. 导出表由编译器生成, 导出表中存储了该PE文件有哪些导出函数以及函数的地址;
  2. 在程序启动时, 系统会根据导出表做初始工作; 将用到的Dll中的函数地址存储到IAT表中;
  3. 为了保护程序, 可以对.EXE的二进制代码进行加密操作;
    • 如果进行加密, 各种表的信息以及数据是混在一起的, 加密后会导致程序无法正常执行;
    • 因此需要新增一个节, 并将PE中的表移动到新节中, 然后将代码和数据进行加密;

内存直接加载运行

  • 病毒木马具有模拟PE加载器的功能, 它们可以把DLL或者exe等PE文件从内存中直接加载到病毒木马的内存中去执行, 不需要通过LoadLibrary等现成的API函数去操作;
  • 假如程序需要动态调用DLL文件, 内存加载运行技术可以把DLL作为资源插入到自己的程序中, 此时可直接在内存中加载运行即可;
  • 内存加载技术的核心就在于模拟PE加载器PE文件, 也就是对导入表、导出表、重定位表的操作过程;

IAT Hook

  • IMAGE_IMPORT_DESCRIPTOR中两个IMAGE_THUNK_DATA结构体,第一个位导入名称表(INT),第二个位导入地址表(IAT)。两个结构在磁盘文件中时是没有差别的,但是当PE文件被装载到内存中后,FirstThunk字段指向的IMAGE_THUNK_DATA的值会被Windows进行填充。该值为一个RVA,该RVA加上映像基址后,虚拟地址就保存了真正的导入函数的入口地址
  • IAT Hook步骤
    1. 获取欲Hook的函数地址
    2. 找到该函数的所保存的IAT地址
    3. 把IAT中该函数的地址修改为Hook函数的地址

Inline Hook(内联钩子注入)流程

  1. 构造跳转指令[JMP后的偏移量 = 目标地址 - 原地址 - jcc的指令长度]
  2. 在内存中找到欲HOOK函数地址,并保存欲HOOK位置处的前5个字节
  3. 将构造的跳转指令写入需HOOK的位置处
  4. 当被HOOK位置被执行时会转到自己的流程执行
  5. 如果要执行原来的流程,取消HOOK,还原被修改的字节
  6. 执行原来的流程
  7. 继续HOOK住原来的位置

  • 远程线程注入是指一个进程在另一个进程中创建线程的技术。是一种病毒木马所青睐的注入技术。

基础知识

  • 基地址(ImageBase): 当PE文件通过Windows加载器载入内存后,内存中的版本称为模块,映射文件的起始地址称为模块句柄,可通过句柄访问内存中其他数据结构,这个内存起始地址称为基地址。
  • 虚拟地址(VA): 在Windows系统中,PE文件被系统加载到内存后,每个程序都有自己的虚拟空间,这个虚拟空间的内存地址称为虚拟地址。
  • 相对虚拟地址(RVA): 可执行文件中,有许多地方需要指定内存中的地址。例如,应用全局变量时需要指定它的地址。为了避免在PE文件中出现绝对内存地址引入了相对虚拟地址,它就是在内存中相对于PE文件载入地址的偏移量。
  • 文件偏移地址(FOA): 当PE文件存储在磁盘中时,某个数据的位置相对于文件头的偏移量称为文件偏移地址(FOA)。文件偏移地址从PE文件中的第一个字节开始计数,起始值为0。

它们之间的关系:虚拟地址(VA) = 基地址(ImageBase) + 相对虚拟地址(RVA)

Windows PE

  • 可执行文件(Executable file)指的是可以由操作系统进行加载执行的文件
  • 可执行文件的格式:
    • Windows 平台
      PE(Portable Executable)文件结构
    • Linux 平台
      ELF(Executable and Linking Format)文件结构