在Windows PE格式中,ImageImportDescriptor结构体是用来描述一个模块依赖的结构体。其中Name字段是指向DLL名称的指针。
要获取Name指针对应的字符串,可以通过以下步骤实现:
- 获取Name字段的RVA(相对虚拟地址)值。
- 根据PE文件头信息获取到该RVA所在节表项,并获得该节数据在内存中的起始地址。
- 计算出Name指针相对于该节的偏移量。
- 通过偏移量获取到该字符串。
以下是Golang代码示例:
import (
"encoding/binary"
"unsafe"
)
type ImageImportDescriptor struct {
OriginalFirstThunk uint32
TimeDateStamp uint32
ForwarderChain uint32
Name uint32
FirstThunk uint32
}
// 获取Name字段对应的字符串
func GetNameString(peData []byte, importDesc *ImageImportDescriptor) string {
namePtrRva := importDesc.Name
// 根据RVA获取所在节表项及其数据起始地址
var sectionHeaderOffset = binary.Size(IMAGE_FILE_HEADER{})
var ntHeader IMAGE_NT_HEADERS32
if err := binary.Read(bytes.NewReader(peData[sectionHeaderOffset:]), binary.LittleEndian, &ntHeader); err != nil {
panic(err)
}
var sec IMAGE_SECTION_HEADER
for i := 0; i < int(ntHeader.FileHeader.NumberOfSections); i++ {
if err := binary.Read(bytes.NewReader(peData[sectionHeaderOffset+int(binary.Size(IMAGE_NT_HEADERS32{}))+i*int(binary.Size(IMAGE_SECTION_HEADER{})):]), binary.LittleEndian, &sec); err != nil {
panic(err)
}
if namePtrRva >= sec.VirtualAddress && namePtrRva < sec.VirtualAddress+sec.VirtualSize {
break
}
}
// 计算Name指针相对于该节的偏移量
var nameOffset = int(namePtrRva - sec.VirtualAddress + sec.PointerToRawData)
// 通过偏移量获取字符串
return goString(peData[nameOffset:])
}
// 将[]byte转换为string类型
func goString(data []byte) string {
p := unsafe.Pointer(&data[0])
return *(*string)(unsafe.Pointer(&reflect.StringHeader{
Data: uintptr(p),
Len: len(data),
}))
}
这个函数会返回指向DLL名称的字符串。注意,此处省略了部分结构体定义和相关常量的定义,需要自己实现。




