【Delphi】XP下的进程静音技术

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

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

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

 

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

XP测试通过

unit FlashMute;

interface

uses
  Windows, SysUtils, Classes, StrUtils, TlHelp32, MMSystem;

type

  TFlashMute = class
  private
    class var Flag: Boolean;

  public
    class function Modify_waveOutWrite: Boolean;
    class procedure Enable;
    class procedure Disable;

  end;

implementation

function MywaveOutWrite(hWaveOut: HWAVEOUT; lpWaveOutHdr: PWaveHdr; uSize: UINT): MMRESULT; stdcall;
begin
  if TFlashMute.Flag then
    ZeroMemory(lpWaveOutHdr.lpData, lpWaveOutHdr.dwBufferLength);
  Result := waveOutWrite(hWaveOut, lpWaveOutHdr, uSize);
end;

{ TFlashMute }

class procedure TFlashMute.Disable;
begin
  TFlashMute.Flag := True;
end;

class procedure TFlashMute.Enable;
begin
  TFlashMute.Flag := False;
end;

class function TFlashMute.Modify_waveOutWrite: Boolean;
var
  hSnapshot: THandle;
  ME32: TModuleEntry32;
  Found: Boolean;
  BaseAddr: DWORD;
  DosHeader: PImageDosHeader;
  NtHeader: PImageNtHeaders;
  ImportDesc: PImageImportDescriptor;
  ITD, ITD2: PImageThunkData;
  IIBN: PImageImportByName;
  mbi: TMemoryBasicInformation;
begin
  Result := False;
  // 枚举当前进程模块列表,找到Flash?.ocx
  hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId);
  if hSnapshot <> INVALID_HANDLE_VALUE then
  begin
    ME32.dwSize := SizeOf(TModuleEntry32);
    Found := Module32First(hSnapshot, ME32);
    while Found do
    begin
      if ContainsText(ME32.szModule, 'Flash') then
      begin
        if SameText(ExtractFileExt(ME32.szModule), '.ocx') then
        begin
          BaseAddr := DWORD(@ME32.modBaseAddr^);
          DosHeader := @ME32.modBaseAddr^;
          NtHeader := Ptr(BaseAddr + DosHeader^._lfanew);
          // 遍历输入模块
          ImportDesc := Ptr(BaseAddr + NtHeader.OptionalHeader.DataDirectory[1].VirtualAddress);
          while ImportDesc^.Name <> 0 do
          begin
            ITD := PImageThunkData(BaseAddr + ImportDesc^.OriginalFirstThunk);    // 指向函数名称RVA或函数序号
            ITD2 := PImageThunkData(BaseAddr + ImportDesc^.FirstThunk);           // 指向函数地址
            // 遍历输入函数
            while ITD^.AddressOfData <> 0 do
            begin
              // 按函数名方式导入的函数
              if ITD^.AddressOfData and IMAGE_ORDINAL_FLAG <> IMAGE_ORDINAL_FLAG then
              begin
                IIBN := PImageImportByName(BaseAddr + ITD^.AddressOfData);
                // 找出 winmm.dll::waveOutWrite
                if SameText(string(PAnsiChar(@IIBN^.Name[0])), 'waveOutWrite') then
                begin
                  if VirtualProtect(@ITD2^._Function, SizeOf(DWORD), PAGE_EXECUTE_READWRITE, @mbi.Protect) then
                  begin
                    ITD2^._Function := DWORD(@MywaveOutWrite);
                    Result := True;
                  end;
                  Break;
                end;
              end;
              Inc(ITD);
              Inc(ITD2);
            end;
            if Result then
              Break;
            Inc(ImportDesc);
          end;
        end;
      end;
      if Result then
        Break;
      Found := Module32Next(hSnapshot, ME32);
    end;
    CloseHandle(hSnapshot);
  end;
end;


 

你可能感兴趣的:(【Delphi】XP下的进程静音技术)