Zestaw szkoleniowy [zamknięty]

102

Postanowiłem nauczyć się języka asemblera. Głównym powodem jest zrozumienie zdemontowanego kodu i być może umiejętność pisania bardziej wydajnych części kodu (na przykład poprzez c ++), robienia takich rzeczy, jak jaskinie kodu itp. Widziałem, że istnieje milion różnych odmian asemblacji więc dla celów, o których wspomniałem, od czego mam zacząć? Jakiego montażu mam się nauczyć? Chcę się uczyć, robiąc najpierw jakieś proste programy (np. Kalkulator), ale celem samym w sobie będzie to, żeby się z nim zaczepić, abym mógł zrozumieć kod pokazany na przykład przez IDA Pro.

Używam okien (jeśli to robi różnicę).

edycja: Więc wydaje się, że wszyscy wskazują na MASM. Chociaż rozumiem, że ma możliwości na wysokim poziomie, wszystkie dobre dla programisty kodu asemblera, nie tego szukam. Wydaje się, że zawiera instrukcje if, invoke itp., Które nie są wyświetlane w popularnych programach deasemblacyjnych (takich jak IDA). Więc to, co chciałbym usłyszeć, jeśli to możliwe, to opinia każdego, kto używa ASM do celów, o które proszę (czytanie kodu zdemasemblowanego exe w IDA), a nie tylko "ogólnych" programistów assemblera.

edycja: OK. Już się uczę montażu. Uczę się MASM, nie używam rzeczy na wysokim poziomie, które nie mają dla mnie znaczenia. To, co teraz robię, to wypróbowywanie mojego kodu na dyrektywach __asm ​​w c ++, więc mogę wypróbowywać rzeczy znacznie szybciej niż gdybym musiał robić wszystko od zera z MASM.

pożarł elizjum
źródło
Podobne pytanie do stackoverflow.com/questions/1355524/ ...
TrueWill
Tak, ja też to czytałem. Powiedziałbym jednak, że moje pytanie jest bardziej „skoncentrowane”.
pożarł elizjum
Jeśli pracujesz w systemie Windows, celem (czyli procesorem, a więc zestawem instrukcji) jest x86 lub x86-64. Chyba że kupisz inną maszynę lub płytę MCU lub użyjesz emulatora. A więc pytanie, którego asemblera powinienem użyć? A może naprawdę pytasz, jaką architekturę wybrać? Osobiście uwielbiam ładne instrukcje ortogonalne ustawione na układach z serii m68k, niestety, niestety.
dmckee --- ex-moderator kitten
2
„Wygląda na to, że zawiera instrukcje if, invoke itp.” - To są makra („M” w „MASM”) i nie musisz ich używać, nawet jeśli asembler je obsługuje.
ChrisW,
3
Trudno było dać pytaniu 65. głos za, 64 to taka piękna liczba. . .
735 Tesla

Odpowiedzi:

40

Zacznij od MASM32, a następnie spójrz na FASM . Ale będziesz się dobrze bawić z MASM.

Noon Silk
źródło
Słyszałem od MASM. Jeśli się nie mylę, ma wiele funkcji „wysokiego poziomu”, których nie widzę, gdy patrzę na niespróbkowany kod. Chciałbym zaprogramować coś, co jest dokładnie takie, jak kod wyjściowy większości deasemblerów, jeśli ma to sens.
pożarł elizjum
1
Byłoby to w zasadzie jak pisanie kodów operacyjnych, które tak naprawdę nie ma sensu. Nauka MASM32 pomoże Ci zrozumieć, jak kod wygląda w debugerze. Możesz także sprawdzić OllyDbg: ollydbg.de
Noon Silk
7
Nie rozumiesz montażu. Musisz to zrozumieć. Kod operacji to liczba. Debugery będą próbowały rozwiązać kody operacyjne do swoich instrukcji (czasami jest to trudne). Musisz zrozumieć podstawowe instrukcje. Nauka MASM pomoże ci to zrobić. Nie trzeba już mówić.
Noon Silk
5
Nie musisz używać wszystkich funkcji MASM tylko dlatego, że one istnieją; możesz uczynić rzeczy tak trudnymi do czytania, jak chcesz, jeśli myślisz, że w ten sposób nauczysz się więcej.
JasonTrue
3
MASM, ze swoimi dziwactwami, błędami i tak zwanymi funkcjami wysokiego poziomu, zrobił więcej, aby zmylić programistów asemblera - zarówno początkujących, jak i ekspertów - bardziej niż cokolwiek, co przychodzi mi do głowy.
IJ Kennedy,
46

Robiłem to wiele razy i nadal to robię. W tym przypadku, gdy twoim głównym celem jest czytanie, a nie pisanie asemblera, czuję, że to ma zastosowanie.

Napisz swój własny deasembler. Nie w celu stworzenia kolejnego największego deasemblera, ten jest wyłącznie dla Ciebie. Celem jest nauczenie się zestawu instrukcji. Czy uczę się asemblera na nowej platformie, pamiętając asemblera dla platformy, którą kiedyś znałem. Zacznij od kilku wierszy kodu, dodając na przykład rejestry i ping-pongowanie między demontażem wyjścia binarnego a dodawaniem coraz bardziej skomplikowanych instrukcji po stronie wejściowej:

