Конференция "WinAPI" » Выгрузка WinApi перехватчика [D7, WinXP]
 
  • evvcom © (03.09.08 13:54) [160]
    честно говоря, такую деталь не помню. Писал давно, да и по сути делал перевод с сишного примера Рихтера на паскаль, а под рукой сейчас исходника нет. Вечером посмотрю, если не забуду :)
  • KygECHuK © (03.09.08 15:11) [161]

    >  сишного примера Рихтера на паскаль


    я то же с чьегото сишного примера делал
  • Anatoly Podgoretsky © (03.09.08 20:14) [162]
    > KygECHuK  (03.09.2008 10:34:39)  [159]

    Есть и на русском и на английском. Четвертое издание.
  • evvcom © (04.09.08 23:27) [163]
    // На вход передаем dwProcessId - идентификатор процесса,
    // в который требуется внедрить dll с именем lpModName
    function InjectLibByRemoteThread(dwProcessId: DWORD; lpModName: PChar): Boolean;
    var
     l_hProcess: THandle;
     l_hThread: THandle;
     l_ThreadFunc: TFNThreadStartRoutine;
     l_ThreadId: DWORD;
     l_iLength: Cardinal;
     l_pBuffer: PChar;
     l_NumberOfBytesWritten: DWORD;
    begin
     Result := False;
     l_hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or
       PROCESS_VM_WRITE, False, dwProcessId);
     if l_hProcess = 0 then Exit;
     try
       l_ThreadFunc := GetProcAddress(GetModuleHandle(kernel32), 'LoadLibraryA');
       if not Assigned(l_ThreadFunc) then Exit;
       l_iLength := Length(lpModName);
       l_pBuffer := VirtualAllocEx(l_hProcess, nil, l_iLength + 1,
         MEM_COMMIT, PAGE_READWRITE);
       if not Assigned(l_pBuffer) then Exit;
       try
         if not WriteProcessMemory(l_hProcess, l_pBuffer, lpModName, l_iLength,
           l_NumberOfBytesWritten)
         then Exit;
         l_hThread := CreateRemoteThread(l_hProcess, nil, 0, l_ThreadFunc,
           l_pBuffer, 0, l_ThreadId);
         Result := l_hThread <> 0;
         if Result then begin
           WaitForSingleObject(l_hThread, INFINITE);
           CloseHandle(l_hThread);
         end;
       finally
         VirtualFreeEx(l_hProcess, l_pBuffer, 0, MEM_RELEASE);
       end;
     finally
       CloseHandle(l_hProcess);
     end;
    end;

    // На вход передаем dwProcessId - идентификатор процесса,
    // из которого требуется выгрузить dll с именем lpModName
    function WithdrawLibByRemoteThread(dwProcessId: DWORD; lpModName: PChar): Boolean;
    var
     l_hProcess: THandle;
     l_hThread: THandle;
     l_ThreadFunc: TFNThreadStartRoutine;
     l_ToolHelp: TToolHelp;
     l_me: TModuleEntry32;
     l_ThreadId: DWORD;
    begin
     Result := False;
     l_hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or
       PROCESS_VM_WRITE, False, dwProcessId);
     if l_hProcess = 0 then Exit;
     try
       l_ThreadFunc := GetProcAddress(GetModuleHandle(kernel32), 'FreeLibrary');
       if not Assigned(l_ThreadFunc) then Exit;
       // Найдем внедренную библиотеку в целевом процессе
       l_ToolHelp := TToolHelp.Create(TH32CS_SNAPMODULE, dwProcessId);
       try
         l_me.dwSize := SizeOf(TModuleEntry32);
         if not l_ToolHelp.ModuleByNameFind(lpModName, l_me) then Exit;
         l_hThread := CreateRemoteThread(l_hProcess, nil, 0, l_ThreadFunc,
           Pointer(l_me.hModule), 0, l_ThreadId);
         Result := l_hThread <> 0;
         if Result then begin
           WaitForSingleObject(l_hThread, INFINITE);
           CloseHandle(l_hThread);
         end;
       finally
         l_ToolHelp.Free;
       end;
     finally
       CloseHandle(l_hProcess);
     end;
    end;

  • evvcom © (05.09.08 08:27) [164]

    > Ты её делаешь сразу без условий или с какими то либо задержками
    > или синхронизацией?

    Из кода видно, что выполняется ожидание завершения потока до закрытия хэндла. Или ты под задержкой/синхронизацией имел ввиду что-то другое?
  • KygECHuK © (05.09.08 09:53) [165]

    > Из кода видно, что выполняется ожидание завершения потока
    > до закрытия хэндла. Или ты под задержкой/синхронизацией
    > имел ввиду что-то другое?


    Я имел ввиду действия, которые производит библиотека при отключении жертвы от неё.
  • evvcom © (05.09.08 10:34) [166]
    Действия, которые производит библиотека при отключении, выполняются в DLL_PROCESS_DETACH (в АП жертвы). Пока они не выполнятся, поток не завершит свою работу. А сервис (у меня сервис), т.е. процесс, который занимается внедрением/изъятием dll в/из АП жертвы, ждет завершения удаленного потока
    WaitForSingleObject(l_hThread, INFINITE);

    Этим и достигается синхронизация.
  • KygECHuK © (05.09.08 10:41) [167]

    > Этим и достигается синхронизация.

    Все это хоршо, я это понял из предыдущего поста. мения интеризуют не конкретно используемые объекты синхронизации Windows, а "синхронизация" потока, исправляющего адреса с другими потоками процесса жертвы
  • evvcom © (05.09.08 12:07) [168]
    аааа.... Ты вот о чем. Идея такова. После того, как случился внедреж :), dll в жертве (далее просто жертва) начинает общаться с сервисом, вариантов реализации этого общения - масса, каждый выбирает, что ему по вкусу, поэтому не буду на этом останавливаться. Жертва запрашивает у сервиса, что приготовлено для данного процесса, какую dll надо загрузить, после чего выполняет LoadLibrary уже штатно. Далее останавливаются все потоки процесса кроме текущего (или это лучше сделать самым первым делом после внедрения), из загруженной dll вытягивается инфа, что должно быть перехвачено, вычисляются адреса и данные, которые должны быть по ним записаны, и все это сообщается сервису, который успешно производит подмены адресов. Сообщение жертве "все готово", та запускает потоки и завершает свой стартовый код DLL_PROCESS_ATTACH. Ну вот типа такого.
  • Сергей М. © (05.09.08 12:24) [169]

    > evvcom ©   (05.09.08 12:07) [168]


    А грабли как были , так и остались, не смотря на все эти хитромудрые телодвижения)

    Ведь выгрузку модуля-перехватчика нельзя делать пор, пока хотя бы в одном из потоков процесса-жертвы исполняется код, принадлежащий АП модуля-перехватчика..

    Первое что напрашивается для устранения засады - в ходе деинициализации перехватчика вернуть на место оригинальные IAT/EAT-элементы и в цикле (опасно, но куда деваться ?) проверять, не ссылается ли контекст каждого из существующих потоков жертвы на код в АП перехватчика или не фигурирует ли в стеках потоков адреса возвратов, указывающие на АП перехватчика.

    Это отдельный геморрой, но он, видимо, того стОит ..
  • evvcom © (05.09.08 13:13) [170]
    Согласен :)
    Я не все здесь описал, что задумал. Даже если в настоящий момент код не выполняется, и мы определим это из контекстов, стеков и прочих ухищрений, нет никакой гарантии, что не схватим AV после Resume потоков. Я столкнулся с этим в первой же своей подобной задаче, о чем упомянул в [141]. Гораздо проще, имхо, и надежнее сделать нечто типа MakeObjectInstance, которая конструировала бы в куче что-то типа вызова перехваченной функции или оригинала по условию в зависимости от взведенного флага и соответственно перед выполнением кода "ловушки" inc счетчика, после dec. Естественно все это надежно защитить, например, крит. секцией. Детали я еще не реализовывал, потому по ходу будут грабли, обязательно будут.
  • Сергей М. © (05.09.08 13:40) [171]

    > нет никакой гарантии, что не схватим AV после Resume потоков


    Гарантия есть, потому что тек.контексты и стеки потоков отныне ни прямо ни косвенно не ссылаются ни на один из адресов в АП модуля-перехватчика, что как раз и покажет проверка. И более никогда не будут обращаться к этому АП, потому что оригинальная IAT восстановлена перед началом проверки.
  • evvcom © (05.09.08 14:10) [172]
    Сергей, ты в [141] читал ситуацию?

    > И более никогда не будут обращаться к этому АП, потому что
    > оригинальная IAT восстановлена перед началом проверки.

    Разве обращаться к функции можно только каждый раз проверяя IAT? Еще раз поясню ситуацию. Процесс загрузил мою dll, dll изменила IAT, процесс считал адрес (это уже адрес в моей dll) и сохранил его в ebx, далее

    цикл:
    push ebx

    условие 1:
    call ebx // перехваченная функция

    ... прочие условия

    условие N:
    call FreeLibrary

    pop ebx
    cmp ...
    jmp nz, цикл



    Вот такая вот реальная ситуация была и происходило это в однопоточном приложении.
  • Сергей М. © (05.09.08 14:33) [173]

    > evvcom ©   (05.09.08 14:10) [172]


    А, ты вон о чем ..

    Ч.г., я не вник в [141], а ты там завел речь о частном случае (довольно редкий он и заведомо не случай автора, потому я и не рассматривал его) ..

    Ну что тут сказать ?
    Для случаев, подобных твоему, метод перехвата путем модификации IAT/EAT не годится, здесь на сцену выходит метод сплайсинга.
  • KygECHuK © (05.09.08 15:20) [174]

    > здесь на сцену выходит метод сплайсинга.


    Что за зверь, где о нём можно раздобыть инфу?
  • Сергей М. © (05.09.08 15:29) [175]

    > KygECHuK ©   (05.09.08 15:20) [174]


    "Шурик, это же не наш метод !" (С)

    Тебе-т он зачем ? Явно же не твой же случай ..

    Или "Надо, Федя, надо"  ?)

    http://www.wasm.ru/article.php?article=apihook_1
  • KygECHuK © (05.09.08 15:44) [176]

    > Тебе-т он зачем ? Явно же не твой же случай ..


    Автор:

    Для того, чтобы его понять нужна всего-лишь капля мозгов (не больше).


    по минимальным требованиям, вроде подхожу... :)
    Учиться никогда не поздно, хотя часто бесполезно ....
 
Конференция "WinAPI" » Выгрузка WinApi перехватчика [D7, WinXP]
Есть новые Нет новых   [134435   +33][b:0.001][p:0.003]