找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 9773|回复: 2

[交流] 【转载】纯VB HOOK API

[复制链接]

8

主题

149

回帖

2

精华

钻石会员

积分
3407
发表于 2012-7-2 23:46:19 | 显示全部楼层 |阅读模式
本帖最后由 LittlePig 于 2012-7-2 23:56 编辑

原文标题:VB变态HOOK API也疯狂
本文于 2007-12-7 首次于http://hi.baidu.com/cxwr 发表 原创作者:菜新


之所以起这个名字,其主要原因是想证明用VB也可以正常稳定的实现HOOK API功能。貌似关于VB实现HOOK API方面的文章chenhui530有写过,说实话,给我的感觉很一般,最让我大跌眼镜的是,所生成的代码的方式竟然是P-CODE??难怪文章最后说只能成功用于VB程序,OK,当看到这时我已没心情继续看下去了。算了,还是来说说我自己的吧,只有自己拿得出真才实料才会让人信服,关于该文章的所有技术实现都是纯VB代码,不加任何外部DLL文件实现。在该文章中你将学会以下知识:

1,HOOK API函数
2,远程注入代码与远程注入DLL
3,学会OD分析调试自己的代码
4,学会自己制作tlb类库文件
5,其它细节方面的知识等等。。

首先让我们了解下HOOK API的原理,HOOK API所实现的原理无非就是通过更改API代码默认运行轨道,将所运行的代码指向他处(这里一般为我们自己的地址),通过如此达到HOOK API的功能。如果用汇编的方式表达的话我想可能更明确,如下:
Mov eax, 转移地址
Jmp eax

HOOK 代码即是如此而已,首先是把我们自己处理的函数地址放在eax寄存器中,然后通过jmp(汇编跳转指令)eax 跳转到eax寄存器中的函数地址处。这时当程序中执行某个被HOOK的函数时,该函数会自动跳转到 eax 地址,也就这样,整个HOOK工作完成了。

OK,明白了原理之后我们还有其它技术方面的问题需要解决,当然在VB中这些问题必须解决,首先是HOOK API问题,在其它语言中如Delphi或ASM可以直接写个DLL HOOK,通过SetWindowsHookEx把该DLL注入到带有消息处理的进程中去,一般 用SetWindowsHookEx注入DLL的方式对于普通的应用程序还行,但对于如系统服务或控制台内进程则无效,所以这时我们需要通过CreateRemoteThread(创建远程线程)API去解决。当然在使用这些方法的前提是必须有DLL。

我们都知道VB压根就实现不了啥标准DLL,当然说到这里可能会有人跟我争辩,我觉得没必要,争来争去结果都一样,VB根本就实现不了啥标准DLL,可网上硬是有些人把什么什么“用VB做输入函数DLL”一文来强加之理,说这就是“标准DLL”,唉,除了汗还是汗,老兄你先把VB下的DLL运行库msvbvm60.dll解决了再来跟我说吧,你呐!~~~

所以,VB用DLL来实现基本上是不可能了,现在唯一一种方法就是利用远程线程注入EXE代码,然后通过注入的代码去解决它,该方法首先要解决的问题是VB的默认运行库,你我都知道VB运行是需要运行库的,别自欺欺人了兄弟!~咱还是老老实实用远程注入DLL的方法去解决它,OK,运行库问题解决了,那么远程注入代码呢?Why??不容易实现?啥?你实现了?说你实现了我又想到了 chenhui530 中的那种对注入代码的处理方式,基本上除了可以正常用于在VB生成的自家兄弟EXE程序以外,插入其它进程基本上会给你一个下图效果:
174036tjalz4a5r5ilailj.jpg

但是这个问题必须要解决,否则就不存在用远程注入代码的方式解决方式了。

当然自己的在用VB编写远程注入代码的时候,也出现了这种现象,不过通过OD反汇编跟踪,我发现罪魁祸首的竟然是 __vbaSetSystemError 的调用。如下图:
174041yls5knk4n6ass1bq.jpg

