首发:变态VB之HookAPI(陈辉作品)

(声明:魏滔序原创,转贴请注明出处。)
        标题的名字本身就变态,因为VB做HookAPI的确让人难以理解,没两把刷子的人也不敢轻易尝试。但陈辉兄弟写出了目前最简单的Hook代码,初步测试效果还不错。
       早期研究过憨豆豆(超级绿豆)的版本,也是一部惊世之作。现在,VB的Fans们又多了一项选择。
        这个HookAPI,在注入的目标为VB编译的EXE或Explorer可以正常工作,其他的exe会有问题,希望有高人能跟踪测试一下问题之所在,造福VB一方网民。 

HookAPI核心部分

项目文件:HookInfo.vbp
Type=Exe
Module=modHookMain; modHookMain.bas
Reference=*/G{00020430-0000-0000-C000-000000000046}#2.0#0#../../../../WINDOWS/system32/STDOLE2.TLB#OLE Automation
Form=frmMain.frm
Module=modHookInfo; modHookInfo.bas
Startup="Sub Main"
HelpFile=""
Title="HookInfo"
ExeName32="HookInfo.exe"
Command32=""
Name="HookInfo"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionCompanyName="Chenhui530"
CompilationType=-1
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1

[MS Transaction Server]
AutoRefresh=1

窗体文件:frmMain.frm (本窗体无任何操作,为了进程的生命期而存在。)
VERSION 5.00
Begin VB.Form frmMain
   Caption         =   "API拦截"
   ClientHeight    =   3090
   ClientLeft      =   60
   ClientTop       =   450
   ClientWidth     =   4680
   LinkTopic       =   "Form1"
   ScaleHeight     =   3090
   ScaleWidth      =   4680
   StartUpPosition =   3  '窗口缺省
End
Attribute VB_Name = "frmMain"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False

模块文件:modHookInfo.bas
Attribute VB_Name = "modHookInfo"
Private Declare Function MessageBoxA Lib "user32" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long
Private Declare Function MessageBoxW Lib "user32" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const PROCESS_QUERY_INFORMATION As Long = (&H400)

Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000

Private Const SYNCHRONIZE As Long = &H100000

Private Const PROCESS_ALL_ACCESS As Long = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)

Private mbytOldCode(5) As Byte
Private mbytNewCode(5) As Byte
Private mlngFunAddr As Long

Private mhProcess As Long

Public Function HookApi(ByVal strDllName As String, ByVal strFunName As String, ByVal lngFunAddr As Long, ByVal hProcess As Long) As Boolean
    Dim hModule As Long, dwJmpAddr As Long
    mhProcess = hProcess
    hModule = LoadLibrary(strDllName)
    If hModule = 0 Then
        HookApi = False
        Exit Function
    End If
    mlngFunAddr = GetProcAddress(hModule, strFunName)
    If mlngFunAddr = 0 Then
        HookApi = False
        Exit Function
    End If
    CopyMemory mbytOldCode(0), ByVal mlngFunAddr, 6
    Debug.Print mbytOldCode(0); mbytOldCode(1); mbytOldCode(2); mbytOldCode(3); mbytOldCode(4)
    mbytNewCode(0) = &HE9
    dwJmpAddr = lngFunAddr - mlngFunAddr - 5
    CopyMemory mbytNewCode(1), dwJmpAddr, 4
    Debug.Print mbytNewCode(0); mbytNewCode(1); mbytNewCode(2); mbytNewCode(3); mbytNewCode(4)
    HookStatus True
    HookApi = True
End Function

Public Function HookStatus(ByVal blnIsHook As Boolean) As Boolean
    If blnIsHook Then
       If WriteProcessMemory(mhProcess, ByVal mlngFunAddr, mbytNewCode(0), 5, 0) <> 0 Then HookStatus = False '拦截
    Else
        If WriteProcessMemory(mhProcess, ByVal mlngFunAddr, mbytOldCode(0), 5, 0) <> 0 Then HookStatus = False '恢复
    End If
