ZBLOG

golang 代码实现ImageImportDescriptor结构中Name指针对应的字符串

好的,以下是一个完整的Golang代码实现ImageImportDescriptor结构中Name指针对应的字符串:

”`go package main

import (

  1. "bytes"
  2. "encoding/binary"
  3. "fmt"
  4. "io/ioutil"
  5. "reflect"
  6. "unsafe"

)

type IMAGE_DOS_HEADER struct {

  1. E_magic uint16
  2. E_cblp uint16
  3. E_cp uint16
  4. E_crlc uint16
  5. E_cparhdr uint16
  6. E_minalloc uint16
  7. E_maxalloc uint16
  8. E_ss uint16
  9. E_sp uint16
  10. E_csum uint16
  11. E_ip uint16
  12. E_cs uint16
  13. E_lfarlc uint16
  14. E_ovno uint16

}

type IMAGE_FILE_HEADER struct {

  1. Machine uint16 // CPU类型:x86、x64等等。
  2. NumberOfSections uint16 // 节数量。
  3. TimeDateStamp uint32 // 文件创建时间戳。
  4. PointerToSymbolTable uint32 // 符号表偏移量,一般为0。
  5. NumberOfSymbols uint32 // 符号数量,一般为0。
  6. SizeOfOptionalHeader uint16 // 可选头大小。
  7. Characteristics uint16 // 文件属性标志,如是否可执行等等。

}

type IMAGE_DATA_DIRECTORY struct {

  1. VirtualAddress DWORD // 虚拟地址RVA(相对虚拟地址)。
  2. Size DWORD // 大小,单位字节。

}

type IMAGE_OPTIONAL_HEADER32 struct {

  1. Magic WORD // 魔数:用于区分PE文件和OBJ文件。PE文件为0x10B或者0x107;OBJ文件为0xFFFF.
  2. MajorLinkerVersion BYTE // 连接器主版本号。
  3. MinorLinkerVersion BYTE // 连接器次版本号。
  4. SizeOfCode DWORD // 代码段大小,单位字节。必须对齐到文件中的FileAlignment属性指定的值。
  5. SizeOfInitializedData DWORD // 初始化数据段大小,单位字节。必须对齐到文件中的FileAlignment属性指定的值。
  6. SizeOfUninitializedData DWORD // 未初始化数据段大小,单位字节。必须对齐到文件中的FileAlignment属性指定的值。
  7. AddressOfEntryPoint DWORD // 程序入口点地址RVA(相对虚拟地址)。
  8. BaseOfCode DWORD // 代码段起始地址RVA(相对虚拟地址)。
  9. BaseOfData DWORD // 数据段起始地址RVA(相对虚拟地址),仅针对于32位PE格式有效。
  10. ImageBase DWORD // 映像装载基址,程序在运行时被映射到内存的起始位置。一般为0x400000
  11. SectionAlignment DWORD // 内存页边界数,要求是2^n,最小值是512,默认是4096(4KB)。通常与文件中区块偏移量划分有关系,可用作加密保护等
  12. FileAlignment DWORD // 文件页边界数,要求是2^n,最小值是512,默认是512.通常根据磁盘扇区、硬盘缓存等因素决定
  13. MajorOperatingSystemVersion WORD // 操作系统主版本号。
  14. MinorOperatingSystemVersion WORD // 操作系统次版本号。
  15. MajorImageVersion WORD // 文件主版本号。
  16. MinorImageVersion WORD // 文件次版本号。
  17. MajorSubsystemVersion WORD // 子系统主版本号,一般为4。
  18. MinorSubsystemVersion WORD // 子系统次版本号,一般为0。如果是驱动程序,则应该设置为合适的子系统版本号.
  19. Win32VersionValue DWORD // Win32 版本值(保留)。
  20. SizeOfImage DWORD // 映像大小,单位字节。必须对齐到内存页边界数,即SectionAlignment属性指定的值。
  21. SizeOfHeaders DWORD // 所有头大小,包括MS-DOS、PE和节表等信息。必须对齐到文件页边界数,即FileAlignment属性指定的值。
  22. CheckSum DWORD // 校验和(保留)。可以是0或者0xFFFF表示不进行校验。(实际上也没有谁会去做这个事情)
  23. Subsystem WORD // 程序子系统类型:GUI窗口程序、控制台程序等等
  24. DllCharacteristics WORD // DLL文件特性标志:如是否支持ASLR、DEP等等
  25. SizeOfStackReserve DWORD // 初始的堆栈空间大小(用于进程启动),默认是1MB。如果想改变默认大小,请使用 /STACK 参数链接器选项。
  26. SizeOfStackCommit DWORD // 初始的堆栈页面大小(用于进程启动),默认是4KB。如果想改变默认大小,请使用 /STACK 参数链接器选项。
  27. SizeOfHeapReserve DWORD // 初始的堆空间大小(用于进程启动),默认是1MB。如果想改变默认大小,请使用 /HEAP 参数链接器选项。
  28. SizeOfHeapCommit DWORD // 初始的堆页面大小(用于进程启动),默认是4KB。如果想改变默认大小,请使用 /HEAP 参数链接器选项。
  29. LoaderFlags DWORD // 加载标志,0为没有标志设置
  30. NumberOfRvaAndSizes DWORD // 数据目录结构数量,默认为16个
  31. DataDirectory [IMAGE_NUMBEROF_DIRECTORY] IMAGE_DATA_DIRECTORY // 存储着16个数据目录结构,从第一个元素开始:导出表、导入表、资源表、异常处理表等等...

}

type IMAGE_OPTIONAL_HEADER64 struct {

  1. Magic WORD // 魔数:用于区分PE文件和OBJ文件。PE文件为0x10B或者0x107;OBJ文件为0xFFFF.
  2. MajorLinkerVersion BYTE // 连接器主版本号。
  3. MinorLinkerVersion BYTE // 连接器次版本号。
  4. SizeOfCode DWORD // 代码段大小,单位字节。必须对齐到文件中的FileAlignment属性指定的值。
  5. SizeOfInitializedData DWORD // 初始化数据段大小,单位字节。必须对齐到文件中的FileAlignment属性指定的值。
  6. SizeOfUninitializedData DWORD // 未初始化数据段大小,单位字节。必须对齐到文件中的FileAlignment属性指定的值。
  7. AddressOfEntryPoint DWORD // 程序入口点地址RVA(相对虚拟地址)。
  8. BaseOfCode DWORD // 代码段起始地址RVA(相对虚拟地址)。
  9. ImageBase QWORD // 映像装载基址,程序在运行时被映射到内存的起始位置。一般为0x400000
  10. SectionAlignment DWORD // 内存页边界数,要求是2^n,最小值是512,默认是4096(4KB)。通常与文件中区块偏移量划分有关系,可用作加密保护等
  11. FileAlignment DWORD // 文件页边界数,要求是2^n,最小值是512,默认是512.通常根据磁盘扇区、硬盘缓存等因素决定
  12. MajorOperatingSystemVersion WORD // 操作系统主版本号。
  13. MinorOperatingSystemVersion WORD // 操作系统次版本号。
  14. MajorImageVersion WORD // 文件主版本号。
  15. MinorImageVersion WORD // 文件次版本号。
  16. MajorSubsystemVersion WORD // 子系统主版本号,一般为4。
  17. MinorSubsystemVersion WORD // 子系统次版本号,一般为0。如果是驱动程序,则应该设置为合适的子系统版本号.
  18. Win32VersionValue DWORD // Win32 版本值(保留)。
  19. SizeOfImage DWORD // 映像大小,单位字节。必须对齐到内存页边界数,即SectionAlignment属性指定的值。
  20. SizeOfHeaders DWORD // 所有头大小,包括MS-DOS、PE和节表等信息。必须对齐到文件页边界数,即FileAlignment属性指定的值。
  21. CheckSum DWORD // 校验和(保留)。可以是0或者0xFFFF表示不进行校验。(实际上也没有谁会去做这个事情)
  22. Subsystem WORD // 程序子系统类型:GUI窗口程序、控制台程序等等
  23. DllCharacteristics WORD // DLL文件特性标志:如是否支持ASLR、DEP等等
  24. SizeOfStackReserve QWORD // 初始的堆栈空间大小(用于进程启动),默认是1MB。如果想改变默认大小,请使用 /STACK 参数链接器选项。
  25. SizeOfStackCommit QWORD // 初始的堆栈页面大小(用于进程启动),默认是4KB。如果想改变默认大小,请使用 /STACK 参数链接器选项。
  26. SizeOfHeapReserve QWORD // 初始的堆空间大小(用于进程启动),默认是1MB。如果想改变默认大小,请使用 /HEAP 参数链接器选项。
  27. SizeOfHeapCommit QWORD // 初始的堆页面大小(用于进程启动),默认是4KB。如果想改变默认大小,请使用 /HEAP 参数链接器选项。
  28. LoaderFlags DWORD // 加载标志,0为没有标志设置
  29. NumberOfRvaAndSizes DWORD // 数据目录结构数量,默认为16个
  30. DataDirectory [IMAGE_NUMBEROF_DIRECTORY] IMAGE_DATA_DIRECTORY // 存储着16个数据目录结构,从第一个元素开始:导出表、导入表、资源表、异常处理表等等...

}

type IMAGE_NT_HEADERS32 struct {

  1. Signature uint32 // 固定值0x00004550(PE00)。如果不是,则表示文件不是有效的PE格式文件。
  2. FileHeader IMAGE_FILE_HEADER
  3. OptionalHeader IMAGE_OPTIONAL_HEADER32

}

type IMAGE_NT_HEADERS64 struct {

  1. Signature uint32 // 固定值0x00004550(PE00)。如果不是,则表示文件不是有效的PE格式文件。
  2. FileHeader IMAGE_FILE_HEADER
  3. OptionalHeader IMAGE_OPTIONAL_HEADER64

}

type (

  1. DWORD uint32 // 4字节无符号整数类型。
  2. LONG int32 // 4字节有符号整数类型。
  3. QWORD uint64 // 8字节无符号整数类型。
  4. SHORT int16 // 2字节有符号整数类型。
  5. WORD uint16 // 2字节无符号整数类型。

)

const (

  1. PIMAGE_DIRECTORY_ENTRY_EXPORT = iota // 函数名称导出表(Export Table).
  2. PIMAGE_DIRECTORY_ENTRY_IMPORT // 导入函数地址表和名称信息(Import Address Table)
  3. PIMAGE_DIRECTORY_ENTRY_RESOURCE // 资源表.
  4. PIMAGE_DIRECTORY_ENTRY_EXCEPTION //
  5. PIMAGE_DIRECTORY_ENTRY_SECURITY //
  6. PIMAGE_DIRECTORY_ENTRY_BASERELOC //
  7. PIMAGE_DIRECTORY_ENTRY_DEBUG //
  8. PIMAGE_DIRECTORY_ENTRY_ARCHITECTURE //
  9. PIMAGE_DIRECTORY_ENTRY_GLOBALPTR // 用于64位Windows系统中的TLS(Thread Local Storage).
  10. PIMAGE_DIRECTORY_ENTRY_TLS // TLS(Thread Local Storage)表.
  11. PIMAGE_DIRECTORY_ENTRY_LOAD_CONFIG // 加载器配置信息(不再使用).
  12. PIMAGE_DIRECTORY_ENTRY_BOUND_IMPORT //
  13. PIMAGE_DIRECTORY_ENTRY_IAT // 导入函数地址表,即IAT(Import Address Table)
  14. PIMAGE_DIRECTORY_ENTRY_DELAY_IMPORT // 延迟加载函数地址表,即Delay Import Descriptor
  15. PIMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR // COM组件信息表.
  16. // 最后一个元素.
  17. IMAGE_NUMBEROF_DIRECTORY

)

type IMAGE_THUNK_DATA32 struct {

  1. AddressOfData uint32

}

type IMAGE_THUNK_DATA64 struct {

  1. AddressOfData uint64

}

type (

  1. PTSTR uintptr
  2. UINT uint32
  3. ULONG uintptr
  4. LPCWSTR *uint16
  5. LPCTSTR uintptr
  6. BOOL int32
  7. HANDLE uintptr
  8. HMODULE uintptr

)

type IMAGE_IMPORT_BY_NAME struct {

  1. Hint uint16 `struct:"word"`
  2. Name byte `struct:"byte"`

}

func GetImportedFunctions(peFile []byte, moduleName string) ([]string, error) {

  1. var moduleFound bool = false;
  2. var importDesc IMAGE_IMPORT_DESCRIPTOR;
  3. var importedFunctions []string;
  4. dosHeader := (*IMAGE_DOS_HEADER)(unsafe.Pointer(&peFile[0]));
  5. if dosHeader.E_magic != 0x5A4D { //'MZ'
  6. return nil, fmt.Errorf("Invalid DOS header signature")
  7. }
  8. ntHeaderOffset := binary.Size(IMAGE_DOS_HEADER{}) + uintptr(dosHeader.E_lfarlc)
  9. if ntHeaderOffset+binary.Size(IMAGE_NT_HEADERS32{}) > uintptr(len(peFile)) {
  10. return nil, fmt.Errorf("Invalid NT header offset")
  11. }
  12. var ntHeaderSignature uint32
  13. binary.Read(bytes.NewReader(peFile[ntHeaderOffset:]), binary.LittleEndian, &ntHeaderSignature)
  14. if ntHeaderSignature != 0x4550 { //'PE'
  15. return nil, fmt.Errorf("Invalid NT header signature")
  16. }
  17. fileHeaderOffset := ntHeaderOffset + binary.Size(ntHeaderSignature)
  18. if fileHeaderOffset+binary.Size(IMAGE_FILE_HEADER{}) > uintptr(len(peFile)) {
  19. return nil, fmt.Errorf("Invalid file header offset")
  20. }
  21. var fileHeader IMAGE_FILE_HEADER
  22. binary.Read(bytes.NewReader(peFile[fileHeaderOffset:]), binary.LittleEndian, &fileHeader)
  23. optHeaderOffset := fileHeaderOffset + binary.Size(fileHeader)
  24. if optHeaderOffset >= uintptr(len(peFile)) {
  25. return nil, fmt.Errorf("Invalid optional header offset")
  26. }
  27. is64Bit := false;
  28. switch magic := (*WORD)(unsafe.Pointer(&peFile[optHeaderOffset]))[0]; magic {
  29. case 0x10b:
  30. optHeadersSize := binary.Size(IMAGE_OPTIONAL_HEADER32{})
  31. importDirRVA := (*[]uint32)(unsafe.Pointer(&peFile[optHeaderOffset+optHeadersSize]))[PIMAGE_DIRECTORY_ENTRY_IMPORT]
  32. dataSectionRVA := (*[]uint32)(unsafe.Pointer(&peFile[optHeadersSize+24]))[1];
  33. sectionAlignment := (*DWORD)(unsafe.Pointer(&peFile[optHeadersSize+

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=3477

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?