上面反汇编代码所对应的VB代码如下:
  1. Public Function MyShowTip() As Long
  2.     MessageBeep 0
  3. End Function
复制代码
上面代码为注入到目标进程中的代码,可见VB的细心照顾竟然是引发“犯罪”的导炎索。算了,我没啥好说了。目前的情形下,我们要解决VB代码默认对 __vbaSetSystemError 的调用,通过发现,只有使用 tlb 类型库才能很好并且很稳定的解决这个问题。这里涉及类型库的编写,具体语法请参考MSDN。

首先我们写一个简单的 MessageBox 类型库试试:
[
uuid(12345678-1234-1234-1234-123456789ABC),
helpstring("my api library"),
lcid(0x0),
version(1.0)
]

library MyAPIs
{
importlib("stdole2.tlb");

typedef [public] long HWND;
    typedef [public] long DWORD;
    typedef [public] long UINT;
    typedef [public] long WPARAM;
    typedef [public] long LPARAM;
    typedef [public] long HANDLE;
   
[dllname("user32")]
module User32
{
   [entry("MessageBoxA")] long MessageBox ([in] HANDLE hWnd, [in] LPSTR lpText,
   [in] LPSTR lpCaption, [in] UINT uType);
};
};

保存为myapi.odl,这里生成tlb文件需要借助VC++来完成,通过VC++的Bin目录中的MKTYPLIB.EXE程序生成,OK,完成以上操作以后我们再回到VB中。

然后在VB工程菜单,引用,选择刚刚输出的 myapi.tlb 文件,注意如果你已经声明了 MessageBox 函数请删除掉。注意这里引用了该类型库以后我们的代码中将不需要再声明MessageBox API。接着我把上面的注入代码改成以下:
  1. Public Function MyShowTip() As Long
  2.     MessageBox 0, "显示一个消息", "消息", 0
  3. End Function
复制代码
然后OD反汇编如下:
174038wu255m5bv56wwn5n.jpg

OK,__vbaSetSystemError 被我们彻底的干掉了。通过上面反汇编的VB代码我们可以看出,使用类型库可以直接定位并调用API函数,免去了VB中默认一些烦杂的操作,可见类型库还是值得提倡的。看看下图将会明白,咱们不再是通过 DllFunctionCall 去调用API了。
174043nrf5mm511n8x5f17.jpg

好了,现在就剩下最后一个问题,就是远程注入代码的重定位问题,这个问题最为关键,我想如果不解决此问题,上面所有的实现原理也就没啥必要了。

据我的观察,VB或Delphi、ASM、VC++默认的基址为0x400000 处,当然也可能其它编程语言所生成的不是这个基址,但是一般的应用程序基址普遍是在0x10000000以下,这里可能某些网友会问为什么我突然间扯到这里来了,不是我为什么要扯到这里,是因为这里我们必须要了解,因为一旦我们设置好了程序的基址,所有代码的重定位工作也就让编译器自然为我们做好了。所以我们需要通过基址来重定位我们的代码。

VB默认不支持EXE的/BASE基址设置功能,所以这里需要我们自己动手去解决它(朋友!养成多动动手的习惯吧!!!),VB程序的编译是靠C2.EXE和LINK.EXE两个东东来完成的,所以我们要从半路中截取它们的命令行参数,并修改,以达到我们需要的效果,这里我写了个拦截代码,如下:
  1. Public Sub Main()
  2.     Dim sBuf As String
  3.     Dim szBase As String
  4.    
  5.     If MsgBox("是否设置EXE基地址?", vbYesNo + 64, "基址") = vbNo Then
  6.         Shell "Link2.exe " & Command
  7.     Else
  8.    
  9.         szBase = InputBox("请输入需要设置的基地址,不用输入 0x", "基址", "400000")
  10.         If Trim(szBase) = vbNullString Then
  11.             szBase = "/BASE:0x400000"
  12.         Else
  13.             szBase = "/BASE:0x" & szBase
  14.         End If
  15.         
  16.         sBuf = Replace(Command, "/BASE:0x400000", szBase)
  17.         Shell "link2.exe " & sBuf
  18.     End If
  19. End Sub