End Function

Private Sub Class_Initialize()
'    mhProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId)
End Sub

Private Sub Class_Terminate()
    HookStatus False
'    CloseHandle mhProcess
End Sub

模块文件:modHookMain.bas
Attribute VB_Name = "modHookMain"

Option Explicit
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwnSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwnSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hhMod As Long, ByVal lpProcName As String) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long
Private Declare Function CreateRemoteThread Lib "kernel32" (ByVal hProcess As Long, lpThreadAttributes As Long, ByVal dwStacknSize As Long, lpStartAddress As Long, lpParameter As Any, ByVal dwCreationFlags As Long, lpthreadid As Long) As Long
Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal ModName As Any) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nnSize As Long, lpNumberOflngBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nnSize As Long, lpNumberOflngBytesWritten As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long
Private Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long
Private Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As Long
Private Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hhMod As Integer, ByVal lpFileName As String, ByVal nnSize As Integer) As Integer
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Sub ExitProcess Lib "kernel32" (ByVal dwExitCode As Long)
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Const MEM_COMMIT = &H1000
Private Const MEM_RESERVE = &H2000
Private Const MEM_RELEASE = &H8000
Private Const PAGE_EXECUTE_READWRITE = &H40&
Private Const IMAGE_NUMBEROF_DIRECTIRY_ENRIES = 16
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const SYNCHRONIZE = &H100000
Private Const PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)

Private Type IMAGE_DATA_DIRECTORY
    VirtualAddress As Long
    Size As Long
End Type

Private Type IMAGE_FILE_HEADER
    Machine As Integer
    NumberOfSections As Integer
    TimeDataStamp As Long
    PointerToSymbolTable As Long
    NumberOfSymbols As Long
    SizeOfOptionalHeader As Integer
    Characteristics As Integer
End Type

Private Type IMAGE_OPTIONAL_HEADER32
    Magic As Integer
    MajorLinkerVersion As Byte
    MinorLinkerVersion As Byte
    SizeOfCode As Long
    SizeOfInitalizedData As Long
    SizeOfUninitalizedData As Long
    AddressOfEntryPoint As Long
    BaseOfCode As Long
    BaseOfData As Long
    ImageBase As Long
    SectionAlignment As Long
    FileAlignment As Long
    MajorOperatingSystemVersion As Integer
    MinorOperatingSystemVersion As Integer
    MajorImageVersion As Integer
    MinorImageVersion As Integer
    MajorSubsystemVersion As Integer
    MinorSubsystemVersion As Integer
    Reserved1 As Long
    SizeOfImage As Long
    SizeOfHeaders As Long
    CheckSum As Long
    Subsystem As Integer
    DllCharacteristics As Integer
    nSizeOfStackReserve As Long
    SizeOfStackCommit As Long
    SizeOfHeapReserve As Long
    SizeOfHeapCommit As Long
    LoaerFlags As Long
    NumberOfRvaAndnSizes As Long
    DataDirectory(IMAGE_NUMBEROF_DIRECTIRY_ENRIES - 1) As IMAGE_DATA_DIRECTORY
End Type

Private Type IMAGE_DOS_HEADER
    e_magic As Integer
    e_cblp As Integer
    e_cp As Integer
    e_crlc As Integer
    e_cparhdr As Integer
    e_minalloc As Integer
    e_maxalloc As Integer
    e_ss As Integer
    e_sp As Integer
    e_csum As Integer
    e_ip As Integer
    e_cs As Integer
    e_lfarlc As Integer
    e_onvo As Integer
    e_res(3) As Integer
    e_oemid As Integer
    e_oeminfo As Integer
    e_res2(9) As Integer
    e_lfanew As Long
End Type
Private Const szTarget As String = "ProgMan"
Private szFileName As String * 261

