вторник, 26 апреля 2016 г.

Перехват с помощью debug api

Ясен хуй че на debugapi далеко не улетишь, но похуй…
С помощью дебугг апи можно обрабатывать события там исключения хуету всякую вобщем. Можно вот например показать рекламу в месаджбоксе.
Со стороны выглядит так:
Подключаемся к процессу. Создаем событие. Получаем евошнюю структуру через WaitForDebugEvent. Обрабатываем. Продолжаем ожидание события через ContinueDebugEvent;
Понять чепочеинахуя можно по этим линкам:раз, два, три
Ну а так по шагам:
Прочитать хидоры фэйлинга

hFile:=OpenFile(путь,OFS,OF_READ);
SetFilePointer(hFile,$3C,0,FILE_BEGIN);
ReadFile(hFile,tmp,4,tmpRW,0);
SetFilePointer(hFile,tmp,0,FILE_BEGIN);
ReadFile(hFile,IMAGENTHEADER,SizeOf(IMAGENTHEADER),tmpRW,0);
CloseHandle(hFile);
Создать процесс

ZeroMemory(@SI,sizeof(SI));ZeroMemory(@PI,SizeOf(PI));
CreateProcess(path, 0, 0, 0, FALSE,DEBUG_ONLY_THIS_PROCESS + DEBUG_PROCESS, 0,0, SI, PI);
Сделать событие вызывающее исключение на ентрипоинте посредством int3:


ReadProcessMemory(PI.hProcess,Pointer(EntryPoint),@EPByte,1,tmpRW);
WriteProcessMemory(PI.hProcess,Pointer(EntryPoint),@int3,1,tmpRW);
Организовать стандартный дебугг луп

While true do 
 Begin
  case DebugEvent.dwDebugEventCode of
   EXCEPTION_DEBUG_EVENT
  итд …
Кароче бля, вот чтоб перехватить функцию нужно поставить брейкпойнт(в данном случае хардварный) на адрес функции. Хардварный занчит через регистры DR. Все как в дебуггере, ага. И с помощью GetThreadContext распарсерить аргументы через ригистер esp, который бля указывает на бля верх стэка, те по формуле esp+4*Arg n.
Тута идем в точку в хода

EXCEPTION_DEBUG_EVENT:
if DebugEvent.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT then begin
  if CTX.Eip = EntryPoint+1 then begin
    Dec(CTX.Eip);
    WriteProcessMemory(PI.hProcess,Pointer(EntryPoint),@EPByte,1,tmpRW);
    CTX.Dr0 := pProc;
    CTX.Dr7 := $01;
    SetThreadContext(PI.hThread,CTX);
    ContinueDebugEvent(PI.dwProcessId, PI.dwThreadID,DBG_CONTINUE);
   end;
Тута парсим аргументы
EXCEPTION_DEBUG_EVENT:
if CTX.Eip = pProc then begin
  ZeroMemory(@argStr,Length(argStr));
  ReadProcessMemory(PI.hProcess,Pointer(CTX.Esp),Pointer(@pRet),4,tmpRW);
  ReadProcessMemory(PI.hProcess,Pointer(CTX.Esp+4*3),Pointer(@pArg),4,tmpRW);
  ReadProcessMemory(PI.hProcess,Pointer(pArg),PChar(@argStr[0]),256,tmpRW);
  WriteLn('Title:'+argStr);
  ZeroMemory(@argStr,Length(argStr));
  ReadProcessMemory(PI.hProcess,Pointer(CTX.Esp+4*2),Pointer(@pArg),4,tmpRW);
  ReadProcessMemory(PI.hProcess,Pointer(pArg),PChar(@argStr[0]),256,tmpRW);
  WriteLn('Text:'+argStr);
  WriteLn('===============');
Подменить там ченить.

ADLen:=StrLen(argStr);
for i := 1 to Length(AD) do begin
  argStr[ADLen-1+i]:=AnsiChar(AD[i]);
end;
ADLen:=Length(argStr);
pFakeText:=Cardinal(VirtualAllocEx(PI.hProcess,0,Length(argStr),MEM_COMMIT,PAGE_READWRITE));
WriteProcessMemory(PI.hProcess,Pointer(pFakeText),PChar(@argStr),Length(argStr),tmpRW);
WriteProcessMemory(PI.hProcess,Pointer(CTX.Esp+4*2),Pointer(@pFakeText),4,tmpRW);
CTX.Dr0 := pRet;
CTX.Dr7 := 1;
SetThreadContext(PI.hThread,CTX);
Потом поставить бряк на ret, те на то куда указывает esp+4*0, да.  Заодно память освободить. Во.

if CTX.Eip = pRet then begin
  VirtualFreeEx(PI.hProcess,Pointer(pFakeText),ADLen,MEM_RELEASE);
  CTX.Dr0 := pProc;
  CTX.Dr7 := $01;
  SetThreadContext(PI.hThread,CTX);
end;
Вот екземпл(>>Слить готовое<<):

uses
  SysUtils,
  Windows;
