XP下的进程静音技术(遍历进程,遍历输入模块,遍历输入函数,找到函数并HOOK) good

很多浏览器有这种功能,实现原理都是一样。发声源基本都来自Flash,比如Flash游戏啦,视频播放器啦等等

而Flash的发声都是通过winmm.dll::waveOutWrite函数来完成,所以,我们只要能“接管”这个函数就行了

下面的代码是以前写的一个模块,针对Flash的静音,代码写的比较粗糙 ^_^

注意,下面的代码仅仅针对Flash模块进行IAT Hook

XP测试通过

  1. unit FlashMute;
  2. interface
  3. uses
  4. Windows, SysUtils, Classes, StrUtils, TlHelp32, MMSystem;
  5. type
  6. TFlashMute = class
  7. private
  8. class var Flag: Boolean;
  9. public
  10. class function Modify_waveOutWrite: Boolean;
  11. class procedure Enable;
  12. class procedure Disable;
  13. end;
  14. implementation
  15. function MywaveOutWrite(hWaveOut: HWAVEOUT; lpWaveOutHdr: PWaveHdr; uSize: UINT): MMRESULT; stdcall;
  16. begin
  17. if TFlashMute.Flag then
  18. ZeroMemory(lpWaveOutHdr.lpData, lpWaveOutHdr.dwBufferLength);
  19. Result := waveOutWrite(hWaveOut, lpWaveOutHdr, uSize);
  20. end;
  21. { TFlashMute }
  22. class procedure TFlashMute.Disable;
  23. begin
  24. TFlashMute.Flag := True;
  25. end;
  26. class procedure TFlashMute.Enable;
  27. begin
  28. TFlashMute.Flag := False;
  29. end;
  30. class function TFlashMute.Modify_waveOutWrite: Boolean;
  31. var
  32. hSnapshot: THandle;
  33. ME32: TModuleEntry32;
  34. Found: Boolean;
  35. BaseAddr: DWORD;
  36. DosHeader: PImageDosHeader;
  37. NtHeader: PImageNtHeaders;
  38. ImportDesc: PImageImportDescriptor;
  39. ITD, ITD2: PImageThunkData;
  40. IIBN: PImageImportByName;
  41. mbi: TMemoryBasicInformation;
  42. begin
  43. Result := False;
  44. // 枚举当前进程模块列表,找到Flash?.ocx
  45. hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId);
  46. if hSnapshot <> INVALID_HANDLE_VALUE then
  47. begin
  48. ME32.dwSize := SizeOf(TModuleEntry32);
  49. Found := Module32First(hSnapshot, ME32);
  50. while Found do
  51. begin
  52. if ContainsText(ME32.szModule, 'Flash') then
  53. begin
  54. if SameText(ExtractFileExt(ME32.szModule), '.ocx') then
  55. begin
  56. BaseAddr := DWORD(@ME32.modBaseAddr^);
  57. DosHeader := @ME32.modBaseAddr^;
  58. NtHeader := Ptr(BaseAddr + DosHeader^._lfanew);
  59. // 遍历输入模块
  60. ImportDesc := Ptr(BaseAddr + NtHeader.OptionalHeader.DataDirectory[1].VirtualAddress);
  61. while ImportDesc^.Name <> 0 do
  62. begin
  63. ITD := PImageThunkData(BaseAddr + ImportDesc^.OriginalFirstThunk);    // 指向函数名称RVA或函数序号
  64. ITD2 := PImageThunkData(BaseAddr + ImportDesc^.FirstThunk);           // 指向函数地址
  65. // 遍历输入函数
  66. while ITD^.AddressOfData <> 0 do
  67. begin
  68. // 按函数名方式导入的函数
  69. if ITD^.AddressOfData and IMAGE_ORDINAL_FLAG <> IMAGE_ORDINAL_FLAG then
  70. begin
  71. IIBN := PImageImportByName(BaseAddr + ITD^.AddressOfData);
  72. // 找出 winmm.dll::waveOutWrite
  73. if SameText(string(PAnsiChar(@IIBN^.Name[0])), 'waveOutWrite') then
  74. begin
  75. if VirtualProtect(@ITD2^._Function, SizeOf(DWORD), PAGE_EXECUTE_READWRITE, @mbi.Protect) then
  76. begin
  77. ITD2^._Function := DWORD(@MywaveOutWrite);
  78. Result := True;
  79. end;
  80. Break;
  81. end;
  82. end;
  83. Inc(ITD);
  84. Inc(ITD2);
  85. end;
  86. if Result then
  87. Break;
  88. Inc(ImportDesc);
  89. end;
  90. end;
  91. end;
  92. if Result then
  93. Break;
  94. Found := Module32Next(hSnapshot, ME32);
  95. end;
  96. CloseHandle(hSnapshot);
  97. end;
  98. end;

http://blog.csdn.net/aqtata/article/details/8112092

上一篇:mysql 异常Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock 解决


下一篇:bootstrap_栅格系统_响应式工具_源码分析