Podmiana jednej funkcji w pliku .dll bez dll Injection

0

Witam, czy da się podmienić jedną funkcje w pliku .dll?, Wiem, że istnieje coś takiego jak MS detours i dll injection, ale chodzi, żeby to wykonać bez wstrzykiwania dodatkowych plików dll, dokładniej to chcę podmienić funkcje EnumDisplaySettings w dll'ce User32.dll, tak aby program miał wylistowane tylko wybrane tryby graficzne, wiem, że można to ustawić w sterowniku karty graficznej, ale chciałbym sprawdzić taki sposób.

0

Nie piszę w C++, ale w Delphi już robiłem takie rzeczy. Masz do wyboru spróbować zespoofować oryginalną dllkę, ale wtedy w swojej musiał byś przekierować wszystkie wykorzystywane funkcje API poza pożądanymi na oryginalne funkcje w dllce systemowej. A swoją pożądaną/pożądane odpowiednio podmienić by robiła to co chcesz i ewentualnie jeśli tylko chcesz odczytać co się dzieję, przekierować na dllkę. Dużo klepania kodu ogólnie.

Drugi sposób to właśnie z detourami/Hookami. Bo może zdarzyć się, że pomimo spoofnięcia dllki, program jest tak napisany, ze i tak nie odczytuje dllki bez ścieżki (czyli wtedy pierszeństwo przed katalogiem systemowym, ma katalog aktualny exeka), a wtedy spoofowanie nie zadziała. Pozostaje wtedy dodanie importu do exeka na swoją własną dllkę z jakąś istniejącą wyeksportowaną funkcją może to być zwykła procedura lub jak to w C++ void o nazwie - nie wiem FooBar. Dokonasz tego na przykład edytorem PE o nazwie PE Tools, polecam wygooglować go sobie.

Następnie w procedurze inicjuącej dllkę (w C++ ma to chyba znaczenie, w Delphi jest to po prostu kod między beginem, a endem kodu samego modułu dllki, bo DllProc w Delphi to też co innego i trzeba to obsłużyć jak poniżej (przykład - odpowiednie nazwy dodatkowych procedur sugerują kiedy inicjujemy Hook na funkcje API i go kończymy):

//...

procedure DllEntry(dwResaon : DWORD);
begin
  case dwResaon of
    DLL_PROCESS_ATTACH : InitHook;
    DLL_PROCESS_DETACH : UninitHook;
  end;
end;

exports
  FooBar;

begin
  DllProc := @DllEntry;
  DllEntry(DLL_PROCESS_ATTACH);
end.

Także musisz poszukać metod dla C++ do Hookowania funkcji API i po prostu Twoja dllka będzie sobie Hookowała wybraną funkcję. A w funkcji obsługi Hooka zrobisz co chcesz, przechwycisz parametry i je podmienisz lub tylko zalogujesz co chcesz np do Debug Window albo pliku, a później pozwolisz funkcji wykonać się jakby nigdy nic. Wszystko zależy od Ciebie. Konkretniej pod kątem C++, za pewne pomogą tutaj Tobie inni Użytkownicy Forum.

PS. Oczywiście zalecam pozostawienie sobie backupu oryginalnego exeka programu, bo ten z dodaną nową tablicą importów i tą dllką nie uruchomi się oczywiście po jej usunięciu z tego samego katalogu, co program. Dołączam też do tego posta przykładowy unit do Hooków dla Delphi. Działa bez problemów, również w przypadku dllki skompilowanej w wersji 64 bitowej. Przykład kodu w Delphi:

//...

var
  Hook : array[0..1] of TNtHookClass;

//..

procedure DoExit(ExitCode : UINT);
begin
  ExitProcess(ExitCode);
end;

procedure HookedExitProcess(ExitCode : UINT); stdcall;
begin
  DoExit(ExitCode);
end;

function HookedRegOpenKeyExA(ahKey : HKEY; lpSubKey : PAnsiChar;
  ulOptions : DWORD; samDesired : REGSAM; var phkResult : HKEY) : Longint; stdcall;
type
  TOriginalRegOpenKeyExA = function(ahKey : HKEY; lpSubKey : PAnsiChar;
    ulOptions : DWORD; samDesired : REGSAM; var phkResult : HKEY) : Longint; stdcall;
begin
  Hook[1].UnHook;
  Result := TOriginalRegOpenKeyExA(Hook[1].BaseAddr)(
    ahKey, lpSubKey, ulOptions, samDesired, phkResult);
  Hook[1].Hook;
end;

procedure InitHook;
begin
  Hook[0] := TNtHookClass.Create('kernel32.dll', 'ExitProcess', @HookedExitProcess);
  Hook[1] := TNtHookClass.Create('advapi32.dll', 'RegOpenKeyExA', @HookedRegOpenKeyExA);
end;

procedure RemoveTheHook;
var
  I : integer;
begin
  for I := Low(Hook) to High(Hook) do
  begin
    if Hook[I] <> nil then
    begin
      FreeAndNil(Hook[I]);
    end;
  end;
end;

//...

Sorry, że tyle kodu nie w C++, a Dephi. No myślę, że to pozwoli Tobie zrozumieć ideę. Zawsze możesz to sobie przetłumaczyć na C++ czy inny język. Podstawową wiedzę do kombinowania już masz, także pozostaje tylko dalej samodzielnie podziałać :)