Private Type OBJECT_ATTRIBUTES
    Length As Long
    RootDirectory As Long
    ObjectName As Long
    Attributes As Long
    SecurityDescriptor As Long
    SecurityQualityOfService As Long
End Type

Private Type CLIENT_ID
    UniqueProcess As Long
    UniqueThread  As Long
End Type

Private Declare Function NtOpenProcess Lib "NTDLL.DLL" (ByRef hProcess As Long, ByVal AccessMask As Long, ByRef ObjectAttributes As OBJECT_ATTRIBUTES, ByRef CliendwThreadId As CLIENT_ID) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As String) As Long
Private Declare Function lstrcpyn Lib "kernel32" Alias "lstrcpynA" (ByVal lpString1 As String, ByVal lpString2 As String, ByVal iMaxLength As Long) As Long
Private mProcess As Long
Private mlnghWnd As Long
Private mdwProcessId As Long
Private Type MYTYPE
    strName As String * 260
    hwnd As Long
    dwProcessId As Long
End Type
Private pInfo As MYTYPE

Private Sub Main()
    ' Sub that will start when the program is run
    Dim dwProcessId As Long, hProcess As Long
    Dim nSize As Long, lngBytesWritten As Long, dwThreadId As Long, hMod As Long, hNewMod As Long
    Dim objPImageOptionalHeader As IMAGE_OPTIONAL_HEADER32, objPImageDosHeader As IMAGE_DOS_HEADER, objTImageFileHeader As IMAGE_FILE_HEADER
    Dim lngExeVariable As Long

    frmMain.Show
    ' Get the EXE name
    GetModuleFileName 0, szFileName, 261
    pInfo.hwnd = frmMain.hwnd
    pInfo.strName = szFileName
    pInfo.dwProcessId = GetCurrentProcessId
    ' Get the dwProcessId of the program. Note that it must be running in memory (open it)
    GetWindowThreadProcessId FindWindow(0&, "测试程序"), dwProcessId
    'GetWindowThreadProcessId FindWindow(szTarget, 0&), dwProcessId

    ' Open the process and give us full access, we need this to hijack it
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwProcessId)
    If hProcess = 0 Then End
    ' Get the memory location of where our code starts in memory, this will correspond to the /BASE: switch that you put in the linker options using compile controller
    hMod = GetModuleHandleA(vbNullString)
    If hMod = 0 Then End
    ' Load the code's header into the DosHeader Type
    CopyMemory objPImageDosHeader, ByVal hMod, Len(objPImageDosHeader)
   
    ' e_lfanew is the starting address of the PE Header in memory. Add this value to the length of the fileheader as well as to the length of the optional header
    ' These headers are the founding blocks of any executable file, wether in memory or on disk.
    CopyMemory objPImageOptionalHeader, ByVal (hMod + objPImageDosHeader.e_lfanew + 4 + Len(objTImageFileHeader)), Len(objPImageOptionalHeader)
   
    ' After adding all those lengths, we will get the final nSize of the executable in memory, this is usually a bit more then the nSize on disk
    nSize = objPImageOptionalHeader.SizeOfImage
    If nSize = 0 Then End
    ' Just to make sure, free the memory in the program at the location of our exe
    VirtualFreeEx hProcess, hMod, 0, MEM_RELEASE
   
    ' Allocate the nSize of our exe in memory of the program, at the location of where our exe is in memory
    hNewMod = VirtualAllocEx(hProcess, hMod, nSize, MEM_RESERVE Or MEM_COMMIT, PAGE_EXECUTE_READWRITE)
    If hNewMod = 0 Then End
  
    ' Copy our exe into program's memory
    If WriteProcessMemory(hProcess, ByVal hNewMod, ByVal hMod, nSize, lngBytesWritten) = 0 Then End

    ' Copy the EXE name
    lngExeVariable = VirtualAllocEx(hProcess, 0, Len(pInfo), MEM_RESERVE Or MEM_COMMIT, PAGE_EXECUTE_READWRITE)
   
    'lngExeVariable = VirtualAllocEx(hProcess, 0, 261, MEM_RESERVE Or MEM_COMMIT, PAGE_EXECUTE_READWRITE)
    If lngExeVariable = 0 Then End
   
    If WriteProcessMemory(hProcess, ByVal lngExeVariable, pInfo, Len(pInfo), lngBytesWritten) = 0 Then End
    'If WriteProcessMemory(hProcess, ByVal lngExeVariable, szFileName, 261, lngBytesWritten) = 0 Then End
    '*************************************************************************
    ''这里要做下判断如果是注入非VB程序得拷贝VB库如果是VB程序则不需要下面代码
    ' Copy VB Runtime to EXE memory (same code as to copy our EXE, so I won't comment it again.
