如何使用其序数值从DLL查找过程?

时间:2018-07-24 20:55:26

标签: go dll

我正在尝试使用序数值从DLL调用过程(无名称)。

我可以在C#中使用此DLL,将原始值设置为Error.php的属性EntryPoint

  

...,也可以按顺序标识入口点。普通字首带有#号,例如#1。 [...]

C#示例:

$_SESSION['message'] = "Some Message";
$MSG = $_SESSION['message'];
header('location: ../Pages/Error.php');
session_destroy();
die();

当尝试在Go中找到带有“#”符号的过程时,它显示以下错误:

  

在dllname.dll中找不到#3过程:找不到指定的过程。

我使用dumpbin来显示DLL的信息,没有函数具有名称:

dumpbin results

是否可以使用序号(例如C#)查找过程?

1 个答案:

答案 0 :(得分:1)

a github issue here,但似乎从Go 1.10.3(我现在正在使用的版本)开始尚未合并。

无论如何,github问题链接到a changeset with the respective function,我从中提取了代码以执行您想要的操作:

var (
    kernel32           = syscall.NewLazyDLL("kernel32.dll")
    procGetProcAddress = kernel32.NewProc("GetProcAddress")
)

// GetProcAddressByOrdinal retrieves the address of the exported
// function from module by ordinal.
func GetProcAddressByOrdinal(module syscall.Handle, ordinal uintptr) (uintptr, error) {
    r0, _, _ := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0)
    proc := uintptr(r0)
    if proc == 0 {
        return 0, syscall.EINVAL
    }
    return proc, nil
}

为完整起见,这是我测试的完整示例,使用Dependecy Walker,我发现kernel32.dll中的第一个函数为AcquireSRWLockExclusive,并使用新函数显示proc地址确实匹配

package main

import (
    "fmt"
    "syscall"
)

func main() {
    dll, err := syscall.LoadDLL("kernel32.dll")
    check(err)

    want, err := syscall.GetProcAddress(dll.Handle, "AcquireSRWLockExclusive")
    check(err)
    fmt.Println(want)

    first, err := GetProcAddressByOrdinal(dll.Handle, 1)
    check(err)
    fmt.Println(first)
}

func check(err error) {
    if err != nil {
        panic(err)
    }
}

var (
    kernel32           = syscall.NewLazyDLL("kernel32.dll")
    procGetProcAddress = kernel32.NewProc("GetProcAddress")
)

// GetProcAddressByOrdinal retrieves the address of the exported
// function from module by ordinal.
func GetProcAddressByOrdinal(module syscall.Handle, ordinal uintptr) (uintptr, error) {
    r0, _, _ := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0)
    proc := uintptr(r0)
    if proc == 0 {
        return 0, syscall.EINVAL
    }
    return proc, nil
}