0

myślałem, żeby np przekierować całe api w dll'ce, ale User32.dll ma ponad 700 odwołań więc raczej mało opłacalny interes, a czy przy Hookowaniu da się określić kolejność ładowania dll'ek? bo przypuszczam, że tryby graficzne ładowane są zaraz po starcie aplikacji więc tutaj "Wstrzyknięcie" dodatkowej dll'ki w trakcie działania programu nie miało by chyba sensu. jedynie mam pomysł, aby podmienić dll'ke która ma względnie mało odwołań, przekierować je i przy okazji podhookować swoje API. Wszytskie pliki .dll są ładowane na samym początku uruchamiania?

0

O ile się nie mylę, to ładowanie dllek powiązane jest z tablicą importów lub samymi wyowłaniami w kodzie, jeżeli jest to robione dynamicznie. Oczywiście można zrobić jeszcze tak jak napisałeś. Znaleźć dllkę z najmniejszą ilością importów i to ją zespoofować, w początkowym kodzie dając Hook na żądaną funkcję API, a wszystkie exportowane funkcje przekierowywać na oryginalną bibliotekę i funkcję. Jednak może zdarzyć się, że i tak taka dllka się nie załaduje w ogóle, bo jej program nie wywołuje bez ścieżki tylko konkretnie z systemu.

To zależy od programu, do którego się dobierasz. Pomijajać to. Nawet jeśłi chcesz wstrzykiwać dllkę to przecież przez swój loader można to zrobić uruchamiając docelowy proces i dokonując injekcji. Nie wiem jak w C++, ale gdy bawiłem się w injectowanie w 32 bitowe procesy, znalezionym modułem z kodem, nie było z tym żadnych problemów. Do 64 bitów rozwiązanie znalazłem sprawdzone tylko na Hooki, ale gdyż korzystało one z VCL to prosta dllka pod praktycznie nowym Delphi XE 8, prosta dllka miała aż ponad 1,7 MB rozmiaru. Także nawet na obecne pojemności dysków i prędkości łącz za gruba przesada.

Jeżeli nie uda się zespoofować, bo wiadomo wtedy wystarczy wrzucić tylko dllkę do katalogu z exekiem, to spróbuj dodać import do exeka. To powiedzie się nawet przy spakowaniu UPX'em, ale przy jakichś wykombinowanych zabezpieczeniach nie do końca wiem czy się powiedzie. Wtedy jeśłi nie spoofing i nie dodanie importu, pozostaje jednak injekcja zaraz po uruchomieniu programu i we wstrzykniętej dllce "podpięcie" się Hookiem czy tam w C++ detourem pod żądaną/e funkcje API.

Oczywiście pisze co wiem z własnego doświadczenia i ogarniętego kodami pod Delphi. Także na pewno ekspertem nie jestem. Bo jeśłi chodzi o tematy inżynierii wstecznej to raczej ze mnie raczkująca lama. Jeśli masz problem z dodaniem importu to obejrzyj w wolnej chwili mój lame tutorial na - dodawanie importu pokazuję od czasu 2:40.

0

hmm Wytestuję później którąś z metod na różnych programach, a czy jest możliwe jakimś programem zedytować plik .dll tak aby w wywołaniu dowolnej określonej funkcji (np Dllmain) wymusić załadowanie własnej dll'ki?

0

Wątpie żeby było coś gotowego. Musiał byś pewnie do dllki dodać import albo pozmieniać jej skompilowany kod poprzez edycje opcodów w odpowiednim miejscu. Jednak takie kombinowanie, w szczególności z systemowymi dllkami, gdzie już nie bardzo jest pewnie gdzie coś dopisać, to się może źle skończyć z wywaleniem systemu włącznie. Może ktoś jeszcze coś Ci tutaj z tym podpowie. Według mnie jeżeli exek się nie oprze to najprościej będzie dodąć własną dllkę albo injectować ją uruchamiające cel. Obie merody są inwazyjne, ale nie aż tak jak grzebanie w dllkach systemowych.

0

Oczywiście, że taka podmiana jest możliwa. Ale to nie jest robota dla newbie. Wystarczyło by zmienić treść wybranej funkcji w oryginalnym dll'u. Tylko wtedy mamy problem taki, że na poziomie assemblera trzeba się zmieścić w rozmiarze starej funkcji, co czasem może być kłopotliwe. Ewentualnie można by oryginalną funkcję EnumDisplaySettings w pliku User32.dll podmienić w ten sposób aby tylko wywoływała funkcję z Twojej dll'ki napisaną już w C/C++ czy innym dowolnym języku. To by było chyba najłatwiejsze rozwiązanie, bo zabawy z assemblerem będzie mało i dotyczy tylko wywołania funkcji z nowej dll'ki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1