Injekcja 64 bitowej dllki w 64 bitowy proces pod Lazarusem.

0

Zwracam się z prośbą do wszystkich znawców Lazarusa. Być może nawet @-123oho zamiast krytykować będzie mógł się podzielić konkretną wiedzą. Nie mogąc spać, wstałem i napisałem tego posta mimo iż wcześniej trochę pobawiłęm się po raz pierwszy w życiu 64 bitowym Lazarusem z IDE w języku polskim. Jednak dość pobieżnie. Co chce osiągnąć? Otóż doczytałem się, że aby zainjectować dllkę w 64 bitowy proces nasz injector jak i sama dllka musi być skompilowana w 64 bitowym środowisku. Jako, że nie chce kombinowac z szukaniem pirackiego Delphi, a na zakup najnowszych mnie nie stać. Poza tym nie chce nadpisywać rozszerzeń dla Delphi 7, postanowiłem spróbować skompilować taki kod umieszczony na: http://olesio.eu/load_tc_and_show_path_on_taskbar.rar pod 64 bitowym Lazarusem. Pod Delphi 7 kompiluje się on bez problemów i kombinowania, dodatkowo oczywiśćie dla 32 bitowego Total Commandera elegancko po odpaleniu pokazuje aktualny katalog z aktywnego panelu na pasku tytułowym. Tak sobie tego życzyła osoba pytająca o takie rozwiązanie na polskim forum totalcmd.pl. Jednak ja chciałbym spróbować zastosować ten kod dla 64 bitowej wersji Total Commandera. O ile injector uruchomi tę wersję po jej wykryciu po nazwie exeka, to injekcja dllki nie dojdzie do skutku (funkcja InjectDll zwróci False). Próbowałem właśnie to skompilować pod Lazarusem. Ale moduł afxcodehook.pas powoduje mnóstwo błędów. Nie pomagają dyrektywy kompilatora takie jak {$MODE DELPHI}oraz {$ASMMODE intel}. Googlowałem, ale nie znalazłem dodatkowego info jak dostosować kod aby nie czepiało się konstrukcji takich jak mov eax, $FFFFFFFF; push eax. A po ich zakomentowaniu co wiadomo może wpłynąc na działąnie całości Lazarusowi nie podobają się linijki takie jak: ImageNtHeaders := Pointer(int64(cardinal(Src)) + PImageDosHeader(Src)._lfanew); i tym podobne. Bez tego modułu nie rusze dalej. W sumie to prośba: jeżeli za trudno go przerobić - to może ktoś pisał coś albo zna nazwy działąjących modułów dla 64 bitowego Lazarusa lub rozwiązań kodu, który po 1. pozwoli na skuteczną injekcje 64 bitowej dllki w 64 bitowy proces po podaniu jego PId'u. Najlepiej żeby dało się tak jak to widać w kodzie, injectować dllkę zawartą w zasobach i zrobić to przy użyciu tylko funkcji WinAPI. Po 2. Przydała by się też funkcja, która działa jak HookCode ze wspomnianego kodu modułu, ponieważ biblioteka inject.dll wykorzystuje ją do ustalenia, która kontrolka w oknie Total Commandera otrzymała Message WM_IME_SETCONTEXT, co po sprawdzeniu klasy kontrolki oznacza że jest to aktywny panel z listą katalogów oraz plików. Ja mam niestety za małą wiedzę o samodzielnym injectowaniu dllek w procesy. Korzystałem zwykle z rozwiązań gotowych znalezionych na sieci. A osoba zajmująca się RE, z którą kontaktowałem się via GG nie ma doświadczenia w dobieraniu się taką techniką do 64 bitowych procesów. Kod z: http://coding-gods.org/topic/1858-tut-prosty-injector mimo iż ładuje dllkę z pliku. Mimo podania prawidłowej ściezki do dllki jak i PId'u nie zainjectował się ani w 32 bitowy w 64 bitowy proces Total Commandera (zwraca błąd "Nie udalo sie stworzyc zdalnego watku"). Mimo iż autor zapewnia, że powinien działąć też pod Lazarusem. Z góry dziękuję za wszelkie przykładowe kody. Może jeśli pokażą się działające rozwiązania i wskazówki jak przerobić mój kod z linku powyżej, to wszystko przyda się też również innym osobom. Znajdowałem też jakieś kody w C++ na stronie z opisem trzech róznych technik injekcji dllki, mozolnie przetłumaczyłem je na Delphi, ale próba injekcji kończyła się zamrożeniem Windowsa na chwilę oraz informacją o błędzie aplikacji otrzymaniej od mojego Windows 7 Ultimate 64 bit. Widzę też, że @deus wrócił na forum, to super, nie wiem czy jeszcze ma On do czynienia z Delphi, ale zagląda do tego działu i być może zarówno On jak i @-123oho plus ewentualnie inni lepiej obeznani z Lazarusem niż ja po ledwie ponad godzinie zabawy - coś doradzą tutaj. A ja zaraz zbieram się do pracy, jak wrócę, odeśpię i pozałatwiam swoje sprawy na mieście to pewnie będę na forum dopiero w poniedziałek wieczorem. Fajnie jak do tego czasu dacie radę poratować konkretnymi kodami lub wskazówkami, dzięki którym będę umiał injectować dllki w 64 bitowe procesy, w Lazarusie. I sorry za tradycyjną rozpiskę i chaos w treści :)

