On Error Resume Next
Debug.Assert 1 / 0
If Err Then MsgBox "IDE" Else MsgBox "Compiled"
On Error GoTo 0
Option Explicit
Private Declare Function FreeLibrary Lib "kernel32.dll" (ByVal hLibModule As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32.dll" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetCProc Lib "kernel32.dll" Alias "GetCurrentProcess" () As Long
Private Declare Function PutMem4 Lib "msvbvm60" (ByVal pDst As Long, ByVal NewValue As Long) As Long
Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" _
(ByVal pDst As Long, ByVal pSrc As Long, ByVal ByteLen As Long)
Private Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (ByRef vArr() As Any) As Long
Private Type SAFEARRAYBOUND_L '8 bytes
p1_DSize As Long
p2_DLbound As Long
End Type
Private Type SAFEARRAY_L '24 bytes
p1_cDims As Integer
p2_fFeat As Integer
p3_ESize As Long
p4_cLocks As Long
p5_pvData As Long
Bounds As SAFEARRAYBOUND_L
End Type
Private MSsa As SAFEARRAY_L, MSa() As Byte, RDa() As Byte, WPMa() As Byte
Private pRet As Long, vESP As Long, kernel As Long, pWPM As Long, NCa() As Byte
Private pRD As Long, pT1 As Long, pT2 As Long
Private Sub Main()
MInit
CallT
MsgBox "Вернулись", vbOKOnly, "Sub Main"
FreeLibrary kernel
End Sub
Private Sub MInit()
InitSA
InitK
End Sub
Private Sub InitSA()
'Инициализируем массив
With MSsa
.p1_cDims = 1
.p2_fFeat = 128
.p3_ESize = 1
.p4_cLocks = 0
.p5_pvData = GetPA(AddressOf Main) 'Сошлёмся на Sub Main "на всякий случай", поросто, чтобы не было неожиданностей...
.Bounds.p1_DSize = 200
.Bounds.p2_DLbound = 0
End With
PutMem4 ArrPtr(MSa), ByVal VarPtr(MSsa)
End Sub
Private Sub InitK()
kernel = LoadLibrary("kernel32.dll")
pWPM = GetProcAddress(kernel, "WriteProcessMemory")
pRD = GetPA(AddressOf ReDirect)
pT1 = GetPA(AddressOf Test1)
pT2 = GetPA(AddressOf Test2)
End Sub
Private Sub CallT()
Dim i As Long, lRes As Long
For i = 1 To 2
If i = 1 Then
lRes = ReDirect(pT1, 123456789)
Else
lRes = ReDirect(pT2, 123456789)
End If
MsgBox lRes, vbOKOnly, "CallT"
Next i
End Sub
Private Function GetPA(ByVal vProcAddress As Long) As Long
GetPA = vProcAddress
End Function
Private Function ReDirect(ByVal vNPA As Long, ByVal vVal As Long) As Long
Dim lNPA As Long
lNPA = vNPA
vESP = VarPtr(vVal) - 8
CopyMem VarPtr(pRet), vESP, 4
MSsa.p5_pvData = pRet - 5
If MSa(0) = &HE8 Then
ReDim NCa(1 To 5)
'pop eax
NCa(1) = &H67: NCa(2) = &H58
'call eax
NCa(3) = &H67: NCa(4) = &HFF: NCa(5) = &HD0
WPM ByVal GetCProc, pRet - 5, VarPtr(NCa(1)), 5, ByVal 0&
ReDim RDa(1 To 16)
'push imm32=vVal
RDa(1) = &H68: PutMem4 VarPtr(RDa(2)), vVal
'push imm32=pRet
RDa(6) = &H68: PutMem4 VarPtr(RDa(7)), pRet
'jmp dword ptr ds:[VarPtr(lNPA)]
RDa(11) = &HFF: RDa(12) = &H25: PutMem4 VarPtr(RDa(13)), VarPtr(lNPA)
PutMem4 vESP, VarPtr(RDa(1))
MsgBox "Это откомпилированая программа" & vbCr & "все необходимые замены сделаны" & vbCr & _
"сейчас пойдём в Test1 из ReDirect" & vbCr & _
"ОДНАКО!!! Второй раз (у нас ведь цикл в Sub CallT), будет вызвана Test2" & vbCr & _
"причём, прямо из Sub CallT!!!", vbOKOnly, "ReDirect"
Else
vESP = vESP - 4
CopyMem VarPtr(pRet), vESP, 4
MSsa.p5_pvData = pRet - 2
If MSa(0) = &HFF Then
ReDim RDa(1 To 16)
'push imm32=vVal
RDa(1) = &H68: PutMem4 VarPtr(RDa(2)), vVal
'push imm32=pRet
RDa(6) = &H68: PutMem4 VarPtr(RDa(7)), pRet
'jmp dword ptr ds:[VarPtr(lNPA)]
RDa(11) = &HFF: RDa(12) = &H25: PutMem4 VarPtr(RDa(13)), VarPtr(lNPA)
PutMem4 vESP, VarPtr(RDa(1))
MsgBox "Это IDE и этим всё сказано" & vbCr & "все необходимые замены сделаны" & vbCr & _
"сейчас пойдём в Test1 из ReDirect" & vbCr & _
"ОДНАКО!!! Второй раз (у нас ведь цикл в Sub CallT), будет вызвана Test2", vbOKOnly, "ReDirect"
End If
End If
End Function
Private Sub WPM(ByVal vP1 As Long, ByVal vP2 As Long, ByVal vP3 As Long, ByVal vP4 As Long, ByVal vP5 As Long)
ReDim WPMa(1 To 14)
'sub esp,imm8=20
WPMa(1) = &H83: WPMa(2) = &HEC: WPMa(3) = 20
'push imm32=<адрес возврата>
WPMa(4) = &H68: CopyMem VarPtr(WPMa(5)), VarPtr(vP1) - 4, 4
'jmp dword ptr ds:[VarPtr(pWPM)]
WPMa(9) = &HFF: WPMa(10) = &H25: PutMem4 VarPtr(WPMa(11)), VarPtr(pWPM)
PutMem4 VarPtr(vP1) - 4, VarPtr(WPMa(1))
End Sub
Private Function Test1(ByVal vVal As Long) As Long
MsgBox vVal, vbOKOnly, "Test1"
Test1 = vVal
End Function
Private Function Test2(ByVal vVal As Long) As Long
MsgBox vVal, vbOKOnly, "Test2"
Test2 = 987654321 - vVal
End Function
GSerg писал(а):Не разбираясь очень глубоко в ActiveXDll, отвечу сразу на замечания:
во-первых, SetFunction можно вызывать сколько угодно раз, меняя, таким образом, адрес, на который настроена функция.
jmp rel32
jmp dword ptr ds:[VarPtr(SomeVariable)]
SomeVariable=vNewAddress
во-вторых, скажи мне, что может быть быстрее записанного туда 1 (одного) jmp?
Call rel32
jmp rel32
Call rel32
call rel32
pop eax
call eax
jmp rel32
Public vCallAddress as Long, Ia() as Byte
ReDim Ia(1 to 6)
'jmp dword ptr ds:[imm32=VarPtr(vCallAddress)]
Ia(1)=&HFF: Ia(2)=&H25: PutMem4 VarPtr(Ia(3)), VarPtr(vCallAddress)
xor eax,eax
ret 4
Public Function PlaceholderFor1ParamFunction(ByVal p As Long) As Long
#If ReleaseBuild Then
PlaceholderFor1ParamFunction = 1&
#Else
Dim a As Long
On Error Resume Next
a = mCol(CStr(ReturnMe(AddressOf modFuncCall.PlaceholderFor1ParamFunction)))
On Error GoTo 0
If a Then PlaceholderFor1ParamFunction = CallFunction(a, 1, p)
#End If
End Function
mov eax,imm32
ret 4
ReDim Ia(1 to 8)
'jmp dword ptr ds:[imm32=VarPtr(vCallAddress)]
Ia(1)=&HFF: Ia(2)=&H25: PutMem4 VarPtr(Ia(3)), VarPtr(vCallAddress)
'nop
'nop
Ia(7)=&H90: Ia(8)=&H90
vCallAddress=vNewValue
call operand
push eip
jmp operand
mov dword ptr ds:[esp–4],eip
sub esp,4
mov eip,operand
ret optional imm16
add esp,optional imm16+4
mov eip,dword ptr ds:[esp–optional imm16–4]
ret imm16
ret imm16
Private Function Test(byval vP1 as Long)as Long
…
End Function
vESP = VarPtr(vP1) – 4
vESP = VarPtr(vP1) – 8
Public pRet as Long
CopyMem VarPtr(pRet), vESP, 4
Public RDa() as Byte, pRD as Long
Private Sub InitRD()
ReDim RDa(1 to 16)
'восстанавливаем значение регистра esp
'sub esp,imm8=4
RDa(1)=&H83: RDa(2)=&HEC: RDa(3)=4
'заново прописываем адрес возврата, предварительно сохранённый нами в pRet
'push dword ptr ds:[imm32=VarPtr(pRet)]
RDa(4)=&HFF: RDa(5)=&H34: RDa(6)=&H25: PutMem4 VarPtr(RDa(7)), VarPtr(pRet)
'ну, теперь, наконец, можно перейти по интересующему нас адресу
'предварительно записанному нами в vCallAddress
'jmp dword ptr ds:[imm32=VarPtr(vCallAddress)]
RDa(11)=&HFF: RDa(12)=&H25: PutMem4 VarPtr(RDa(13)), VarPtr(vCallAddress)
pRD=VarPtr(RDa(1))
End Sub
Private Function Test(byval vP1 as Long)as Long
#If ReleaseBuild Then
vESP = VarPtr(vP1) - 4
#Else
vESP = VarPtr(vP1) - 8
#End If
CopyMem VarPtr(pRet), vESP, 4
PutMem4 vESP, pRD
End Function
call rel32
call rel32=Offset PlaceholderFor1ParamFunction
jmp rel32=Offset <Вызываемая функция>
call rel32=Offset PlaceholderFor1ParamFunction
jmp dword ptr ds:[imm32=VarPtr(vCallAddress)]
#If ReleaseBuild Then
Private Ra() as Byte
Public Function ReDirect(Optional ByVal vP0 As Long, Optional ByVal vP1 As Long) As Long
vESP=VarPtr(vP0)-4
CopyMem VarPtr(pRet), vESP, 4
ReDim Ra(1 to 7)
'call dword ptr ds:[imm32=VarPtr(vCallAddress]
Ra(1)=&H3E: Ra(2)=&HFF: Ra(3)=&H15: PutMem VarPtr(Ra(4)), VarPtr(vCallAddress)
WriteProcessMemory GetCurProcess, pRet-7, VarPtr(Ra(1)), 7, 0&
PutMem4 vESP, pRD
End Function
#End If
vCallAddress=vNewAddress
vReturnValue=ReDirect(,vParamValue)
push imm8=0
call rel32
call dwrod ptr ds:[imm32]
push imm8=0
#If ReleaseBuild Then
Private REa() as Byte
Public Function REx(ByVal vP0 As Long, ByVal vP1 As Long) As Long
vESP=VarPtr(vP0)-4
CopyMem VarPtr(pRet), vESP, 4
ReDim REa(1 to 5)
‘pop eax
REa(1)=&H67: REa(2)=&H58
'call eax
REa(3)=&H67: REa(4)=&HFF: REa(5)=&HD0
WriteProcessMemory GetCurProcess, pRet-5, VarPtr(REa(1)), 5, 0&
PutMem4 vESP, pRD
End Function
#End If
vReturnValue=REx(vCallAddress,vParamValue)
call rel32
pop eax
call eax
call rel32
#If ReleaseBuild Then
Public vNewAddress as Long
Private Function GetPA(ByVal vProcAddress as Long)as Long
GetPA=vProcAddress
End Function
Public Function ReD(ByVal vP1 As Long) As Long
vESP=VarPtr(vP0)-4
CopyMem VarPtr(pRet), vESP, 4
'до обращения в vNewAddress должен содержаться «абсолютный» адрес
'после вычисления там будет содержаться относительный
vNewAddress=pRet-GetPA(AddressOf ReD)+vNewAddress
WriteProcessMemory GetCurProcess, pRet-4, VarPtr(vNewAddress), 4, 0&
PutMem4 vESP, pRD
End Function
#End If
vNewAddress=<адрес вызываемой процедуры>
…
vReturnValue=ReD(vParamValue)
call rel32
GSerg писал(а):Что я могу сказать? Только "не люблю глобальные переменные"
А вообще, для моего асм-уровня это слишком круто
Private Declare Function Call0 Lib "Asm.dll" Alias "CallEx" _
(ByVal pProc As Long) As Long
Private Declare Function Call1 Lib "Asm.dll" Alias "CallEx" _
(ByVal pProc As Long, ByVal vP1 As Long) As Long
Private Declare Function Call9 Lib "Asm.dll" Alias "CallEx" _
(ByVal pProc As Long, ByVal vP1 As Long, ByVal vP2 As Long, ByVal vP3 As Long, ByVal vP4 As Long, _
ByVal vP5 As Long, ByVal vP6 As Long, ByVal vP7 As Long, ByVal vP8 As Long, ByVal vP9 As Long) As Long
Private Sub Main()
Dim vLR0 As Long, vLR1 As Long, vLR9 As Long
'способ первый и самый правильный
vLR0 = Call0(AddressOf Test0)
vLR1 = Call1(AddressOf Test1, 1122334455)
vLR9 = Call9(AddressOf Test9, 1, 2, 3, 4, 5, 6, 7, 8, 9)
MsgBox vLR0 & ", " & vLR1 & ", " & vLR9, vbOKOnly, "Результаты"
End
End Sub
Private Function Test0() As Long
Test0 = 1234567890
End Function
Private Function Test1(ByVal vP1 As Long) As Long
Test1 = vP1
End Function
Private Function Test9(ByVal vP1 As Long, ByVal vP2 As Long, ByVal vP3 As Long, ByVal vP4 As Long, ByVal vP5 As Long, _
ByVal vP6 As Long, ByVal vP7 As Long, ByVal vP8 As Long, ByVal vP9 As Long) As Long
Test9 = vP1 + vP2 + vP3 + vP4 + vP5 + vP6 + vP7 + vP8 + vP9
Test9 = Test9 / 9
End Function
tyomitch писал(а):Так, к слову...
В Win9x в kernel32 есть все нужные функции - Callback4, Callback8, Callback12, и так далее примерно до Callback48 (могу ошибиться с верхней границей).
Т.е. там можно и без Asm.dll
tyomitch писал(а):Да я их так, к слову упомянул, а вовсе не как "конкуренцию" для Asm.dll
Кстати, а какая принципиальная разница, одна там функция, или много? Всё равно по одному объявлению на каждое число параметров, так?
tyomitch писал(а):Approximator, я не шучу, я просто не догоняю сразу
Объясни пожалуйста, почему одна функция - лучше чем много?
"Для успеха два ореха лучше, чем один" (с)
GSerg писал(а):Одна функция, наверное, лучше потому, что меньше места занимает
Роющим ради процесса привет и понимание
А у Сергея, хоть и медленно работает под IDE, но какое это имеет значение, под IDE-то? Нет, это не повод, чтобы не рыть Но потому я на это и забил, что под IDE не так уж это и важно.
GSerg писал(а):Да нет, ну почему сразу хуже... Никто же не критикует
ЗЫ: Если рыть - то это как раз внимать альтернативным вариантам. Даже если только ради процесса Кстати, потом часто оказывается, что нарытое в процессе рытья ради процесса (:D) весьма полезно и применимо...
Approximator писал(а):P.S. Представляете, как мы с моими "товарищами по оружию" "пинаем" друг друга при "обкатке" кем-либо новой темы на семинарах?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 50