1) nauczyć się zestawu instrukcji dla konkretnego procesora

2) nauczyć się niuansów pisania kodu w asemblerze dla wspomnianego procesora, tak aby można było poruszać każdym bitem kodu operacji w każdej instrukcji

3) uczysz się zestawu instrukcji lepiej niż większość inżynierów, którzy używają go do zarabiania na życie

W twoim przypadku jest kilka problemów, zwykle polecam zestaw instrukcji ARM na początek, obecnie jest więcej dostarczanych produktów opartych na ARM niż jakichkolwiek innych (w tym komputery x86). Ale prawdopodobieństwo, że używasz teraz ARM i nie znasz wystarczająco asemblera, aby pisać kod startowy lub inne procedury, wiedząc, że ARM może, ale nie musi, pomóc w tym, co próbujesz zrobić. Drugim i ważniejszym powodem dla ARM jest to, że długości instrukcji mają stały rozmiar i są wyrównane. Demontaż instrukcji o zmiennej długości, takich jak x86, może być koszmarem jako pierwszy projekt, a celem jest tutaj nauczenie się zestawu instrukcji, aby nie tworzyć projektu badawczego. Trzeci ARM to dobrze wykonany zestaw instrukcji, rejestry są tworzone równo i nie mają indywidualnych specjalnych niuansów.

Musisz więc dowiedzieć się, od jakiego procesora chcesz zacząć. Proponuję najpierw msp430 lub ARM, potem ARM najpierw lub drugi, a potem chaos x86. Bez względu na platformę, każda platforma, z której warto korzystać, ma arkusze danych lub podręczniki programistów wolne od dostawcy, które zawierają zestaw instrukcji, a także kodowanie kodów operacyjnych (bity i bajty języka maszynowego). Aby dowiedzieć się, co robi kompilator i jak napisać kod, z którym kompilator nie musi się zmagać, dobrze jest znać kilka zestawów instrukcji i zobaczyć, jak ten sam kod wysokiego poziomu jest implementowany w każdym zestawie instrukcji z każdym kompilatorem z każdą optymalizacją oprawa. Nie chcesz zajmować się optymalizacją kodu tylko po to, aby stwierdzić, że ulepszyłeś go dla jednego kompilatora / platformy, ale znacznie gorzej dla wszystkich innych.

Aha do deasemblacji zestawów instrukcji o zmiennej długości, zamiast po prostu zaczynać od początku i deasemblować każde czterobajtowe słowo liniowo przez pamięć, tak jak w przypadku ARM lub co dwa bajty, jak w przypadku msp430 (msp430 ma instrukcje o zmiennej długości, ale nadal możesz sobie z tym poradzić przechodzenie liniowo przez pamięć, jeśli zaczniesz od punktów wejścia z tablicy wektorów przerwań). Dla zmiennej długości chcesz znaleźć punkt wejścia na podstawie tabeli wektorów lub wiedzy o tym, jak uruchamia się procesor i postępować zgodnie z kodem w kolejności wykonania. Musisz całkowicie zdekodować każdą instrukcję, aby wiedzieć, ile bajtów jest używanych, a następnie, jeśli instrukcja nie jest bezwarunkową gałęzią, załóżmy, że następny bajt po tej instrukcji jest kolejną instrukcją. Musisz również przechowywać wszystkie możliwe adresy oddziałów i założyć, że są to początkowe adresy bajtów, aby uzyskać więcej instrukcji. Pewnego razu udało mi się wykonać kilka przejść przez plik binarny. Zaczynając od punktu wejścia, oznaczyłem ten bajt jako początek instrukcji, a następnie dekodowałem liniowo przez pamięć, aż trafiłem do gałęzi bezwarunkowej. Wszystkie cele gałęzi zostały oznaczone jako adresy początkowe instrukcji. Wykonałem wiele przejść przez plik binarny, dopóki nie znalazłem żadnych nowych celów gałęzi. Jeśli w jakimkolwiek momencie napotkasz instrukcję 3-bajtową, ale z jakiegoś powodu oznaczyłeś drugi bajt jako początek instrukcji, masz problem. Jeśli kod został wygenerowany przez kompilator wysokiego poziomu, nie powinno to mieć miejsca, chyba że kompilator robi coś złego, jeśli kod ma ręcznie napisany asembler (jak powiedzmy stara gra zręcznościowa), jest całkiem możliwe, że będą rozgałęzienia warunkowe, które nigdy nie mogą się wydarzyć, jak r0 = 0, po których nastąpi skok, jeśli nie zero. Być może będziesz musiał ręcznie edytować te z pliku binarnego, aby kontynuować. Dla twoich bezpośrednich celów, które zakładam, że będą na x86, nie sądzę, że będziesz miał problem.

