Dobre dekompilatory

0

Witam. Proszę o wskazanie mi dobrych dekompilatorów. Dobrych tz. działających i generujących w miarę czytelny kod. Jak do tej pory próbowałem używać dwóch:

-plugina do IDA
-boomerang

Problem z pierwszym polega na tym, że generuje dość dziwny kod, i ogólnie nieczytelne nazwy funkcji i zmiennych(nieczytelne tz. np sub_XXXXXX i ciezko odroznic jedna taka funkcje od drugiej; jak juz to wolalbym zeby generowalo cos w stylu sub1, sub2....)
Ale to maly problem w porownaniu z czyms takim:

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  CHAR File; // [sp+2Ch] [bp-100h]@5

  sub_423730();
  (*(void (__stdcall **)(_DWORD, _DWORD, _DWORD))(*LODWORD(dword_54FD30) + 80))(LODWORD(dword_54FD30), "Data.chunk", 0);
  sub_449690();
  if ( !(unsigned __int8)sub_4237E0()
    && (unsigned __int8)(*(int (__stdcall **)(_DWORD))(*LODWORD(dword_54FD30) + 4))(LODWORD(dword_54FD30)) )
  {
    (*(void (__stdcall **)(_DWORD))(*LODWORD(dword_54FD30) + 128))(LODWORD(dword_54FD30));
    (*(void (__cdecl **)(_DWORD, _DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Loading...", 0);
    sub_4490C0();
    (*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Starting...");
    (*(void (__cdecl **)(_DWORD))(*LODWORD(dword_54FD30) + 12))(LODWORD(dword_54FD30));
    (*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Clearing things...");
    sub_41E4E0();
    (*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Freeing objects...");
    sub_448C70();
    (*(void (__stdcall **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Freeing sounds...");
    sub_43F4A0();
    (*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Freeing textures...");
    sub_449640();
  }
  (*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Removing resource...");
  (*(void (__stdcall **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 84))(LODWORD(dword_54FD30), "Data.chunk");
  (*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Shutting down...");
  (*(void (__stdcall **)(_DWORD))(*LODWORD(dword_54FD30) + 8))(LODWORD(dword_54FD30));
  (*(void (__stdcall **)(_DWORD))*LODWORD(dword_54FD30))(LODWORD(dword_54FD30));
  if ( byte_54FD70 )
  {
    GetModuleFileNameA(0, &File, 0x100u);
    ShellExecuteA(0, "open", &File, 0, 0, 1);
  }
  return 0;
} 

(*(void (__stdcall **)(_DWORD, _DWORD, _DWORD))(*LODWORD(dword_54FD30) + 80))(LODWORD(dword_54FD30), "Data.chunk", 0);

Nawet nie jestem w stanie tego odczytac - te wszystkie gwiazdki, nawiasy sie mi rozmywaja

Przy czyms takim musze przeskakiwac do widoku asemblera:

mov eax, dword_54FD30
push 0
push offset aData_chunk ; "Data.chunk"
push eax
mov ecx, [eax]
call dword ptr [ecx+50h]

Czy naprawde tego sie nie na zapisac jakos czytelniej, na kilka linii?

Cos w stylu

_eax = &dword_54FD30
_ecx = eax
(
(*ecx+50h)(eax, aData_chunk, 0)); //nie wiem czy to jest poprawne, nigdy nie uzywalem wskaznikow na funkcje

  1. Boomerang.

Tutaj, jesli wierzyc przykladowi na stronie projektu, kod wyglada bardzo czytelnie. Niestety, dekompiler mi nie dziala. Niewazne czy wybiore wersje gui czy konsolowa, zawsze crashuje sie prawie na koncu procesu dekompilacji(wtedy jak tworzy chyba jakies drzewo czy graf funckcji)

Czy sa jakies inne alternatywy?

1

Bezpośrednie czytanie assembly? Dekompilatory są drogie i niedokładne, jak sam z resztą zauważyłeś. W gruncie rzeczy wystarczy coś pokroju IDY, która bardzo ładnie pokazuje różne ścieżki wykonania. Do tego trochę wprawy i czyta się to prawie jak C ;).

Można zapytać z resztą @Gynvael Coldwind jak na co dzień pracują profesjonaliści. Jestem przekonany, że firmy, które pracują również w dziedzinie RE posiadają zabawki typu Hex Rays, ale raczej nie korzysta się z nich przy każdej okazji?

0

Tz nie mowie ze ten dekompilator jest zly, tylko mysle ze moglby byc troche lepszy. Zreszta nie wiem, moze gdzies jest konfiguracja i da sie go troche pozmieniac? Pytam sie o inne dlatego ze chce wybrac najlepszy, a w tej chwili nie mam wyboru bo boomerang nie dziala a innego nie znam.

Co do uzywania deasemblera do mojego aktualnego celu - raczej odpada. Chce przepisac gre do czytelnego kodu C, tak zeby dzialala tak jak oryginal. Wymyslilem to tak ze

1.Dekompiler wygeneruje mi kod C na podstawie exeka
2.Bede funkcja po funkcji zmienial ich zawartosc na ladna i czytelna

Zdaje sobie sprawe ze to duzo roboty, ale tak bedzie na pewno kilka razy szybciej niz przepisywac z asma.

No i jeszcze kwesita kluczowa: czy moge wyeksportowac w IDA ten kod do pliku? Cze bede musial wszystkie(kilkaset) funkcji recznie kopiowac? Bo z tego co widze to w pseudokodzie nie ma odpowiednika text view w asmie; tz widze naraz tylko jedna funkcje a nie caly kod.
I 2 sprawa: czy ten kod po niewielkich zmianach bedzie dzialac? Wiem ze to pseudocode, ale skladnia jest prawie jak c, tylko te rzeczy typu _DWORD, ale to chyba mozna makrem zalatwic typu:

#define _DWORD int

no nie?

Mam nadzieje ze zbytnio nie namieszalem, jesli post jest chaotyczny to sorry, jutro poprawie.

0

Są, ale poukrywane głęboko w sejfach niektórych firm. Co lepsze autorskie mogą też mieć zrobione niektóry crackerzy. W obu wypadkach do ręki raczej nie dostaniesz. :)
Co do tych dziwnych wywołań, to są to normalne wywołania z metod polimorficznych C++ z tablic wirtualnych (tu do ogródka tych, którzy uważają, że programować obiektowo nie można z języków nieobiektowych). Aby uzyskać wskaźnik do metody trzeba wywołać pewną funkcję wyciągającą z obiektu wskaźnik do tablicy wirtualnej jego klasy, a stamtąd (też za pomocą innej funkcji) właściwy indeks wskaźnika. Dość łatwe do zrozumienia jak się skompiluje jakiś program w C++ za pomocą kompilatora front-end do C (wtedy nie giną oryginalne nazwy).

0

1: jak cos to edytowalem poprzedni post

2:Mozesz wyjasnic o co chodzi z tym kompilowaniem bez straty oryginalnych nazw? Jakis link? Pierwszy raz cos takiego widze

0

Co do tematu to mozna go zamknac. Wole jednak sobie analizowac kod asemblera, to jest o wiele czytelniejsze niz to co wypluwa dekompilator. A lepszego dekompilatora niz HexRays x86 decompiler raczej nie ma ;/

2

Swoją drogą, dość bogaty jesteś skoro możesz sobie wyrobić takie zdanie na temat Hex Rays :)

1
Olamagato napisał(a):

Są, ale poukrywane głęboko w sejfach niektórych firm. Co lepsze autorskie mogą też mieć zrobione niektóry crackerzy. W obu wypadkach do ręki raczej nie dostaniesz. :)

Gadasz durnoty, większość firm poważnie związanych z RE obecnie korzysta z IDA'y. Napisanie narzędzia, które by faktycznie z sensem służyło zastępom profesjonalistów wymaga zatrudnienia kolejnego zastępu profesjonalistów. Z racji tego, że dziedzina jest niszowa, to raczej za zwyczajową stawkę młodszego programisty Delphi nie będą chcieli pracować... Istnienie wielu takich wyspecjalizowanych narzędzi jest cholernie nieopłacalne.

Poza tym IDA ma dość dobre wsparcie techniczne i kupę mocnych pluginów jak np. Hexrays. Bardzo ciężko dostać coś wypaśniejszego od tego zestawu, o ile coś wypaśniejszego w ogóle istnieje na chwilę obecną. Tak czy siak, niezależnie od tego jak nie był by zajebiaszczy dekompilator to nie zinterpretuje on wszystkich konstrukcji i optymalizacji poprawnie tak jakbyś chciał (bo poprawność to inna sprawa) za jednym magicznym wciśnięciem F5, z Hexraysa też trzeba umieć korzystać ;)

nieczytelne tz. np sub_XXXXXX i ciezko odroznic jedna taka funkcje od drugiej; jak juz to wolalbym zeby generowalo cos w stylu sub1, sub2....

Te Twoje XXX to adres początku funkcji :| Przy czym możesz sobie dowolnie zmieniać ich nazwy i detale z poziomu IDA'y...

Nawet nie jestem w stanie tego odczytac - te wszystkie gwiazdki, nawiasy sie mi rozmywaja

Inwestuj w okulistę. Swoją drogą jeśli ogólnie chodzi o sam burdel - im mocniejszy optymalizator był wykorzystany przy kompilacji tym większy burdel będzie w zdekompilowanym kodzie jeśli dekompilator poprawnie tych optymalizacji nie rozpozna.

0

Ja nie mowie ze hex-rays jest zle, tylko po prostu dla mnie jest nieczytelne. Dla profesjonalistow pewnie jest bdb :P I te nazwy to jak powiedzialem, najmniejszy problem. Chodzi mi bardziej o to:

(*(void (__stdcall **)(_DWORD))(*LODWORD(dword_54FD30) + 128))(LODWORD(dword_54FD30));
(*(void (__cdecl **)(_DWORD, _DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Loading...", 0);
sub_4490C0();
(*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Starting...");
(*(void (__cdecl **)(_DWORD))(*LODWORD(dword_54FD30) + 12))(LODWORD(dword_54FD30));
(*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Clearing things...");
sub_41E4E0();
(*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Freeing objects...");
sub_448C70();
(*(void (__stdcall **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Freeing sounds...");
sub_43F4A0();
(*(void (__cdecl **)(_DWORD, _DWORD))(*LODWORD(dword_54FD30) + 20))(LODWORD(dword_54FD30), "Freeing textures...");
sub_449640();

nie powiesz mi, ze to jest czytelne. W takim wypadku da sie cos zrozumiec tylko patrzac na asembly.

0

nie powiesz mi, ze to jest czytelne. W takim wypadku da sie cos zrozumiec tylko patrzac na asembly.

A kto ci powiedział że kompilacja to proces odwracalny?!?!

Ty chyba oczekujesz że IDA zrobi ze wszystkiego rekordy, klasy, funkcje (nazwy i parametry), generyki. A prawda jest taka że tutaj dużo zgadywania jest, i stąd masz wyniki takie jakie masz. Ale ty wolisz oczekiwać niemożliwego.
Lepszych wyników i tak nie otrzymasz więc zastanów się nad tym czy w ogóle warto to do C konwertować. Łatwiej IMO jest zrobić jakieś hacki do swoich dodatków.

0

Co do uzywania deasemblera do mojego aktualnego celu - raczej odpada. Chce przepisac gre do czytelnego kodu C, tak zeby dzialala tak jak oryginal.

Pytanie - po co chcesz przepisywać grę do C?

Jeśli dla czystej zabawy i bez żadnego celu to OK, nic tu się nie wymyśli.
Jeśli chcesz tylko zmodyfikować jakąś jedną część gry (np. lamersko włączyć GodMode), to są prostsze sposoby i przepisywanie całej gry nie ma sensu.
Jeśli chcesz rozszerzyć grę/zmienić w znacznym stopniu, to jest ciekawiej. Nie robiłem czegoś takiego, ale ja bym uruchamiał grę normalnie i hookował wszystko co trzeba/co się da, opakował to w ładne, zdarzeniowe API, po czym kontrolował grę za pomocą tego.

Btw. ten kod który tak bez przerwy podajesz jest nie tyle nieczytelny, co po prostu HexRays najwidoczniej nie rozumie jakiegoś idiomu używanego przez kompilator - i wypisuje go dosłownie.
Rzutowanie na wskaźnik do funkcji i wywoływanie, to wygląda trochę jak metody wirtualne.

0

Jeśli chcesz rozszerzyć grę/zmienić w znacznym stopniu, to jest ciekawiej. Nie robiłem czegoś takiego, ale ja bym uruchamiał grę normalnie i hookował wszystko co trzeba/co się da, opakował to w ładne, zdarzeniowe API, po czym kontrolował grę za pomocą tego.

Generalnie jeśli tak na to patrzeć to zwykle z większym lub mniejszym trudem można injectnąć DLLkę, która hooknie wszystkie stosowne funkcje. Obecność debug stringów w binarce automatycznie taki proces znacznie ułatwia. Jeżeli gra faktycznie jest w oryginale w C++ to nawet system typów idzie częściowo odwzorować.

0

Mowilem ze temat do zamkniecia :P Juz niewazne, po prostu przeliczylem sie z mozliwosciami. Zaczne od podstaw,prostych crackme i przerobienia ogolnie manuali intela.

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