0
Rev napisał(a)

że dyrektywami kompilatora raczej dużo nie zdziałasz
Zdziałasz, ale niestety prawie wszystkie wstawki asemblerowe trzeba będzie przepisać na nowo. Czyli coś takiego:

{$IFDEF WIN64}
asm
   // wstawka 64-bitowa
end;
{$ELSE}
asm
  // wstawka 32-bitowa
end;
{$ENDIF}

To będzie kupa roboty.

0

Być może nawet @-123oho zamiast krytykować będzie mógł się podzielić konkretną wiedzą.

Niestety nie mam 64bitowego systemu ani Lazarusa. Ah będę się musiał przerzucić niedługo.

A po ich zakomentowaniu co wiadomo może wpłynąc na działąnie całości Lazarusowi nie podobają się linijki takie jak: ImageNtHeaders := Pointer(int64(cardinal(Src)) + PImageDosHeader(Src)._lfanew); i tym podobne.

Być może kod jest pod PE32 nie pod PE32+? A tak to pewnie brakuje paru headerów, możesz poszukać w moim module mype_simple.pas (część szyfratora relokacji), tam na pewno są wszystkie podstawowe headery dla PE32.

Kod z: http://coding-gods.org/topic/1858-tut-prosty-injector mimo iż ładuje dllkę z pliku. Mimo podania prawidłowej ściezki do dllki jak i PId'u nie zainjectował się ani w 32 bitowy w 64 bitowy proces Total Commandera (zwraca błąd "Nie udalo sie stworzyc zdalnego watku").

Może spróbuj podejrzeć co to dokładnie za błąd? Wydaje mi się że powinno to działać.

Znajdowałem też jakieś kody w C++ na stronie z opisem trzech róznych technik injekcji dllki, mozolnie przetłumaczyłem je na Delphi, ale próba injekcji kończyła się zamrożeniem Windowsa na chwilę oraz informacją o błędzie aplikacji otrzymaniej od mojego Windows 7 Ultimate 64 bit.

Metoda której używasz zawsze mi działała na procesach 32 nawet przy systemie 64.

Próbowałem właśnie to skompilować pod Lazarusem. Ale moduł afxcodehook.pas powoduje mnóstwo błędów. Nie pomagają dyrektywy kompilatora takie jak {$MODE DELPHI}oraz {$ASMMODE intel}. Googlowałem, ale nie znalazłem dodatkowego info jak dostosować kod aby nie czepiało się konstrukcji takich jak mov eax, $FFFFFFFF; push eax