复制代码
编译为EXE,然后复制到VB98目录,修改目录下的LINK.exe为LINK2.exe,然后修改刚刚编译好的EXE为LINK.exe,OK!当编译EXE时会自动弹出以下对话框:
174044yqy7ooy2m71hzw28.jpg

然后点击“是”,接着再弹出以下对话框:
174045q41meh2byym44vdb.jpg

上面这个东西有下载,请到 http://cxwr.ys168.com/的Source Code 目录下载或者参见下面的附件。

输入相应的基址即可,默认我们输入 0x14000000,只要高出 0x10000000 就行了,当然你也可以设置为0x20000000、0x30000000等等等,只要你愿意,就随你吧(注意不能超过 0x80000000)。下图为 PEiD查看的结果:
1740422239ll9kgm29h92z.jpg

OK,所有的操作原理都明白以后,剩下的就是正式写注入和HOOK代码了。

首先HOOK API时我前面说过,默认的注入代码方法不可取,我们需要一个类型库,这样所注入的代码操作会尽可能的“远离”msvbvm60.dll,记住,要想让你的VB代码能在其它进程中撒欢,那么就得少用些运行库中的函数,最好能全部用API解决,有时VB中默认添加的一个小小的转换函数就会让整个进程崩溃,要不然为啥VB的本机代码不支持多线程?现在我们只需要把HOOK API常用的几个API做成类型库即可。下面是需要用到的几个API函数:
ReadProcessMemory、WriteProcessMemory、GetModuleHandle、GetProcAddress、GetCurrentProcess、CopyMemory

(问:不会吧?HOOK API就这几个API就可以搞定? 答:是的)OK,以下为类型库ODL代码:
[
uuid(12345678-1234-1234-1234-123456789ABC),
helpstring("my api library"),
lcid(0x0),
version(1.0)
]

library MyAPIs
{
importlib("stdole2.tlb");

typedef [public] long HWND;
    typedef [public] long DWORD;
    typedef [public] long UINT;
    typedef [public] long WPARAM;
    typedef [public] long LPARAM;
    typedef [public] long HANDLE;
   
[dllname("kernel32")]
module kernel32
{
   [entry("WriteProcessMemory")] long WriteProcessMemory ([in] HANDLE hProcess,
   [in] void* lpBaseAddress, [in] void* lpBuffer, [in] DWORD nSize, [in] DWORD* lpNumberOfBytesWritten);
   [entry("ReadProcessMemory")] long ReadProcessMemory ([in] HANDLE hProcess,
   [in] void* lpBaseAddress, [in] void* lpBuffer, [in] DWORD nSize, [in] DWORD* lpNumberOfBytesWritten);
   [entry("GetCurrentProcess")] HANDLE GetCurrentProcess();
   [entry("RtlMoveMemory")] void CopyMemory([in] void* pDest, [in] void*
       pSrc, [in] long ByteLen);
   [entry("GetModuleHandleA")] long GetModuleHandle ([in] LPSTR lpModuleName);
   [entry("GetProcAddress")] long GetProcAddress ([in] DWORD hModule, [in] LPSTR lpProcName);
};

[dllname("user32")]
module User32
{
   [entry("MessageBoxA")] long MessageBox ([in] HANDLE hWnd, [in] LPSTR lpText,
   [in] LPSTR lpCaption, [in] UINT uType);
   [entry("MessageBoxW")] long MessageBoxW ([in] HANDLE hWnd, [in] LPWSTR lpText,
   [in] LPWSTR lpCaption, [in] UINT uType);
};
};

OK现在,上面保存名为 odl 的扩展名文件,然后用MKTYPLIB.EXE生成一下就OK了。。

该文件请到 http://cxwr.ys168.com/ 中下载或者参考下面的附件。

