ZBLOG

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

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

”`go package main

import (

"bytes"
"encoding/binary"
"fmt"
"io/ioutil"
"reflect"
"unsafe"

)

type IMAGE_DOS_HEADER struct {

E_magic    uint16
E_cblp     uint16
E_cp       uint16
E_crlc     uint16
E_cparhdr  uint16
E_minalloc uint16
E_maxalloc uint16
E_ss       uint16
E_sp       uint16
E_csum     uint16
E_ip       uint16
E_cs       uint16
E_lfarlc   uint16
E_ovno     uint16

}

type IMAGE_FILE_HEADER struct {

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

}

type IMAGE_DATA_DIRECTORY struct {

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

}

type IMAGE_OPTIONAL_HEADER32 struct {

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

}

type IMAGE_OPTIONAL_HEADER64 struct {

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

}

type IMAGE_NT_HEADERS32 struct {

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

}

type IMAGE_NT_HEADERS64 struct {

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

}

type (

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

)

const (

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

)

type IMAGE_THUNK_DATA32 struct {

AddressOfData uint32

}

type IMAGE_THUNK_DATA64 struct {

AddressOfData uint64

}

type (

PTSTR uintptr
UINT  uint32
ULONG uintptr

LPCWSTR *uint16
LPCTSTR uintptr

BOOL int32

HANDLE uintptr

HMODULE uintptr

)

type IMAGE_IMPORT_BY_NAME struct {

Hint uint16 `struct:"word"`
Name byte   `struct:"byte"`

}

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

var moduleFound bool = false;
var importDesc IMAGE_IMPORT_DESCRIPTOR;
var importedFunctions []string;

dosHeader := (*IMAGE_DOS_HEADER)(unsafe.Pointer(&peFile[0]));
if dosHeader.E_magic != 0x5A4D { //'MZ'
	return nil, fmt.Errorf("Invalid DOS header signature")
}

ntHeaderOffset := binary.Size(IMAGE_DOS_HEADER{}) + uintptr(dosHeader.E_lfarlc)
if ntHeaderOffset+binary.Size(IMAGE_NT_HEADERS32{}) > uintptr(len(peFile)) {
	return nil, fmt.Errorf("Invalid NT header offset")
}

var ntHeaderSignature uint32
binary.Read(bytes.NewReader(peFile[ntHeaderOffset:]), binary.LittleEndian, &ntHeaderSignature)
if ntHeaderSignature != 0x4550 { //'PE'
	return nil, fmt.Errorf("Invalid NT header signature")
}

fileHeaderOffset := ntHeaderOffset + binary.Size(ntHeaderSignature)
if fileHeaderOffset+binary.Size(IMAGE_FILE_HEADER{}) > uintptr(len(peFile)) {
	return nil, fmt.Errorf("Invalid file header offset")
}

var fileHeader IMAGE_FILE_HEADER
binary.Read(bytes.NewReader(peFile[fileHeaderOffset:]), binary.LittleEndian, &fileHeader)

optHeaderOffset := fileHeaderOffset + binary.Size(fileHeader)
if optHeaderOffset >= uintptr(len(peFile)) {
	return nil, fmt.Errorf("Invalid optional header offset")
}

is64Bit := false;
switch magic := (*WORD)(unsafe.Pointer(&peFile[optHeaderOffset]))[0]; magic {
case 0x10b:
	optHeadersSize := binary.Size(IMAGE_OPTIONAL_HEADER32{})

	importDirRVA := (*[]uint32)(unsafe.Pointer(&peFile[optHeaderOffset+optHeadersSize]))[PIMAGE_DIRECTORY_ENTRY_IMPORT]

    dataSectionRVA := (*[]uint32)(unsafe.Pointer(&peFile[optHeadersSize+24]))[1];

    sectionAlignment := (*DWORD)(unsafe.Pointer(&peFile[optHeadersSize+

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?