Polecam narzędzia gcc, mingw32 to łatwy sposób na użycie narzędzi gcc w systemie Windows, jeśli Twoim celem jest x86. Jeśli nie, mingw32 plus msys jest doskonałą platformą do generowania kompilatora krzyżowego ze źródeł binutils i gcc (ogólnie całkiem łatwe). mingw32 ma pewne zalety w stosunku do cygwin, takie jak znacznie szybsze programy i unikasz piekła dll cygwin. gcc i binutils pozwolą ci pisać w C lub asemblerze i demontować twój kod, a jest więcej stron internetowych niż możesz przeczytać, pokazujących, jak zrobić jedną lub wszystkie trzy. Jeśli masz zamiar robić to z zestawem instrukcji o zmiennej długości, bardzo polecam użycie zestawu narzędzi, który zawiera dezasembler. Na przykład program do deasemblacji innej firmy dla x86 będzie wyzwaniem, ponieważ nigdy nie wiadomo, czy został on poprawnie zdemontowany. Niektóre z nich są również zależne od systemu operacyjnego, celem jest skompilowanie modułów do formatu binarnego, który zawiera instrukcje oznaczania informacji z danych, aby dezasembler mógł wykonać dokładniejszą pracę. Innym wyborem dla tego głównego celu jest posiadanie narzędzia, które można skompilować bezpośrednio do asemblera w celu inspekcji, a następnie mieć nadzieję, że gdy kompiluje się do formatu binarnego, tworzy te same instrukcje.

Krótka (dobrze trochę krótsza) odpowiedź na Twoje pytanie. Napisz dezasembler, aby nauczyć się zestawu instrukcji. Zacząłbym od czegoś RYZYKOWEGO i łatwego do nauczenia, takiego jak ARM. Gdy już znasz jeden zestaw instrukcji, inne stają się znacznie łatwiejsze do przyswojenia, często w ciągu kilku godzin, dzięki trzeciemu zestawowi instrukcji możesz prawie natychmiast rozpocząć pisanie kodu, korzystając z arkusza danych / instrukcji obsługi składni. Wszystkie procesory, których warto używać, mają arkusz danych lub podręcznik referencyjny, który opisuje instrukcje z dokładnością do bitów i bajtów opkodów. Naucz się procesora RISC, takiego jak ARM i CISC, takiego jak x86, na tyle, aby poczuć różnice, takie jak konieczność przechodzenia przez rejestry dla wszystkiego lub możliwość wykonywania operacji bezpośrednio na pamięci z mniejszą liczbą rejestrów lub bez nich. Trzy instrukcje operandów kontra dwie itd. Podczas strojenia kodu wysokiego poziomu, skompilować dla więcej niż jednego procesora i porównać dane wyjściowe. Najważniejszą rzeczą, której się nauczysz, jest to, że bez względu na to, jak dobrze napisano kod wysokiego poziomu, jakość kompilatora i dokonane wybory optymalizacyjne mają ogromny wpływ na rzeczywiste instrukcje. Polecam llvm i gcc (z binutils), żadna z nich nie produkujeświetny kod, ale są one przeznaczone dla wielu platform i dla wielu celów i oba mają optymalizatory. Oba są bezpłatne i można łatwo tworzyć kompilatory krzyżowe ze źródeł dla różnych procesorów docelowych.

old_timer
źródło
Dziękuję za odpowiedź. Ale ja nawet nie wiem, jak napisać deasembler.
pożarł elizjum
8
„Napisz swój własny deasembler” - zgadzam się, tak się tego nauczyłem. (O co chodzi z „Ale ja nawet nie wiem, jak napisać deasembler”?) LOL.
slashmais
Idę z Tobą! Właśnie kupiłem MSP430 i książkę na nim ... :)
Pepe
1
Mam kilka przykładów msp430 github.com/dwelch67 plus kilka symulatorów zestawu instrukcji do eksperymentowania z uczeniem się asm itp.
old_timer
Bardzo, bardzo podoba mi się ten pomysł.
Millie Smith
34

Zestaw, który napisałbyś ręcznie, i zestaw wygenerowany przez kompilator są często bardzo różne, gdy ogląda się je z wysokiego poziomu. Oczywiście wnętrze programu będzie bardzo podobne (w końcu jest tylko tyle różnych sposobów kodowania a = b + c), ale nie stanowią problemu, gdy próbujesz coś odtworzyć. Kompilator doda mnóstwo kodu Gotowa do nawet prostych plików wykonywalnych: ostatni raz w porównaniu „Hello World” opracowany przez GCC wynosiła około 4kB, a jeśli pisane ręcznie w montażu to około 100 bajtów. Gorzej jest na Windowsie: ostatni raz porównywałem (trzeba przyznać, że to było w zeszłym wieku) najmniejszy "Hello World" jaki mogłem wygenerować mój kompilator Windows, który wtedy wybierał, to 52kB! Zwykle ten szablon jest wykonywany tylko raz, jeśli w ogóle, więc nie wpływa to zbytnio na szybkość programu - tak jak powiedziałem powyżej, rdzeń programu, część, w której spędza się najwięcej czasu wykonania, jest zwykle bardzo podobny, niezależnie od tego, czy jest skompilowany, czy napisane ręcznie.

Ostatecznie oznacza to, że ekspert programista montażu i ekspert deasembler to dwie różne specjalności. Zwykle występują u tej samej osoby, ale są naprawdę oddzielne, a nauczenie się, jak być doskonałym koderem w asemblerze, nie pomoże ci zbytnio nauczyć się inżynierii odwrotnej.

