VB用Jmp实现函数指针VB崩溃解决方法
VB用Jmp实现函数指针VB崩溃
用了这几个函数:
GetCurrentProcess'获取当前进程的伪句柄
WriteProcessMemory'在指定进程中写内存
GetProcAddress'返回函数地址
GetModuleHandle'获取一个应用程序或动态链接库的模块句柄
主要代码:
在模块里的
这段代码的目的是用Jmp指令重定向MessageBoxIndirectA函数(VB的Msgbox使用这个函数实现的)的地址为fmsgbox函数,实现VB在调用Msgbox时转到fmsgbox函数去执行,但是调试发现实际上并没有转到fmsgbox函数,而是崩溃了。Command2_Click的代码是借助API函数写入Jmp的机器码到内存的代码,到底哪里出问题了呢?
------解决方案--------------------
第一,直接WriteProcessMemory不可能成功。因为user32.dll里面的函数体的那块内存的属性是不可写的,你必须用VirtualProtectEx来修改成PAGE_EXECUTE_READWRITE,写入内存后,再次修改回原属性,否则无法执行。
第二,JMP的机器码有很多,{0xEB,0x11,0x11,0x11,0x11}编译之后不是JMP 0x11111111。而是:
EB 11 JMP SHORT 0000001A
1111 ADC [ECX],EDX
1100 ADC [EAX],EAX
会跳到0x0000001A的地方去执行。
------解决方案--------------------
系统是分时执行的,不同的时间段内的堆、栈、寄存器值都会根据每个进程的执行状态而改变,而windows的内存管理也是个很复杂的机制,要想在这种复杂变换的堆、栈、寄存器中操作Windows资源,直接用CPU指令去弄个跳转是很危险的,只有用Windows提供的接口来调用相关资源才是最为安全的。
------解决方案--------------------
如果只是hook自己的程序,可以在导入表操作,是自己的程序空间。随便弄。
你修改dll,那是系统的空间了。程序在内存的分布,dll的分布,系统共享的内存区域等,你还没有明白。
用了这几个函数:
GetCurrentProcess'获取当前进程的伪句柄
WriteProcessMemory'在指定进程中写内存
GetProcAddress'返回函数地址
GetModuleHandle'获取一个应用程序或动态链接库的模块句柄
主要代码:
Private Sub Command2_Click()'Caption = "阻止对话框弹出(Command2)"
WriteProcessMemory GetCurrentProcess(), VarPtr(a(0)), GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxIndirectA"), 5, t '备份原代码
Dim bt As Byte
bt = &HEB
'写JMP的第一个字节:EB
WriteProcessMemory GetCurrentProcess(), GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxIndirectA"), VarPtr(bt), 1, t
Dim lt As Long
'计算JMP剩下4字节的值
lt = AddrHelper(AddressOf fmsgbox) - GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxIndirectA") - 5&
'写JMP的剩下4字节,公式为(目标地址- 当前地址- 5&)
WriteProcessMemory GetCurrentProcess(), GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxIndirectA") + 1, VarPtr(lt), 4, t
End Sub
在模块里的
Public Function fmsgbox(ByVal a As Long) As Long
fmsgbox = 0
End Function
这段代码的目的是用Jmp指令重定向MessageBoxIndirectA函数(VB的Msgbox使用这个函数实现的)的地址为fmsgbox函数,实现VB在调用Msgbox时转到fmsgbox函数去执行,但是调试发现实际上并没有转到fmsgbox函数,而是崩溃了。Command2_Click的代码是借助API函数写入Jmp的机器码到内存的代码,到底哪里出问题了呢?
------解决方案--------------------
第一,直接WriteProcessMemory不可能成功。因为user32.dll里面的函数体的那块内存的属性是不可写的,你必须用VirtualProtectEx来修改成PAGE_EXECUTE_READWRITE,写入内存后,再次修改回原属性,否则无法执行。
第二,JMP的机器码有很多,{0xEB,0x11,0x11,0x11,0x11}编译之后不是JMP 0x11111111。而是:
EB 11 JMP SHORT 0000001A
1111 ADC [ECX],EDX
1100 ADC [EAX],EAX
会跳到0x0000001A的地方去执行。
------解决方案--------------------
系统是分时执行的,不同的时间段内的堆、栈、寄存器值都会根据每个进程的执行状态而改变,而windows的内存管理也是个很复杂的机制,要想在这种复杂变换的堆、栈、寄存器中操作Windows资源,直接用CPU指令去弄个跳转是很危险的,只有用Windows提供的接口来调用相关资源才是最为安全的。
------解决方案--------------------
如果只是hook自己的程序,可以在导入表操作,是自己的程序空间。随便弄。
你修改dll,那是系统的空间了。程序在内存的分布,dll的分布,系统共享的内存区域等,你还没有明白。