'    Dim hVBMod As Long, lngVBnSize As Long, hVBNewMod As Long
'    hVBMod = GetModuleHandleA("msvbvm60.dll")
'    If hVBMod = 0 Then End
'    CopyMemory objPImageDosHeader, ByVal hVBMod, Len(objPImageDosHeader)
'    CopyMemory objPImageOptionalHeader, ByVal (hVBMod + objPImageDosHeader.e_lfanew + 4 + Len(objTImageFileHeader)), Len(objPImageOptionalHeader)
'    lngVBnSize = objPImageOptionalHeader.SizeOfImage
'    hVBNewMod = VirtualAllocEx(hProcess, hVBMod, lngVBnSize, MEM_RESERVE Or MEM_COMMIT, PAGE_EXECUTE_READWRITE)
'    If hVBNewMod = 0 Then End
'    If WriteProcessMemory(hProcess, ByVal hVBNewMod, ByVal hVBMod, lngVBnSize, lngBytesWritten) = 0 Then End
    '**************************************************************************
    ' Create our remote thread
    If CreateRemoteThread(hProcess, ByVal 0, 0, ByVal GetFunAddr(AddressOf RemoteFunAdd), ByVal lngExeVariable, 0, dwThreadId) = 0 Then End
   
    'ExitProcess 0
End Sub

Public Function GetFunAddr(ByVal lngEntrypoint As Long) As Long
    GetFunAddr = lngEntrypoint
End Function

Public Function RemoteFunAdd(ByVal hAddr As Long) As Long ' Code that will run in the hijacked program - CANNOT USE MOST VB INTRISTIC FUNCTIONS -
    ' Call our hMod with full access to VB functions, any other code here needs to be extremly basic (not even left/mid etc)
    HookMain hAddr
End Function

Private Function HookMain(ByVal lngAgs As Long) As Long
    Dim szExename As String * 261, lnglngBytesWritten As Long
    'ReadProcessMemory OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId), ByVal lngAgs, ByVal szExename, 261, ByVal lnglngBytesWritten
    'MessageBox 0, "成功HOOK", szExename, 0
    Dim mInfo As MYTYPE, nSize As Long
    CopyMemory mInfo, ByVal lngAgs, Len(mInfo)
    nSize = lstrlen(mInfo.strName)
    If nSize <> 0 Then
        nSize = nSize + 1
        Call lstrcpyn(szExename, mInfo.strName, nSize)
    Else
        szExename = mInfo.strName
    End If
    mdwProcessId = mInfo.dwProcessId
'    MessageBox 0, mInfo.hWnd, szExename, 0
    mProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId)
'    GetWindowThreadProcessId mInfo.hWnd, mdwProcessId
    MessageBox 0, szExename, mInfo.dwProcessId, 0
    HookApi "ntdll", "NtOpenProcess", GetFunAddr(AddressOf NtOpenProcessCallback), mProcess
End Function