To, co chcesz zrobić, to pobrać podręczniki architektury IA-32 i AMD64 (oba są omówione razem) od Intel i AMD i przejrzeć wczesne sekcje dotyczące instrukcji i kodów operacyjnych. Może przeczytaj kilka tutoriali na temat języka asemblera, żeby poznać podstawy języka asemblera. Następnie weź małyprzykładowy program, który Cię interesuje, i zdemontuj go: przejdź przez jego przepływ sterowania i spróbuj zrozumieć, co robi. Sprawdź, czy możesz go załatać, aby zrobić coś innego. Następnie spróbuj ponownie z innym programem i powtarzaj, aż poczujesz się na tyle komfortowo, aby spróbować osiągnąć bardziej użyteczny cel. Możesz być zainteresowany takimi rzeczami, jak "crackmes", tworzone przez społeczność inżynierii odwrotnej, które są wyzwaniem dla osób zainteresowanych inżynierią wsteczną, które mogą spróbować swoich sił i miejmy nadzieję, że nauczą się czegoś po drodze. Różnią się one poziomem trudności od podstawowego (zacznij tutaj!) Do niemożliwego.

Przede wszystkim musisz po prostu ćwiczyć . Podobnie jak w wielu innych dyscyplinach, w przypadku inżynierii odwrotnej praktyka czyni mistrza ... a przynajmniej lepiej .

kquinn
źródło
Wiem, że kiedy kompilujesz cokolwiek w języku wysokiego poziomu, otrzymasz dużo „śmieciowego” kodu, który nie byłby potrzebny, gdybyś został zakodowany bezpośrednio w asemblerze. Rozumiem też, że istnieje różnica między doświadczonym programistą w montażu a ekspertem w dezasemblacji. Ale to samo można powiedzieć o prawie wszystkim innym.
pożarł elysium
3
Martwię się, że chociaż teoretycznie mógłbym przeczytać artykuły i zrozumieć, co one znaczą, dopóki sam nie zacznę pisać, nie wierzę, że naprawdę to zrozumiem. Mówisz, że mogę zacząć od zmiany małych części kodu, ale aby to zrobić, najpierw muszę wiedzieć, jakiego rodzaju "smak" zespołu używa na przykład IDA pro.
pożarł elysium
Ponadto, czego używa MSVC ++ dla wbudowanego kodu asemblera? MASM?
pożarł elizjum
15

Będę pod prąd większości odpowiedzi i polecam wariant MMIX architektury MIPS RISC firmy Knuth . Nie będzie tak praktyczny, jak języki asemblera x86 lub ARM (nie żeby były one tak ważne w dzisiejszych czasach w większości codziennych zadań ... ;-), ale odblokuje dla ciebie magię najnowszego Knutha wersja największego w historii arcydzieła poświęconego głębokiemu zrozumieniu algorytmów i struktur danych na niskim poziomie - TAOCP , „The Art of Computer Programming”. Linki z dwóch podanych przeze mnie adresów URL to świetny sposób na rozpoczęcie odkrywania tej możliwości!

Alex Martelli
źródło
12

(Nie wiem jak Ty, ale byłem podekscytowany montażem)

Proste narzędzie do eksperymentowania z montażem jest już zainstalowane na twoim komputerze.

Przejdź do menu Start-> Uruchom i wpiszdebug

debugowanie (polecenie)

debug to polecenie w DOS, MS-DOS, OS / 2 i Microsoft Windows (tylko wersje x86, nie x64), które uruchamia program debug.exe (lub DEBUG.COM w starszych wersjach DOS). Debugowanie może działać jako asembler, deasembler lub program zrzutu szesnastkowego, umożliwiając użytkownikom interaktywne badanie zawartości pamięci (w języku asemblera, szesnastkowym lub ASCII), wprowadzanie zmian i wybiórcze wykonywanie plików COM, EXE i innych typów. Posiada również kilka podkomend, które są używane do uzyskiwania dostępu do określonych sektorów dysku, portów we / wy i adresów pamięci. Debugowanie MS-DOS działa na 16-bitowym poziomie procesu i dlatego jest ograniczone do 16-bitowych programów komputerowych . FreeDOS Debug ma wersję „DEBUGX” obsługującą również 32-bitowe programy DPMI.

Poradniki:


Jeśli chcesz zrozumieć kod, który widzisz w IDA Pro (lub OllyDbg ), musisz dowiedzieć się, jak zbudowany jest skompilowany kod. Polecam książkę Reversing: Secrets of Reverse Engineering

Eksperymentowałem przez kilka tygodni, debugkiedy zacząłem uczyć się asemblera (15 lat temu).
Zauważ, że debugdziała na poziomie maszyny podstawowej, nie ma poleceń zespołu wysokiego poziomu.

A teraz prosty przykład:

Daj azacząć pisać kod asemblera - wpisz poniższy program - i na koniec daj ggo uruchomić.

tekst alternatywny


( INT 21wyświetla na ekranie znak ASCII zapisany w DLrejestrze, jeśli AHrejestr jest ustawiony na 2- INT 20kończy program)

