You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang中向MS-RPC发送DCE-RPC/SMB请求并调用MS-EVEN函数?

解决Golang调用MS-EVEN RPC的ELFTOpenELW函数问题

以下是针对你问题的具体落地思路,一步步排查并实现:

1. 确认MS-EVEN RPC绑定的核心参数

首先要确保RPC绑定的UUID和版本号完全正确,这是绑定成功的前提:

  • MS-EVEN的UUID是dfac7a5c-5f19-11d2-978e-0000f8757e2d,版本为0.0(可从Impacket的even.py模块中验证)
  • 绑定RPC时,必须指定这个UUID和版本,替换掉原ms-srvs对应的参数,同时确保安全上下文(比如NTLM认证的凭据、签名设置)和SMB连接一致。

2. 把Impacket的请求结构转成Golang的NDR兼容结构体

ELFTOpenELW是宽字符版本的函数,请求结构体需要严格遵循NDR编码规范:

  • 参考Impacket中ELFTOpenELWRequest的定义,转换成Golang结构体,注意字段的顺序、类型(比如宽字符串用[]uint16,整数用小端字节序)
  • 实现结构体的MarshalNDR方法,参考go-smb中已有RPC结构体的NDR序列化逻辑,处理字符串长度、字段对齐等细节。例如:
type ELFTOpenELWRequest struct {
    ServerName    []uint16
    EventLogName  []uint16
    Reserved      uint32
    DesiredAccess uint32
}

func (r *ELFTOpenELWRequest) MarshalNDR(w ndr.Writer) error {
    // 序列化ServerName:先写长度(含终止符),再写字节
    if err := w.WriteUint32(uint32(len(r.ServerName))); err != nil {
        return err
    }
    for _, c := range r.ServerName {
        if err := w.WriteUint16(c); err != nil {
            return err
        }
    }
    // 按同样逻辑序列化EventLogName
    if err := w.WriteUint32(uint32(len(r.EventLogName))); err != nil {
        return err
    }
    for _, c := range r.EventLogName {
        if err := w.WriteUint16(c); err != nil {
            return err
        }
    }
    // 序列化Reserved和DesiredAccess
    if err := w.WriteUint32(r.Reserved); err != nil {
        return err
    }
    return w.WriteUint32(r.DesiredAccess)
}

3. 抓包对比定位请求差异

因为Wireshark没有MS-EVEN解析器,直接用字节对比法排查:

  • 先用Impacket运行调用ELFTOpenELW的代码,抓取完整的SMB+RPC流量
  • 再用你的Go代码发起请求,抓取同样的流量
  • 逐字节对比两个请求的RPC调用包,重点看:
    • RPC头中的操作编号(ELFTOpenELW的操作编号是0x00,可从MS-EVEN文档或Impacket中确认)
    • NDR序列化后的请求结构体部分,比如字符串长度、字段值是否和Impacket的一致
    • 任何字节差异都可能是问题所在,比如宽字符串是否多写/少写了终止符,整数是否用了大端字节序

4. 复用go-smb的RPC框架补全逻辑

go-smb已经实现了SMB上的RPC基础通信,你只需要:

  • 基于现有RPC客户端,创建MS-EVEN的绑定上下文
  • 构造ELFTOpenELW的请求结构体,调用RPC的Call方法
  • 解析返回的响应结构体(同样需要实现UnmarshalNDR方法)

5. 解析RPC错误码快速定位问题

如果调用失败,先解析返回的RPC错误码:

  • 0x00000005:权限不足,检查SMB连接的凭据是否有访问事件日志的权限
  • 0x000006BA:RPC绑定失败,检查UUID、版本或网络连通性
  • 0x00000002:找不到指定的事件日志,检查EventLogName参数是否正确(比如"System"、"Application")

内容的提问来源于stack exchange,提问作者Defton Deftonovich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:08:44