No nic dziwnego bo to kod asma 32 bit. Wiele rzeczy w tej bibliotece zależy na rzeczach 32bitowych. Może poszukaj biblioteki hookującej dla 64 bitów? Albo możesz zmienić tą, jest bardzo prosta. Natomiast żeby zmienić całą bibliotekę to już będzie dużo roboty.

O ile wydaje mi się że zrobienie injectora będzie dosyć proste, to mogą być problemy z biblioteką (hookowanie) a zwłaszcza z ładowaniem z zasobów bo mało jest takich loaderów dla PE32+.

U siebie stosuję taką metodę injectowania (wymaga żeby proces już był otwarty, ale powinieneś dać radę przerobić ;) ):

function InjectModule(ModulePath: PAnsiChar; ProcessID: DWORD;hprocess:Cardinal): Boolean;
type
  TNtCreateThreadEx = function(
  ThreadHandle: PHANDLE;
  DesiredAccess: ACCESS_MASK;
  ObjectAttributes: Pointer;
  ProcessHandle: THANDLE;
  lpStartAddress: Pointer;
  lpParameter: Pointer;
  CreateSuspended: BOOL;
  dwStackSize: DWORD;
  Unknown1: Pointer;
  Unknown2: Pointer;
  Unknown3: Pointer): HRESULT; stdcall;
var
  lpStartAddress, lpParameter: Pointer;
  dwSize: Integer;
  hThread, lpThreadId, lpExitCode, lpBytesWritten: Cardinal;
  NtCreateThreadEx: TNtCreateThreadEx;
  s,ss:ansistring;
begin
  Result := False;
  dwSize := StrLen(ModulePath) + 1;
  lpParameter := VirtualAllocEx(hProcess, nil, dwSize, MEM_COMMIT, PAGE_READWRITE);
  if (lpParameter = nil) then
  begin
    ShowMessage('Injection error '+inttostr(GetLastError));
    if hProcess <> 0 then
      CloseHandle(hProcess);
    Exit;
  end;
    //NtCreateThreadEx := GetProcAddress(GetModuleHandleW('ntdll'), 'NtCreateThreadEx');
  lpStartAddress := GetProcAddress(GetModuleHandleW('kernel32'), 'LoadLibraryA');
  if (lpStartAddress = nil) then
    Exit;
    {if (@NtCreateThreadEx = nil) then
      Exit;}
  lpBytesWritten := 0;
  if (WriteProcessMemory(hProcess, lpParameter, ModulePath, dwSize, lpBytesWritten) = False) then
  begin
    VirtualFreeEx(hProcess, lpParameter, 0, MEM_RELEASE);
    if hProcess <> 0 then
      CloseHandle(hProcess);
    Exit;
  end;
  hThread := 0;
  lpThreadId := 0;
    hThread := CreateRemoteThread(hProcess, nil, 0, lpStartAddress, lpParameter, 0, lpThreadId);
  if (hThread = 0) then
  begin
    VirtualFreeEx(hProcess, lpParameter, 0, MEM_RELEASE);
    CloseHandle(hProcess);
    Exit;
  end;
  GetExitCodeThread(hThread, lpExitCode);
  if hProcess <> 0 then
    CloseHandle(hProcess);
  if hThread <> 0 then
    CloseHandle(hThread);
  Result := True;
end;
0