Nick Dandoulakis
źródło
Musiałem wcisnąć ctrl-c, zanim mogłem wpisać „g”.
ericp,
2
@ericp, nie musisz naciskać ctrl-c. Na przykład wpisz a& [enter], aby rozpocząć pisanie kodu asemblera. Jeśli naciśniesz [enter] dwa razy, wyjdziesz z trybu asemblacji. g& [enter], aby go uruchomić (domyślnie przesunięcie 100).
Nick Dandoulakis
czy faktycznie powoduje przepełnienie stosu, czy po prostu zapisuje go na ekranie?
Janus Troelsen
1
@user, po prostu wpisuje nazwę tej strony :-)
Nick Dandoulakis
@JanusTroelsen te liczby (53, 74, 61, itd.) To kody ASCII dla 'S' 't' 'a' ... Każde wywołanie Int21 wypisuje po jednym znaku! Dlatego montaż NIE jest szybszy :)
doug65536
8

Uważam, że Hacking: The Art of Exploitation to ciekawy i użyteczny sposób na poruszanie się w tym temacie ... Nie mogę powiedzieć, że kiedykolwiek korzystałem z tej wiedzy bezpośrednio, ale tak naprawdę nie po to ją przeczytałem. Zapewnia znacznie lepsze zrozumienie instrukcji, do których kompiluje się Twój kod, co czasami jest przydatne w zrozumieniu subtelniejszych błędów.

Nie zniechęcaj się tytułem. Większa część pierwszej części książki to „hakowanie” w sensie tego słowa autorstwa Erica Raymonda: kreatywne, zaskakujące, prawie podstępne sposoby rozwiązywania trudnych problemów. Ja (a może i ty) byłem dużo mniej zainteresowany aspektami bezpieczeństwa.

mblackwell8
źródło
8

Nie skupiałbym się na próbach pisania programów w asemblerze, przynajmniej nie na początku. Jeśli korzystasz z x86 (którym, jak zakładam, jesteś, ponieważ używasz systemu Windows), istnieje mnóstwo dziwnych, specjalnych przypadków, których nie ma sensu się uczyć. Na przykład wiele instrukcji zakłada, że ​​działasz na rejestrze, którego nie nazwałeś wyraźnie, a inne instrukcje działają na niektórych rejestrach, ale nie na innych.

Dowiedziałbym się wystarczająco o planowanej architekturze, abyś zrozumiał podstawy, a następnie po prostu wskoczył i spróbował zrozumieć wyjście kompilatora. Uzbrój się w podręczniki Intel i po prostu zanurz się w wynikach swojego kompilatora. Wyodrębnij interesujący kod do małej funkcji, aby mieć pewność, że wszystko zrozumiesz.

Uznałbym podstawy za:

  • rejestry: ile ich jest, jak się nazywają i jakie są ich rozmiary?
  • kolejność operandów: add eax, ebxoznacza „Dodaj ebx do eax i zapisz wynik w eax”.
  • FPU: poznaj podstawy stosu zmiennoprzecinkowego i przekonwertuj na / z fp.
  • tryby adresowania: [podstawa + przesunięcie * mnożnik], ale mnożnik może wynosić tylko 1, 2 lub 4 (a może 8?)
  • konwencje wywoływania: w jaki sposób parametry są przekazywane do funkcji?

W większości przypadków będzie zaskakujące, co emituje kompilator. Zrób z tego zagadkę, aby dowiedzieć się, dlaczego do cholery kompilator pomyślał, że to dobry pomysł. To cię wiele nauczy.

Prawdopodobnie pomoże to również uzbroić się w podręczniki Agner Fog , szczególnie w opisie jednej instrukcji. Powie ci z grubsza, jak kosztowna jest każda instrukcja, chociaż jest to trudniejsze do bezpośredniego oszacowania na nowoczesnych procesorach. Ale pomoże to wyjaśnić, na przykład, dlaczego kompilator robi tak daleko, aby uniknąć wydawania idivinstrukcji.

Moją jedyną radą jest to, aby zawsze używać składni Intela zamiast AT&T, kiedy masz wybór. Kiedyś byłem dość neutralny w tej kwestii, aż do dnia, w którym zdałem sobie sprawę, że niektóre instrukcje są całkowicie różne między nimi (na przykład movslqw składni AT&T jest movsxdskładnia Intel). Ponieważ wszystkie podręczniki są napisane przy użyciu składni Intela, po prostu trzymaj się tego.

Powodzenia!

Josh Haberman
źródło
4

Zacząłem od nauki MIPS, który jest bardzo kompaktową architekturą 32-bitową. Jest to zredukowany zestaw instrukcji, ale to ułatwia zrozumienie początkującym. Nadal będziesz w stanie zrozumieć, jak działa montaż, bez przytłaczania złożonością. Możesz nawet pobrać fajne, małe IDE, które pozwoli ci skompilować swój kod MIPS: clicky Kiedy już to zrozumiesz, myślę, że byłoby znacznie łatwiej przejść do bardziej złożonych architektur. Tak przynajmniej myślałem :) W tym momencie będziesz miał podstawową wiedzę na temat alokacji i zarządzania pamięcią, przepływu logiki, debugowania, testowania itp.


źródło
4

Sugestia użycia debugowania jest fajna, można z nią zrobić wiele fajnych sztuczek. Jednak w przypadku nowoczesnego systemu operacyjnego uczenie się asemblacji 16-bitowej może być nieco mniej przydatne. Zamiast tego rozważ użycie ntsd.exe. Jest wbudowany w system Windows XP (niestety został wycofany w wersji Server 2003 i nowszych), co czyni go wygodnym narzędziem do nauki, ponieważ jest tak powszechnie dostępny.