剩下的就是写代码了,不说多了,直接上代码,该代码为通过演示HOOK MessageBoxA API函数,让你明白在VB中使用纯代码HOOK API是如何实现的。如果你想HOOK NtOpenProcess 等等API也是如此。

该注入与HOOK程序中只用到了两个模块,如下:

modMain.bas 中的代码:
  1. Option Explicit

  2. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
  3. Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
  4. 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
  5. Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
  6. '上面这些是我们自己用到的,因为我们已经引用了类型库,所以默认声明为 Private 方式,
  7. '这样做的好处是不影响 modHOOK 模块中的相同API使用

  8. Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
  9. Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
  10. Public Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
  11. Public Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
  12. Public Declare Function CreateRemoteThread Lib "kernel32" (ByVal hProcess As Long, lpThreadAttributes As Long, ByVal dwStackSize As Long, lpStartAddress As Long, lpParameter As Any, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
  13. Public Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

  14. Public Const MEM_RELEASE = &H8000
  15. Public Const MEM_COMMIT = &H1000
  16. Public Const MEM_RESERVE = &H2000
  17. Public Const MEM_DECOMMIT = &H4000
  18. Public Const PAGE_EXECUTE_READWRITE = &H40

  19. Public Const SYNCHRONIZE = &H100000
  20. Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
  21. Public Const PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)

  22. Public Const INFINITE = &HFFFFFFFF

  23. '以下全部从Delphi中翻译
  24. Public Type IMAGE_DOS_HEADER
  25.     e_magic As Integer
  26.     e_cblp As Integer
  27.     e_cp As Integer
  28.     e_crlc As Integer
  29.     e_cparhdr As Integer
  30.     e_minalloc As Integer
  31.     e_maxalloc As Integer
  32.     e_ss As Integer
  33.     e_sp As Integer
  34.     e_csum As Integer
  35.     e_ip As Integer
  36.     e_cs As Integer
  37.     e_lfarlc As Integer
  38.     e_ovno As Integer
  39.     e_res(3) As Integer
  40.     e_oemid As Integer
  41.     e_oeminfo As Integer
  42.     e_res2(9) As Integer
  43.     e_lfanew As Long
  44. End Type

  45. Public Type IMAGE_FILE_HEADER
  46.     Machine As Integer
  47.     NumberOfSections As Integer
  48.     TimeDateStamp As Long
  49.     PointerToSymbolTable As Long
  50.     NumberOfSymbols As Long
  51.     SizeOfOptionalHeader As Integer
  52.     Characteristics As Integer
  53. End Type

  54. Public Type IMAGE_DATA_DIRECTORY
  55.     VirtualAddress As Long
  56.     Size As Long
  57. End Type
  58.    
  59. Public Type IMAGE_OPTIONAL_HEADER
  60.     Magic As Integer
  61.     MajorLinkerVersion As Byte
  62.     MinorLinkerVersion As Byte
  63.     SizeOfCode As Long
  64.     SizeOfInitializedData As Long
  65.     SizeOfUninitializedData As Long
  66.     AddressOfEntryPoint As Long
  67.     BaseOfCode As Long
  68.     BaseOfData As Long
  69.     ImageBase As Long
  70.     SectionAlignment As Long
  71.     FileAlignment As Long
  72.     MajorOperatingSystemVersion As Integer
  73.     MinorOperatingSystemVersion As Integer
  74.     MajorImageVersion As Integer
  75.     MinorImageVersion As Integer
  76.     MajorSubsystemVersion As Integer
  77.     MinorSubsystemVersion As Integer
  78.     Win32VersionValue As Long
  79.     SizeOfImage As Long
  80.     SizeOfHeaders As Long
  81.     CheckSum As Long
  82.     Subsystem As Integer
  83.     DllCharacteristics As Integer
  84.     SizeOfStackReserve As Long
  85.     SizeOfStackCommit As Long
  86.     SizeOfHeapReserve As Long
  87.     SizeOfHeapCommit As Long
  88.     LoaderFlags As Long
  89.     NumberOfRvaAndSizes As Long
  90.     DataDirectory(15) As IMAGE_DATA_DIRECTORY
  91. End Type
  92.    
  93. Public Type IMAGE_NT_HEADERS
  94.     Signature As Long
  95.     FileHeader As IMAGE_FILE_HEADER
  96.     OptionalHeader As IMAGE_OPTIONAL_HEADER
  97. End Type


  98. Public Sub Main()
  99.     Dim Pid As Long
  100.     Dim sBuf As String
  101.    
  102.     sBuf = InputBox("PID", , 0)
  103.     Pid = CLng(sBuf)
  104.    
  105.     If InjectMsvbvm6_dll(Pid) Then
  106.         MsgBox "插入运行库OK"
  107.     End If
  108.    
  109.     If InjectExe(Pid) Then
  110.         MsgBox "已插入代码"
  111.     End If

  112. End Sub

  113. '///////////////////////////////////////////////////////
  114. '///
  115. '///说明: 插入运行库代码
  116. '///参数: Pid=进程PID
  117. '///返回: 成功True,否则False
  118. '///
  119. '///////////////////////////////////////////////////////
  120. Public Function InjectMsvbvm6_dll(ByVal Pid As Long) As Boolean
  121.     Dim hProcess As Long, hThread As Long
  122.     Dim szDllPath As String
  123.     Dim cbDllPath As Long
  124.     Dim pBaseAddr As Long
  125.     Dim pFuncAddr As Long
  126.     Dim hMod As Long
  127.    
  128.     InjectMsvbvm6_dll = False
  129.    
  130.     hMod = GetModuleHandle("kernel32.dll")
  131.     pFuncAddr = GetProcAddress(hMod, "LoadLibraryA")
  132.    
  133.     hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, Pid)
  134.     If hProcess = 0 Then GoTo Err
  135.    
  136.     szDllPath = "c:\windows\system32\msvbvm60.dll"
  137.     cbDllPath = Len(szDllPath) * 2 + 1
  138.    
  139.     pBaseAddr = VirtualAllocEx(hProcess, ByVal 0&, cbDllPath, MEM_COMMIT Or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
  140.     If pBaseAddr = 0 Then GoTo Err
  141.    
  142.     If WriteProcessMemory(hProcess, ByVal pBaseAddr, ByVal szDllPath, cbDllPath, 0) = 0 Then GoTo Err
  143.    
  144.     hThread = CreateRemoteThread(hProcess, ByVal 0&, 0, ByVal pFuncAddr, ByVal pBaseAddr, 0, 0)
  145.     If hThread = 0 Then GoTo Err
  146.    
  147.     WaitForSingleObject hThread, INFINITE
  148.     CloseHandle hThread
  149.    
  150.     InjectMsvbvm6_dll = True
  151.    
  152. Err:
  153.     If pBaseAddr <> 0 Then VirtualFreeEx hProcess, ByVal pBaseAddr, 0, MEM_RELEASE
  154.     If hProcess <> 0 Then CloseHandle hProcess
  155. End Function


  156. '///////////////////////////////////////////////////////
  157. '///
  158. '///说明: 插入代码
  159. '///参数: Pid=进程PID
  160. '///返回: 成功True,否则False
  161. '///
  162. '///////////////////////////////////////////////////////
  163. Public Function InjectExe(ByVal Pid As Long) As Boolean
  164.     Dim hMod As Long
  165.     Dim stIDH As IMAGE_DOS_HEADER
  166.     Dim stINH As IMAGE_NT_HEADERS
  167.     Dim cbImage As Long
  168.     Dim hProcess As Long, hThread As Long
  169.     Dim pBaseAddr As Long
  170.     Dim pFuncAddr As Long
  171.    
  172.     InjectExe = False
  173.    
  174.     hMod = GetModuleHandle(vbNullString)
  175.    
  176.     '得到相应的偏移值结构
  177.     CopyMemory stIDH, ByVal hMod, Len(stIDH)
  178.     CopyMemory stINH, ByVal (hMod + stIDH.e_lfanew), Len(stINH)
  179.     cbImage = stINH.OptionalHeader.SizeOfImage
  180.     If cbImage = 0 Then GoTo Err
  181.    
  182.     hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, Pid)
  183.     If hProcess = 0 Then GoTo Err
  184.    
  185.     VirtualFreeEx hProcess, hMod, 0, MEM_RELEASE
  186.     pBaseAddr = VirtualAllocEx(hProcess, ByVal hMod, cbImage, MEM_COMMIT Or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
  187.     If pBaseAddr = 0 Then GoTo Err
  188.         
  189.     If WriteProcessMemory(hProcess, ByVal pBaseAddr, ByVal hMod, cbImage, 0) = 0 Then GoTo Err
  190.    
  191.     '现在处理该是处理我们自己的函数地址的时候了,至于为什么会先在这里把函数地址计算好,具
  192.     '体可以看 modHook 中的说明
  193.     '
  194.     Dim pFAddr As Long
  195.    
  196.     Init '先初始以便获取函数地址
  197.    
  198.     pFAddr = VirtualAllocEx(hProcess, ByVal 0&, 4, MEM_COMMIT Or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
  199.     If pFAddr = 0 Then GoTo Err
  200.    
  201.     '然后把咱们的地址传进去
  202.     If WriteProcessMemory(hProcess, ByVal pFAddr, NewAddr(1), 4, 0) = 0 Then GoTo Err
  203.    
  204.    
  205.     pFuncAddr = GetFuncAddr(AddressOf Hook)
  206.     hThread = CreateRemoteThread(hProcess, ByVal 0&, 0, ByVal pFuncAddr, ByVal pFAddr, 0, 0)
  207.     If hThread = 0 Then GoTo Err
  208.    
  209.     WaitForSingleObject hThread, INFINITE
  210.     CloseHandle hThread
  211.    
  212.     InjectExe = True
  213. Err:

  214.     'If pBaseAddr <> 0 Then VirtualFreeEx hProcess, ByVal pBaseAddr, 0, MEM_RELEASE
  215.     If hProcess <> 0 Then CloseHandle hProcess
  216.    
  217. End Function

  218. Private Function Init() As Long
  219.     Dim pFuncAddr As Long

  220.     pFuncAddr = GetFuncAddr(AddressOf NewMessageBox)
  221.    
  222.     '保存该地址,一会要注入进去的
  223.     CopyMemory NewAddr(1), pFuncAddr, 4
  224. End Function

  225. Private Function GetFuncAddr(ByVal func As Long) As Long
  226.     GetFuncAddr = func
  227. End Function

  228. 然后 modHook.bas 中的代码:

  229. Option Explicit

  230. Public NewAddr(7) As Byte

  231. Public Function Hook(ByVal pFAddr As Long) As Long
  232.     Dim hMod As Long
  233.     Dim pBaseAddr As Long
  234.    
  235.    
  236.    
  237.     hMod = GetModuleHandle("user32.dll")
  238.     pBaseAddr = GetProcAddress(hMod, "MessageBoxA")
  239.    
  240.     '该步骤下普遍会崩溃...我实现是米得办法啊..用OD跟踪发现读取内存有误,唉..VB就是VB..没办法
  241.     '这里有点让我抓狂,曾想过用硬编码的方式...汗!~~ 我实在是米有办法啊!!~~~
  242.    
  243.     'Dim pFuncAddr As Long
  244. '    pFuncAddr = GetFuncAddr(AddressOf NewMessageBox)
  245. '    CopyMemory NewAddr(1), pFuncAddr, 4


  246.     '以下部分为机器码生成
  247.     '机器码意思为:
  248.     '
  249.     'mov eax, 我们的地址
  250.     'jmp eax
  251.     '
  252.     NewAddr(0) = &HB8
  253.     NewAddr(5) = &HFF
  254.     NewAddr(6) = &HE0
  255.     NewAddr(7) = &H0
  256.    
  257.     '最后我想到一个折中的办法,就是先让注入程序帮我们把地址算好,然后我们直接调用即可.
  258.     ReadProcessMemory GetCurrentProcess, ByVal pFAddr, NewAddr(1), 4, 0
  259.    
  260.     MessageBox 0, "被我给HOOK了...", "已HOOK", 32
  261.         
  262.     '这一步写进去以后基本上就成功OK了..
  263.     WriteProcessMemory GetCurrentProcess, ByVal pBaseAddr, NewAddr(0), 8, 0
  264. End Function

  265. Public Function NewMessageBox(ByVal hWnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long

  266.     '默认HOOK的是MessageBoxA函数,所以我们用 MessageBoxW 给我们弹出消息
  267.     '这里没有写还原函数,其实这个都很好解决,我们在用 WriteProcessMemory写入HOOK代码时可以还通过
  268.     'ReadProcessMemory读取原始代码,当需要恢复时再通过 WriteProcessMemory写回去就OK了..
  269.    
  270.     MessageBoxW 0, "哈哈...被我们给HOOK了", "嘿嘿~~啦啦啦..", 16

  271.     NewMessageBox = 1
  272. End Function
复制代码
OK,上面所有代码及测试和Odl 文件都可在 http://cxwr.ys168.com/ 中下载。现在来看看测试效果,我只用了VB与Delphi写了一个测试程序,如下图:
首先是Delphi 的HOOK前和HOOK后,至于进程PID的话可以直接打开进程管理器找:
174038lsspeiilsus8idis.jpg

HOOK后如下:
174039x24zmo4x444xnxp7.jpg

还有一个VB测试结果,如下:
174031zslzu4f85q9ful2p.jpg

HOOK 后:
17403093kutjcgaz7jrtay.jpg

至于VC++和ASM我想应该也没问题。如果大家有兴趣可以自己试试。

注:以上在Windows XP SP2 环境下测试通过。

结束语:

最近都在忙着学内核ring0,也不知什么原因,这些天突然心血来潮要用VB来搞HOOK API,其实如果用VB借助其它语言编写的DLL来完成此功能的话我想应该非常容易,如果用纯VB来实现的话如果没有一定的汇编和OD调试基础,基本上很难用VB实现。附一张图大家看看就知道了,如下:
17403555doqoj0j7jj7df9.jpg

呵。。大家表笑,事实就是如此,上图为调试VB HOOK 的崩溃信息,说真的我都不知道我是怎么坚持下来的。就我个人认为,用VB纯代码写HOOK API是很变态的事情,至少我是这么认为的。好了,不说多了,该文章也算是学VB一年多来一个好的结尾吧,我这样说并不是说我就放弃VB了,只是我觉得用VB写Win32系统程序是一件很烦的事情,光声明这些API都不知要花多少时间,除此之外当然还有其它原因(当然除写数据库外)。所以以后大部分程序我可能不会采用VB来写,而是用Delphi、VC++和ASM等来完成。不要问我为什么,你我心里都明白!

最后我想说的是,VB是我人生中的第一个语言,因为拥有它,我才有今天,所以做人不得忘本!关于VB界内的信息我会一直关注的!另外就是复制转帖问题,请一定要保留文章出处与作者信息。谢谢合作。

注:该文中的所有资料或代码都可在 http://cxwr.ys168.com/ 中下载。


文章附件下载地址:
下载地址1(劳资的SkyDrive)
下载地址2(作者的永硕网盘)

8

主题

149

回帖

2

精华

钻石会员

积分
3407
 楼主| 发表于 2012-7-2 23:46:52 | 显示全部楼层
惯例,沙发不留~

0

主题

3

回帖

0

精华

初来乍到

积分
28
发表于 2012-8-22 22:53:36 | 显示全部楼层
真的是純VB = =?
還用VC弄個庫文件
不過這篇在網路上也看過的
具體來說是不錯..支持下
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表