type TString = array [0..256] of ansichar;
var
    hFile,tmpRW,tmp:DWORD;
    EntryPoint:DWORD;
    pArg,pProc,pRet,pFakeText:DWORD;
    EPByte:BYTE;
    int3:BYTE = $CC;
    OFS:_OFSTRUCT;
    INH:TIMAGENTHEADERS;
    SI:TStartupInfo;
    PI:TProcessInformation;
    DebugEvent:TDEBUGEVENT;
    CTX:CONTEXT;
    argStr:TString;
    i,ADLen:integer;
    AD:ansistring = #13#10'visit:thehukker.blogspot.ru'#0;
const
    path = 'test.exe';
    procName = 'MessageBoxA';
    libName = 'USER32.DLL';
function StrLen(var str:TString):integer;
var i:integer;
begin
  for I := 0 to Length(str) do begin
    if str[i]=Char(0) then break
  end;
  StrLen:=i;
end;
begin
  pProc:=DWORD(GetProcAddress(GetModuleHandle(libName),procName));
  hFile:=OpenFile(path,OFS,OF_READ);
  SetFilePointer(hFile,$3C,0,FILE_BEGIN);
  ReadFile(hFile,tmp,4,tmpRW,0);
  SetFilePointer(hFile,tmp,0,FILE_BEGIN);
  ReadFile(hFile,INH,SizeOf(INH),tmpRW,0);
  CloseHandle(hFile);
  EntryPoint:=INH.OptionalHeader.AddressOfEntryPoint+INH.OptionalHeader.ImageBase;
  ZeroMemory(@SI,sizeof(SI));ZeroMemory(@PI,SizeOf(PI));
  CreateProcess(path, 0, 0, 0, FALSE,DEBUG_ONLY_THIS_PROCESS + DEBUG_PROCESS, 0,0, SI, PI);
  ResumeThread(PI.hThread);
  ReadProcessMemory(PI.hProcess,Pointer(EntryPoint),@EPByte,1,tmpRW);
  WriteProcessMemory(PI.hProcess,Pointer(EntryPoint),@int3,1,tmpRW);
  ZeroMemory(@CTX,SizeOf(@CTX));
  CTX.ContextFlags:=CONTEXT_FULL + CONTEXT_DEBUG_REGISTERS;
  while True do begin
    WaitForDebugEvent(DebugEvent,INFINITE);
    GetThreadContext(PI.hThread,CTX);
    case DebugEvent.dwDebugEventCode of
    EXCEPTION_DEBUG_EVENT: begin
      if DebugEvent.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT then begin
        if CTX.Eip = EntryPoint+1 then begin
          Dec(CTX.Eip);
          WriteProcessMemory(PI.hProcess,Pointer(EntryPoint),@EPByte,1,tmpRW);
          CTX.Dr0 := pProc;
          CTX.Dr7 := $01;
          SetThreadContext(PI.hThread,CTX);
          ContinueDebugEvent(PI.dwProcessId, PI.dwThreadID,DBG_CONTINUE);
        end;
      end;
      if DebugEvent.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_SINGLE_STEP then begin
        if CTX.Eip = pProc then begin
          ZeroMemory(@argStr,Length(argStr));
          ReadProcessMemory(PI.hProcess,Pointer(CTX.Esp),Pointer(@pRet),4,tmpRW);
          ReadProcessMemory(PI.hProcess,Pointer(CTX.Esp+4*3),Pointer(@pArg),4,tmpRW);
          ReadProcessMemory(PI.hProcess,Pointer(pArg),PChar(@argStr[0]),256,tmpRW);
          WriteLn('Title:'+argStr);
          ZeroMemory(@argStr,Length(argStr));
          ReadProcessMemory(PI.hProcess,Pointer(CTX.Esp+4*2),Pointer(@pArg),4,tmpRW);
          ReadProcessMemory(PI.hProcess,Pointer(pArg),PChar(@argStr[0]),256,tmpRW);
          WriteLn('Text:'+argStr);
          WriteLn('===============');
          ADLen:=StrLen(argStr);
          for i := 1 to Length(AD) do begin
            argStr[ADLen-1+i]:=AnsiChar(AD[i]);
          end;
          ADLen:=Length(argStr);
          pFakeText:=Cardinal(VirtualAllocEx(PI.hProcess,0,Length(argStr),MEM_COMMIT,PAGE_READWRITE));
          WriteProcessMemory(PI.hProcess,Pointer(pFakeText),PChar(@argStr),Length(argStr),tmpRW);
          WriteProcessMemory(PI.hProcess,Pointer(CTX.Esp+4*2),Pointer(@pFakeText),4,tmpRW);
          CTX.Dr0 := pRet;
          CTX.Dr7 := 1;
          SetThreadContext(PI.hThread,CTX);
        end;
        if CTX.Eip = pRet then begin
          VirtualFreeEx(PI.hProcess,Pointer(pFakeText),ADLen,MEM_RELEASE);
          CTX.Dr0 := pProc;
          CTX.Dr7 := $01;
          SetThreadContext(PI.hThread,CTX);
        end;
      end;
    end;
    EXIT_PROCESS_DEBUG_EVENT: begin
      Break;
    end;
    end;
  ContinueDebugEvent(PI.dwProcessId, PI.dwThreadID,DBG_CONTINUE);
  end;
  Halt;
end.

Комментариев нет:

Отправить комментарий