To powiedziawszy, oryginalna wersja w XP zawiera wiele błędów. Jeśli naprawdę chcesz go używać (lub cdb lub windbg, które są zasadniczo różnymi interfejsami z tą samą składnią poleceń i zapleczem debugowania), powinieneś zainstalować bezpłatny pakiet narzędzi do debugowania systemu Windows .

Plik debugger.chm zawarty w tym pakiecie jest szczególnie przydatny podczas próby odgadnięcia nietypowej składni.

Wspaniałą rzeczą w ntsd jest to, że możesz go wyskoczyć na dowolnej maszynie XP, którą jesteś w pobliżu i użyć go do montażu lub demontażu. To sprawia, że ​​/ świetne / X86 narzędzie do nauki montażu. Na przykład (używając cdb, ponieważ jest on umieszczony w wierszu poleceń, poza tym jest identyczny):

(pomijane błędy symboli, ponieważ są nieistotne - mam również nadzieję, że to formatowanie działa, to jest mój pierwszy post)

C:\Documents and Settings\User>cdb calc

Microsoft (R) Windows Debugger Version 6.10.0003.233 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: calc
Symbol search path is: *** Invalid ***
Executable search path is:
ModLoad: 01000000 0101f000   calc.exe
ModLoad: 7c900000 7c9b2000   ntdll.dll
ModLoad: 7c800000 7c8f6000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 7c9c0000 7d1d7000   C:\WINDOWS\system32\SHELL32.dll
ModLoad: 77dd0000 77e6b000   C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77e70000 77f02000   C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 77fe0000 77ff1000   C:\WINDOWS\system32\Secur32.dll
ModLoad: 77f10000 77f59000   C:\WINDOWS\system32\GDI32.dll
ModLoad: 7e410000 7e4a1000   C:\WINDOWS\system32\USER32.dll
ModLoad: 77c10000 77c68000   C:\WINDOWS\system32\msvcrt.dll
ModLoad: 77f60000 77fd6000   C:\WINDOWS\system32\SHLWAPI.dll
(f2c.208): Break instruction exception - code 80000003 (first chance)
eax=001a1eb4 ebx=7ffd6000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4
eip=7c90120e esp=0007fb20 ebp=0007fc94 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c90120e cc              int     3
0:000> r eax
eax=001a1eb4
0:000> r eax=0
0:000> a eip
7c90120e add eax,0x100
7c901213
0:000> u eip
ntdll!DbgBreakPoint:
7c90120e 0500010000      add     eax,100h
7c901213 c3              ret
7c901214 8bff            mov     edi,edi
7c901216 8b442404        mov     eax,dword ptr [esp+4]
7c90121a cc              int     3
7c90121b c20400          ret     4
ntdll!NtCurrentTeb:
7c90121e 64a118000000    mov     eax,dword ptr fs:[00000018h]
7c901224 c3              ret
0:000> t
eax=00000100 ebx=7ffd6000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4
eip=7c901213 esp=0007fb20 ebp=0007fc94 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ntdll!DbgUserBreakPoint+0x1:
7c901213 c3              ret
0:000>`

Ponadto - grając z IDA, koniecznie sprawdź IDA Pro Book autorstwa Chrisa Eagle (niepowiązane, ponieważ StackOverflow nie chce pozwolić mi opublikować więcej niż dwóch linków do mojego pierwszego postu). To bez wątpienia najlepsze odniesienie.

Jordania
źródło
1
+1 za książkę Chrisa Eagle. Muszę włożyć trochę miłości do Sk3wl z r00t;)
mrduclaw
4

Niedawno wziąłem udział w zajęciach z systemów komputerowych. Jednym z tematów był montaż jako narzędzie do komunikacji ze sprzętem.

Dla mnie znajomość montażu nie byłaby pełna bez zrozumienia szczegółów działania systemów komputerowych. Zrozumienie tego pozwala na nowe zrozumienie, dlaczego instrukcje asemblacji na jednej architekturze procesora są świetne, ale okropne na innej architekturze.

Biorąc to pod uwagę, jestem skłonny polecić mój podręcznik klasowy:

Systemy komputerowe: perspektywa programisty .

Systemy komputerowe: perspektywa programisty
(źródło: cmu.edu )

Obejmuje montaż x86, ale książka jest znacznie szersza. Obejmuje układanie potoku procesora i pamięć jako pamięć podręczną, system pamięci wirtualnej i wiele więcej. Wszystko to może wpływać na sposób optymalizacji zespołu dla danych funkcji.

Frank V
źródło
3

Myślę, że chcesz nauczyć się mnemoników kodu operacji w formacie ASCII (i ich parametrów), które są wyświetlane przez dezasembler i które są rozumiane przez asemblera (mogą być używane jako dane wejściowe).

Każdy asembler (np. MASM) by zrobił.

I / lub może lepiej byłoby, gdybyś przeczytał książkę na ten temat (na SO były polecane książki, nie pamiętam które).

ChrisW
źródło
3

Czy wykonujesz inne prace deweloperskie w systemie Windows? Na którym IDE? Jeśli jest to VS, nie ma potrzeby dodatkowego IDE, aby odczytać zdemontowany kod: debuguj aplikację (lub dołącz do aplikacji zewnętrznej), a następnie otwórz okno dezasemblacji (w ustawieniach domyślnych jest to Alt + 8). Przechodź i obserwuj pamięć / rejestry tak, jak w przypadku normalnego kodu. Możesz także chcieć pozostawić otwarte okno rejestrów (domyślnie Alt + 5).

Firma Intel udostępnia bezpłatne podręczniki , które zawierają zarówno przegląd podstawowej architektury (rejestry, jednostki procesora itp.), Jak i pełne odniesienie do instrukcji. Ponieważ architektura dojrzewa i staje się coraz bardziej złożona, podręczniki dotyczące „podstawowej architektury” stają się coraz mniej czytelne. Jeśli możesz zdobyć starszą wersję, prawdopodobnie będziesz miał lepsze miejsce do rozpoczęcia (nawet podręczniki P3 - lepiej wyjaśniają to samo podstawowe środowisko wykonawcze).

Jeśli chcesz zainwestować w książkę, oto ładny tekst wprowadzający. Wyszukaj w serwisie Amazon „x86”, a otrzymasz wiele innych. Możesz uzyskać kilka innych wskazówek z innego pytania tutaj .

Wreszcie, można skorzystać trochę z przeczytaniu niektórych niski - poziom blogów. Osobiście najlepiej sprawdzają się te bity informacji o rozmiarze bajtów.

Ofek Shilon
źródło
3

Niekoniecznie pomoże to w pisaniu wydajnego kodu!

Kody operacyjne i86 są mniej więcej „starszym” formatem, który utrzymuje się ze względu na ogromną ilość kodu i wykonywalnych plików binarnych dla systemów Windows i Linux.

To trochę tak, jak dawni uczeni piszący po łacinie, włoski mówca, taki jak Galileo, pisałby po łacinie, a jego artykuł byłby zrozumiały dla osoby mówiącej po polsku, takiej jak Kopernik. Wciąż był to najskuteczniejszy sposób porozumiewania się, mimo że niether szczególnie dobrze władał łaciną, a łacina jest beznadziejnym językiem do wyrażania pomysłów matematycznych.

Kompilatory generują więc domyślnie kod x86, a nowoczesne chipy odczytują kody operacyjne rodów i przekształcają to, co widzą, na równoległe instrukcje risc, z reorganizacją wykonania, wykonaniem spekulacyjnym, potokowaniem itp., A ponadto w pełni wykorzystują 32 lub 64 rejestry procesora faktycznie ma (w przeciwieństwie do żałosnej 8, którą widzisz w instrukcjach x86).

Teraz wszystkie optymalizujące kompilatory wiedzą, że tak się naprawdę dzieje, więc kodują sekwencje kodów OP, które, jak wiedzą, chip może skutecznie zoptymalizować - nawet jeśli niektóre z tych sekwencji wyglądałyby na nieskuteczne dla programisty .asm z około 1990 roku.

W pewnym momencie musisz zaakceptować fakt, że dziesiątki tysięcy lat pracy włożonych przez twórców kompilatorów opłaciło się i możesz im zaufać.

Najprostszym i najłatwiejszym sposobem uzyskania wydajniejszego środowiska wykonawczego jest zakup kompilatora Intel C / C ++. Mają niszowy rynek dla efektywnych kompilatorów i mają tę przewagę, że mogą zapytać projektantów chipów o to, co się dzieje w środku.

James Anderson
źródło
Twoja historia sugeruje nieco, że procesory CISC wewnętrznie stały się procesorami RISC. Może źle zrozumiałem, ale to po prostu nieprawda. A żałosne 8? Nowoczesne procesory (powiedzmy od 1999 r.) Obejmują znacznie więcej: 10 gpr: EAX-EFLAGS, 80 bitów FP0-FP7, 64-bitowych MMX0-MMX7, 128-bitowych XMM0-XMM7, segment: CS-GS, oferty specjalne: CR0-CR4 , DR0-DR7, TR3-TR7, GDTR, IDTR, LDTR, MSR, a na x86-64 także R8-R15. Nie wszystkie z nich są dostępne z ring-3, ale większość jest i większość jest używana przez najnowsze (po 2006) kompilatory GCC / VC ++. W sumie nieco więcej niż „żałosna ósemka”;).
Abel
3

Aby zrobić to, co chcesz, po prostu wziąłem zestaw instrukcji Intel (może nie być dokładnie tym, którego użyłem, ale wygląda wystarczająco) i kilka prostych programów, które napisałem w Visual Studio i zacząłem wrzucać je do IDAPro / Windbg . Kiedy wyrosłem z własnych programów, oprogramowanie w crackmes było pomocne.

Zakładam, że masz podstawową wiedzę na temat działania programów w systemie Windows. Ale tak naprawdę, do czytania asemblera jest tylko kilka instrukcji do nauczenia się i kilka odmian tych instrukcji (np. Jest instrukcja skoku, skok ma kilka smaków, takich jak skok-jeśli-równy, skok-jeśli-ecx-jest-zero itp.). Gdy już nauczysz się podstawowych instrukcji, łatwo jest zrozumieć istotę wykonywania programu. Widok wykresu IDA pomaga, a jeśli śledzisz program za pomocą Windbg, dość łatwo jest dowiedzieć się, co robią instrukcje, jeśli nie masz pewności.

Po takiej zabawie kupiłem Hacker Disassembly Uncovered . Generalnie trzymam się z daleka od książek ze słowem „Hacker” w tytule, ale naprawdę podobało mi się, jak ten dogłębnie wyjaśnił, jak skompilowany kod wyglądał na zdemontowany. Zajmuje się również optymalizacją kompilatora i niektórymi interesującymi sprawami dotyczącymi wydajności.

Wszystko tak naprawdę zależy od tego, jak bardzo chcesz również zrozumieć program. Jeśli przeprowadzasz inżynierię wsteczną celu szukającego luk w zabezpieczeniach, jeśli piszesz kod wykorzystujący lukę lub analizujesz spakowane złośliwe oprogramowanie pod kątem możliwości, będziesz potrzebować więcej czasu na uruchomienie, aby naprawdę działać (szczególnie w przypadku bardziej zaawansowanego złośliwego oprogramowania ). Z drugiej strony, jeśli chcesz po prostu zmienić poziom swojej postaci w swojej ulubionej grze wideo, powinieneś radzić sobie dobrze w stosunkowo krótkim czasie.

mrduclaw
źródło
2

Jednym ze standardowych pedagogicznych języków asemblera jest MIPS. Możesz zdobyć symulatory MIPS (spim) i różne materiały dydaktyczne.

Osobiście nie jestem fanem. Raczej lubię IA32.

Paul Nathan
źródło
MIPS jest fajny. 68000 też jest i jeśli nauczysz się 68000, możesz pisać pliki binarne, które działają w MAME. :-)
Nosredna
2

Moim ulubionym jest NASM, głównie dlatego, że jest wieloplatformowy i kompiluje MMX, SSE, 64-bit ...

Zacząłem kompilować prosty plik źródłowy C za pomocą gcc i „transkodować” instrukcję asemblera z formatu gcc na format NASM. Następnie możesz zmienić małe fragmenty kodu i zweryfikować poprawę wydajności, jaką przynosi.

Dokumentacja NASM jest naprawdę kompletna, nigdy nie musiałem szukać informacji w książkach lub innych źródłach.

GB
źródło
1

Wiele dobrych odpowiedzi. Programowanie niskopoziomowe, asemblacja itp. Są popularne w społeczności zajmującej się bezpieczeństwem, dlatego warto poszukać tam wskazówek i wskazówek, gdy już zaczniesz. Mają nawet dobre samouczki, takie jak ten dotyczący asemblacji x86 .

Brian Lyttle
źródło
1

Nauczyliśmy się montażu za pomocą zestawu rozwojowego mikrokontrolera (Motorola HC12) i grubego arkusza danych.

ciebie
źródło
0

Aby faktycznie osiągnąć swój cel, możesz rozważyć rozpoczęcie od IDE, w którym się znajdujesz. Ogólnie jest to okno dezasemblera, więc możesz wykonać pojedyncze przejście przez kod. Zwykle jest jakiś widok, który pozwala zobaczyć rejestry i zajrzeć do obszarów pamięci.

Badanie niezoptymalizowanego kodu C / C ++ pomoże zbudować link do rodzaju kodu, który kompilator generuje dla Twoich źródeł. Niektóre kompilatory mają jakieś zarezerwowane słowo ASM, które umożliwia wstawianie instrukcji maszynowych do kodu.

Radziłbym pobawić się przez chwilę tego rodzaju narzędziami i zmoczyć stopy, a następnie zejść na górę? na dół? do prostego kodu asemblera na każdej platformie, na której pracujesz.

Istnieje wiele świetnych narzędzi, ale może ci się to przydać, aby na początku uniknąć stromej krzywej uczenia się.

EvilTeach
źródło
0

Wiem, że nie na temat, ale ponieważ jesteś programistą Windows, nie mogę się powstrzymać od myśli, że może to być bardziej odpowiednie i / lub lepsze wykorzystanie twojego czasu na naukę MSIL. Nie, to nie jest montaż, ale prawdopodobnie jest bardziej odpowiedni w erze .NET.

slf
źródło
0

Znajomość asemblera może być przydatna do debugowania, ale nie byłbym zbyt podekscytowany używaniem go do optymalizacji kodu. Współczesne kompilatory są obecnie znacznie lepsze w optymalizacji niż ludzie.

Adam Pierce
źródło
Hmm. Nadal możesz samodzielnie wycisnąć trochę dodatkowego zestawu kodującego, ale pokonanie kompilatora wymaga więcej pracy niż kiedyś.
Nosredna
0

Możesz obejrzeć kurs wideo xorpd x86 Assembly . (Napisałem to). Sam kurs jest płatny, ale ćwiczenia są dostępne na githubie. Jeśli masz jakieś doświadczenie w programowaniu, myślę, że powinieneś być w stanie pracować tylko z ćwiczeniami i wszystko rozumieć.

Zauważ, że kod jest przeznaczony dla platformy Windows i jest napisany przy użyciu asemblera Fasm . Kurs i ćwiczenia nie zawierają żadnych konstrukcji wysokiego poziomu, jednak możesz użyć Fasm do tworzenia bardzo skomplikowanych makr, jeśli kiedykolwiek zechcesz.

xorpd
źródło