Dziękuję za odpowiedzi. Kod do injekcji przetestuje i na pewno się przyda. Lazarus jakby co na dysku zostanie, spróbuje później okiełznać jego konfiguracje. Chociaż póki co exek z czystą formatką zajmuje po kompilacji ponad 15 MB, po stripie 2 MB. Jak możecie to niech ktoś doświadczony z Lazarusem machnie jakiś art na 4p jak skutecznie odchudzić exeki w Lazarusie żeby strip robił się automatycznie lub co i gdzie ustawić w samym IDE aby generować jak najmniejsze pliki. Trochę się przyzwyczaiłem do IDE Delphi 7 z GExperts. Brakuje mi w Lazarusie takiego samego działania Ctrl+G jak pod GExperts. Nie podoba mi się zmieniona kolorystyka edytora kodu, z którą pewnie trzeba się babrać żeby wygładało to zbliżenie do Delphi 7. Dziwne jest też to otwieranie ostatniego projektu, ja i tak wolę robić to z pod Total Commandera, a tutaj widzę że projekt żeby na pewno tworzyć nowy trzeba zamknąć, a polecenie do tego "wylądowało" w innym menu, co trochę utrudniało mi połapanie się. Co do samej injekcji osoba, która potrzebowała pomocy na forum.totalcmd.pl jest zadowolona z obecnego rozwiązania dla wersji 32 bitowej, a z braku skutecznej funkcji do Hookowania funkcji API dla Lazarusa 64 bitowego w taki sposób jak robi to 32 bitowa aktualna dllka inject.dll nie zrobił bym identycznej funkcjonalności dla wersji 64 bitowej Total Commandera. Myslę, że osoba ta mając gotowe rozwiązanie na tacy i tak to jakoś przeboleje. Według mnie spokojnie można używac Total Commandera 32 bitowego na Windows 64 bitowym. Ja tak robię na swoim Windows 7 Ultimate i uważam, że nie ma się wtedy jakichś problemów.

0

Chociaż póki co exek z czystą formatką zajmuje po kompilacji ponad 15 MB, po stripie 2 MB. Jak możecie to niech ktoś doświadczony z Lazarusem machnie jakiś art na 4p jak skutecznie odchudzić exeki w Lazarusie żeby strip robił się automatycznie lub co i gdzie ustawić w samym IDE aby generować jak najmniejsze pliki.

Wygodniej podczas testowania jest mieć te 15MB pliki, ja póki nie robię kompilacji finalnej to nie przejmuję się rozmiarami plików do 20MB. Wiem że początkowo to denerwuje, ale po czasie idzie się przyzwyczaić.
Co do arta, to niestety raczej nie napiszę bo moje konto jest zablokowane. Ale ostatnio @Patryk27 jest w tej kwestii aktywny, było już to pytanie parę razy zadawane więc na forum można znaleźć sporo o tym. Wystarczy że ktoś zbierze to do kupy i wesprze linkami do doców Lazarusa.
Btw. http://wiki.freepascal.org/Lazarus_For_Delphi_Users

Trochę się przyzwyczaiłem do IDE Delphi 7 z GExperts. Brakuje mi w Lazarusie takiego samego działania Ctrl+G jak pod GExperts.

Narzędzia->Opcje->Edytor->Klawisze skrótu->Load a scheme->Classic (?)

Nie podoba mi się zmieniona kolorystyka edytora kodu, z którą pewnie trzeba się babrać żeby wygładało to zbliżenie do Delphi 7.

Konfiguracja jest całkiem przyjemna, menu nie jest jakoś specjalnie namieszane. Osobiście używam swojej własnej kompozycji która częściowo czerpie z Lazarusa a częściowo jest moim pomysłem. Pewnie też kwestia przyzwyczajenia.
Btw. Narzędzia->Opcje->Edytor->Ekran->Kolory->Na górze rozwijasz Default i wybierasz Delphi

Dziwne jest też to otwieranie ostatniego projektu, ja i tak wolę robić to z pod Total Commandera, a tutaj widzę że projekt żeby na pewno tworzyć nowy trzeba zamknąć, a polecenie do tego "wylądowało" w innym menu, co trochę utrudniało mi połapanie się.

Co wylądowało w innym menu? Nowy projekt? Nie za bardzo rozumiem. Zamykanie projektu też jest w menu 'projekt'. I nie trzeba zamykać starego projektu żeby utworzyć nowy.

Według mnie spokojnie można używac Total Commandera 32 bitowego na Windows 64 bitowym. Ja tak robię na swoim Windows 7 Ultimate i uważam, że nie ma się wtedy jakichś problemów.

Platforma 32 bitowa jest dużo bardziej zbadana i ogarnięta, więc normalne jest to że używa się wielu programów 32 bitowych. Ja nawet mam system 32 bit i żyję.

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