Private Function NtOpenProcessCallback(ByRef hProcess As Long, ByVal AccessMask As Long, ByRef ObjectAttributes As OBJECT_ATTRIBUTES, ByRef ClientId As CLIENT_ID) As Long
    Dim lngReturn As Long
    HookStatus False
    lngReturn = NtOpenProcess(hProcess, AccessMask, ObjectAttributes, ClientId)
    HookStatus True
    If hProcess <> 0 Then
        If ClientId.UniqueProcess >= mdwProcessId And ClientId.UniqueProcess < mdwProcessId + 4 Then
            MessageBox 0, "被拦截了", "哈哈", 0
            hProcess = 0
        End If
    End If
    NtOpenProcessCallback = lngReturn
End Function

测试部分

项目文件:Test.vbp
Type=Exe
Form=frmMain.frm
Reference=*/G{00020430-0000-0000-C000-000000000046}#2.0#0#../../../../../WINDOWS/system32/STDOLE2.TLB#OLE Automation
Startup="frmMain"
ExeName32="Test.exe"
Command32=""
Name="Test"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionCompanyName="eabax"
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1

[MS Transaction Server]
AutoRefresh=1

窗体文件:frmMain.frm
VERSION 5.00
Begin VB.Form frmMain
   Caption         =   "测试程序"
   ClientHeight    =   3090
   ClientLeft      =   60
   ClientTop       =   450
   ClientWidth     =   4680
   LinkTopic       =   "Form1"
   ScaleHeight     =   3090
   ScaleWidth      =   4680
   StartUpPosition =   3  '窗口缺省
   Begin VB.CommandButton cmdKill
      Caption         =   "结束进程"
      Height          =   525
      Left            =   1080
      TabIndex        =   0
      Top             =   1260
      Width           =   1695
   End
End
Attribute VB_Name = "frmMain"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Sub cmdKill_Click()
    Dim hWnd As Long, dwProcesdId As Long, hProcess As Long
    hWnd = FindWindow(vbNullString, "API拦截")
    GetWindowThreadProcessId hWnd, dwProcessId
    hProcess = OpenProcess(1, 0, dwProcessId)
    TerminateProcess hProcess, 0
End Sub

两个项目编译后,先打开Test.exe,然后再打开HookInfo.exe。
点击Test中窗体的按钮即可看到效果,祝你好运。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
VB HookAPI是一种在Visual Basic中使用的编程技术,用于拦截和修改Windows操作系统的API调用。它可以通过拦截API函数的调用来监视和处理特定的系统事件和消息。 通过使用VB HookAPI,我们可以实现许多有趣和有用的功能。例如,我们可以拦截键盘和鼠标的输入,以便在特定按键或鼠标动作时执行特定的操作。我们还可以拦截窗口消息,并根据需要修改或禁止其执行。此外,可以利用VB HookAPI来实现对窗口的监视和控制,包括窗口焦点的管理、窗口的移动和调整大小等。 VB HookAPI的实现通常包括以下步骤:首先,我们需要确定要拦截的API函数,并在代码中声明它们的外部函数。然后,我们需要创建一个钩子过程(Hook Procedure),它会接收系统的消息和事件,并对其进行处理。接下来,我们使用VB HookAPI函数来安装和卸载钩子,并将钩子过程链接到特定的系统事件或消息上。最后,我们可以在钩子过程中编写我们自己的代码,用于处理相应的系统事件和消息。 需要注意的是,VB HookAPI需要一定的编程经验和对Windows操作系统的了解。此外,使用钩子技术需要谨慎,因为不正确的使用可能导致系统不稳定或产生安全风险。在使用VB HookAPI时,我们需要确保只拦截需要处理的事件和消息,并在不需要时及时卸载钩子,以确保系统的稳定和安全。 总的来说,VB HookAPI是一种强大的编程技术,可以让我们在Visual Basic中实现对系统事件和消息的监视和控制。通过合理运用它,我们可以实现各种功能和效果,为我们的应用程序增添更多的灵活性和个性化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值