Assemblea didattica [chiusa]


102

Ho deciso di imparare il linguaggio Assembly. Il motivo principale per farlo è essere in grado di comprendere il codice disassemblato e forse essere in grado di scrivere parti di codice più efficienti (ad esempio, tramite c ++), fare cose come code cave, ecc. Ho visto che ci sono un'infinità di diversi tipi di assembly , quindi, per gli scopi che menziono, come devo iniziare? Che tipo di assemblaggio dovrei imparare? Voglio imparare facendo prima alcuni programmi facili (es. Una calcolatrice), ma l'obiettivo stesso sarà quello di abituarmi ad esso in modo da poter capire il codice mostrato, ad esempio, da IDA Pro.

Sto usando Windows (se questo fa la differenza).

edit: Quindi, sembra che tutti stiano puntando verso MASM. Anche se ho capito che ha capacità di alto livello, tutte buone per il programmatore di codice assembly, non è quello che sto cercando. Sembra che abbia istruzioni if, invoke, ecc. Non mostrate nei disassemblatori popolari (come IDA). Quindi quello che mi piacerebbe sentire, se possibile, è l'opinione di chiunque usi ASM per gli scopi che sto chiedendo (leggendo il codice exe disassemblato in IDA), non solo dei programmatori di assembly "generali".

modifica: OK. Sto già imparando l'assemblaggio. Sto imparando MASM, non usando roba di alto livello che non mi importa. Quello che sto facendo in questo momento è provare il mio codice sulle direttive __asm ​​in c ++, così posso provare le cose molto più velocemente che se dovessi fare tutto da zero con MASM.



Sì, stavo leggendo anche quello. Ma la mia domanda è un po 'più "mirata", direi.
elisio divorato

Se sei su Windows il target (che è il processore, e quindi il set di istruzioni) è x86 o x86-64. A meno che tu non abbia un'altra macchina o una scheda MCU o usi un emulatore. Quindi, la domanda è quale assemblatore dovrei usare? O ti stai davvero chiedendo quale architettura scegliere? Personalmente adoro le belle istruzioni ortogonali impostate sui chip della serie m68k, ahimè, ahimè.
dmckee --- gattino ex moderatore

2
"Sembra avere istruzioni if, invoke, ecc." - Quelle sono macro (la 'M' in "MASM") e non devi usarle anche se l'assembler le supporta.
ChrisW

3
È stata una decisione difficile dare alla domanda il suo 65 ° voto positivo, 64 è un numero così bello. . .
735Tesla

Risposte:


40

Inizia con MASM32 e da lì guarda FASM . Ma ti divertirai con MASM.


Ho sentito da MASM. Se non sbaglio, ha molte caratteristiche "di alto livello", che non vedo quando guardo il codice disaggregato. Mi piacerebbe dover programmare qualcosa che sia esattamente come il codice di output della maggior parte dei disassemblatori, se questo ha senso.
elisio divorato il

1
Sarebbe fondamentalmente come scrivere codici operativi, il che non ha davvero senso. L'apprendimento di MASM32 ti aiuterà a capire come appare il codice in un debugger. Potresti anche dare un'occhiata a OllyDbg: ollydbg.de
Noon Silk

7
Non capisci l'assemblaggio. Devi capirlo. Un codice operativo è un numero. I debugger tenteranno di risolvere i codici operativi in ​​base alle loro istruzioni (a volte è difficile). Devi capire le istruzioni di base. Imparare MASM ti aiuterà a farlo. Non c'è più bisogno di dire.
Noon Silk

5
Non è necessario utilizzare tutte le funzionalità MASM solo perché sono presenti; puoi rendere le cose difficili da leggere quanto vuoi, se pensi che imparerai di più in questo modo.
JasonTrue

3
MASM, con le sue stranezze, i bug e le cosiddette funzionalità di alto livello, ha fatto di più per confondere i programmatori di assembly, principianti ed esperti allo stesso modo, più di qualsiasi cosa io possa pensare.
IJ Kennedy

44

L'ho fatto molte volte e continuo a farlo. In questo caso in cui il tuo obiettivo principale è leggere e non scrivere assemblatore, penso che questo si applichi.

Scrivi il tuo disassemblatore. Non allo scopo di creare il prossimo più grande disassemblatore, questo è rigorosamente per te. L'obiettivo è imparare il set di istruzioni. Sia che stia imparando l'assemblatore su una nuova piattaforma, ricordando l'assemblatore per una piattaforma che conoscevo una volta. Inizia con solo poche righe di codice, ad esempio aggiungendo registri e ping pong tra lo smontaggio dell'output binario e l'aggiunta di istruzioni sempre più complicate sul lato di input:

1) apprendere il set di istruzioni per il processore specifico

2) impara le sfumature di come scrivere il codice in assemblare per detto processore in modo da poter muovere ogni bit di codice operativo in ogni istruzione

3) impari il set di istruzioni meglio della maggior parte degli ingegneri che lo utilizzano per guadagnarsi da vivere

Nel tuo caso ci sono un paio di problemi, normalmente raccomando il set di istruzioni ARM per iniziare, ci sono più prodotti basati su ARM spediti oggi rispetto a qualsiasi altro (computer x86 inclusi). Ma la probabilità che tu stia usando ARM ora e non conosci abbastanza assemblatore per scrivere codice di avvio o altre routine sapendo che ARM può o non può aiutare quello che stai cercando di fare. La seconda e più importante ragione per ARM prima è perché le lunghezze delle istruzioni sono di dimensioni fisse e allineate. Disassemblare istruzioni di lunghezza variabile come x86 può essere un incubo come primo progetto, e l'obiettivo qui è imparare il set di istruzioni per non creare un progetto di ricerca. Il terzo ARM è un set di istruzioni ben fatto, i registri sono creati uguali e non hanno sfumature speciali individuali.

Quindi dovrai capire con quale processore vuoi iniziare. Suggerisco prima msp430 o ARM, poi ARM prima o secondo poi il caos di x86. Indipendentemente dalla piattaforma, qualsiasi piattaforma che valga la pena utilizzare ha schede tecniche o manuali di riferimento per programmatori gratuiti dal fornitore che includono il set di istruzioni e la codifica degli opcode (i bit e i byte del linguaggio macchina). Allo scopo di apprendere cosa fa il compilatore e come scrivere codice con cui il compilatore non deve lottare è bene conoscere alcuni set di istruzioni e vedere come lo stesso codice di alto livello viene implementato su ogni set di istruzioni con ogni compilatore ad ogni ottimizzazione ambientazione. Non vuoi entrare nell'ottimizzazione del tuo codice solo per scoprire di averlo reso migliore per un compilatore / piattaforma ma molto peggio per ogni altro.

Oh, per disassemblare i set di istruzioni di lunghezza variabile, invece di iniziare semplicemente dall'inizio e disassemblare ogni parola di quattro byte in modo lineare attraverso la memoria come faresti con ARM o ogni due byte come il msp430 (il msp430 ha istruzioni di lunghezza variabile ma puoi ancora cavartela andando linearmente attraverso la memoria se si inizia dai punti di ingresso dalla tabella dei vettori di interrupt). Per la lunghezza variabile si desidera trovare un punto di ingresso basato su una tabella vettoriale o sulla conoscenza di come il processore si avvia e segue il codice in ordine di esecuzione. È necessario decodificare completamente ciascuna istruzione per sapere quanti byte vengono utilizzati, quindi se l'istruzione non è un ramo incondizionato, si assume che il byte successivo a tale istruzione sia un'altra istruzione. È necessario memorizzare anche tutti i possibili indirizzi di ramo e assumere che siano gli indirizzi di byte iniziali per ulteriori istruzioni. L'unica volta che ho avuto successo ho fatto diversi passaggi attraverso il binario. A partire dal punto di ingresso ho contrassegnato quel byte come l'inizio di un'istruzione, quindi decodificato linearmente attraverso la memoria fino a raggiungere un ramo incondizionato. Tutti i target di diramazione sono stati contrassegnati come indirizzi iniziali di un'istruzione. Ho eseguito più passaggi attraverso il binario fino a quando non ho trovato nuovi target di ramo. Se in qualsiasi momento trovi un'istruzione di 3 byte ma per qualche motivo hai etichettato il secondo byte come l'inizio di un'istruzione, hai un problema. Se il codice è stato generato da un compilatore di alto livello, ciò non dovrebbe accadere a meno che il compilatore non stia facendo qualcosa di malvagio, se il codice ha un assemblatore scritto a mano (come ad esempio un vecchio gioco arcade) è possibile che ci saranno rami condizionali che non possono mai verificarsi come r0 = 0 seguito da un salto se non da zero. Potrebbe essere necessario modificare manualmente quelli dal binario per continuare. Per i tuoi obiettivi immediati che presumo saranno su x86, non penso che avrai un problema.

Raccomando gli strumenti gcc, mingw32 è un modo semplice per utilizzare gli strumenti gcc su Windows se x86 è il tuo obiettivo. In caso contrario, mingw32 plus msys è un'ottima piattaforma per generare un compilatore incrociato da sorgenti binutils e gcc (generalmente piuttosto semplice). mingw32 ha alcuni vantaggi rispetto a cygwin, come programmi significativamente più veloci e si evita l'inferno di cygwin dll. gcc e binutils ti permetteranno di scrivere in C o assembler e disassemblare il tuo codice e ci sono più pagine web di quante ne puoi leggere che ti mostrano come fare una o tutte e tre le cose. Se hai intenzione di farlo con un set di istruzioni di lunghezza variabile, ti consiglio vivamente di utilizzare un set di strumenti che includa un disassemblatore. Un disassemblatore di terze parti per x86, ad esempio, sarà una sfida da usare poiché non si sa mai veramente se è stato disassemblato correttamente. Alcuni di questi dipendono anche dal sistema operativo, l'obiettivo è quello di compilare i moduli in un formato binario che contenga istruzioni per contrassegnare le informazioni dai dati in modo che il disassemblatore possa eseguire un lavoro più accurato. La tua altra scelta per questo obiettivo primario è avere uno strumento che possa compilare direttamente in assembler per la tua ispezione, quindi sperare che quando compila in un formato binario crei le stesse istruzioni.

La risposta breve (ok leggermente PIÙ breve) alla tua domanda. Scrivi un disassemblatore per apprendere un set di istruzioni. Inizierei con qualcosa di RISCy e facile da imparare come ARM. Una volta che conosci un set di istruzioni, altri diventano molto più facili da raccogliere, spesso in poche ore, dal terzo set di istruzioni puoi iniziare a scrivere il codice quasi immediatamente utilizzando il foglio dati / manuale di riferimento per la sintassi. Tutti i processori che vale la pena utilizzare hanno una scheda tecnica o un manuale di riferimento che descrive le istruzioni fino ai bit e ai byte dei codici operativi. Impara un processore RISC come ARM e un CISC come x86 abbastanza per avere un'idea delle differenze, cose come dover passare attraverso i registri per tutto o essere in grado di eseguire operazioni direttamente sulla memoria con meno o nessun registro. Tre istruzioni di operandi contro due, ecc. Quando si ottimizza il codice di alto livello, compilare per più di un processore e confrontare l'output. La cosa più importante che imparerai è che non importa quanto sia buono il codice di alto livello scritto, la qualità del compilatore e le scelte di ottimizzazione fatte fanno un'enorme differenza nelle istruzioni effettive. Raccomando llvm e gcc (con binutils), né produconoottimo codice, ma sono multipiattaforma e multi target ed entrambi hanno ottimizzatori. Ed entrambi sono gratuiti e puoi creare facilmente compilatori incrociati da sorgenti per vari processori di destinazione.


Grazie per la risposta. Ma non so nemmeno come scrivere un disassemblatore.
elisio divorato il

8
"Scrivi il tuo disassemblatore" - Sono d'accordo, è così che l'ho imparato meglio. (Che succede con "Ma non so nemmeno come scrivere un disassemblatore"?) LOL.
slashmais

Vengo con te! Ho appena comprato un MSP430 e un libro su di esso ... :)
Pepe

1
Ho alcuni esempi di msp430 github.com/dwelch67 più alcuni simulatori di set di istruzioni per sperimentare incluso l'apprendimento di asm, ecc.
old_timer

Mi piace davvero molto questa idea.
Millie Smith,

33

L'assembly che scriveresti a mano e l'assembly generato da un compilatore sono spesso molto diversi se visti da un livello elevato. Ovviamente, le parti interne del programma saranno molto simili (ci sono solo così tanti modi diversi di codificare a = b + c, dopotutto), ma non sono il problema quando si tenta di decodificare qualcosa. Il compilatore aggiungerà una tonnellata di codice boilerplate anche a semplici eseguibili: l'ultima volta che ho confrontato, "Hello World" compilato da GCC era di circa 4kB, mentre se scritto a mano in assembly è di circa 100 byte. È peggio su Windows: l'ultima volta che ho confrontato (è vero, questo è stato il secolo scorso) il più piccolo "Hello World" che potevo ottenere dal mio compilatore Windows scelto in quel momento per generare era 52kB! Di solito questo boilerplate viene eseguito solo una volta, se non del tutto, quindi non influisce molto sulla velocità del programma - come ho detto sopra, il nucleo del programma, la parte in cui viene speso la maggior parte del tempo di esecuzione, di solito è abbastanza simile se compilato o scritto a mano.

Alla fine della giornata, questo significa che un esperto programmatore di montaggio e un esperto disassemblatore sono due specialità diverse. Di solito si trovano nella stessa persona, ma sono davvero separati e imparare a essere un eccellente programmatore di assembly non ti aiuterà molto a imparare il reverse engineering.

Quello che vuoi fare è prendere i manuali dell'architettura IA-32 e AMD64 (entrambi sono trattati insieme) da Intel e AMD e guardare attraverso le prime sezioni sulle istruzioni e sui codici operativi. Magari leggi uno o due tutorial sul linguaggio assembly, solo per ottenere le basi del linguaggio assembly. Quindi prendi un piccoloprogramma di esempio che ti interessa e smontalo: segui il suo flusso di controllo e cerca di capire cosa sta facendo. Vedi se riesci a correggerlo per fare qualcos'altro. Quindi riprova con un altro programma e ripeti finché non sei abbastanza a tuo agio da provare a raggiungere un obiettivo più utile. Potresti essere interessato a cose come "crackmes", prodotte dalla comunità del reverse engineering, che sono sfide per le persone interessate al reverse engineering su cui cimentarsi e, si spera, imparare qualcosa lungo la strada. Variano in difficoltà da base (inizia qui!) A impossibile.

Soprattutto, devi solo esercitarti . Come in molte altre discipline, con il reverse engineering, la pratica rende perfetti ... o almeno migliori .


So che quando compili qualcosa con un linguaggio di alto livello, otterrai un sacco di codice "spazzatura" che non sarebbe necessario se fosse stato codificato direttamente in assembly. Capisco anche che c'è una differenza tra un esperto programmatore di assemblaggi e un esperto disassemblatore. Ma lo stesso si potrebbe dire di quasi tutto il resto.
elisio divorato il

3
La mia preoccupazione è che mentre in teoria potrei leggere i giornali e capire cosa significano, finché non comincio a scrivere cose da solo non credo che lo capirò veramente. Dici che posso iniziare modificando piccole parti di codice, ma per farlo devo prima sapere che tipo di "sapore" di assemblaggio IDA pro, ad esempio, usa.
elisio divorato il

Inoltre, cosa usa MSVC ++ per il codice assembly inline? MASM?
elisio divorato il

15

Vado contro il grano della maggior parte delle risposte e raccomando la variante MMIX di Knuth dell'architettura MIPS RISC. Non sarà praticamente utile come i linguaggi assembly x86 o ARM (non che siano così cruciali nella maggior parte dei lavori della vita reale in questi giorni ... ;-), ma sbloccherà per te la magia delle ultime novità di Knuth versione del più grande capolavoro di sempre sulla profonda comprensione di basso livello di algoritmi e strutture dati - TAOCP , "The Art of Computer Programming". I collegamenti dai due URL che ho citato sono un ottimo modo per iniziare a esplorare questa possibilità!


12

(Non so voi ma ero eccitato dall'assemblea)

Un semplice strumento per sperimentare l'assemblaggio è già installato nel tuo PC.

Vai al menu Start-> Esegui e digitadebug

debug (comando)

debug è un comando in DOS, MS-DOS, OS / 2 e Microsoft Windows (solo versioni x86, non x64) che esegue il programma debug.exe (o DEBUG.COM nelle versioni precedenti di DOS). Il debug può agire come un programma di assemblaggio, disassemblatore o dump esadecimale che consente agli utenti di esaminare in modo interattivo il contenuto della memoria (in linguaggio assembly, esadecimale o ASCII), apportare modifiche ed eseguire selettivamente COM, EXE e altri tipi di file. Ha anche diversi sottocomandi che vengono utilizzati per accedere a specifici settori del disco, porte I / O e indirizzi di memoria. Il debug di MS-DOS viene eseguito a un livello di processo a 16 bit e pertanto è limitato ai programmi per computer a 16 bit . FreeDOS Debug ha una versione "DEBUGX" che supporta anche programmi DPMI a 32 bit.

Tutorial:


Se vuoi capire il codice che vedi in IDA Pro (o OllyDbg ), dovrai imparare come è strutturato il codice compilato. Consiglio il libro Reversing: Secrets of Reverse Engineering

Ho sperimentato un paio di settimane debugquando ho iniziato ad imparare l'assemblaggio (15 anni fa).
Si noti che debugfunziona a livello di macchina di base, non ci sono comandi di assieme di alto livello.

E ora un semplice esempio:

dare aper iniziare a scrivere codice assembly - digitare il programma seguente - e infine dare gper eseguirlo.

testo alternativo


( INT 21visualizza sullo schermo il carattere ASCII memorizzato nel DLregistro se il AHregistro è impostato su 2- INT 20termina il programma)


Ho dovuto premere ctrl-c, prima di poter inserire "g".
ericp

2
@ericp, non devi premere ctrl-c. Ad esempio, digiti a& [invio] per iniziare a scrivere il codice assembly. Se premi [invio] due volte, esci dalla modalità di assemblaggio. g& [invio] per eseguirlo (offset 100 per impostazione predefinita).
Nick Dandoulakis

in realtà causa un overflow dello stack o lo scrive semplicemente sullo schermo?
Janus Troelsen

1
@user, scrive solo il nome di questo sito :-)
Nick Dandoulakis

@JanusTroelsen quei numeri (53, 74, 61, ecc.) Sono i codici ASCII per 'S' 't' 'a' ... Ogni chiamata Int21 stampa un carattere alla volta! Questo è il motivo per cui l'assemblaggio NON è più veloce :)
doug65536

8

Ho trovato Hacking: The Art of Exploitation un modo interessante e utile in questo argomento ... non posso dire di aver mai usato la conoscenza direttamente, ma non è proprio per questo che l'ho letto. Ti dà un apprezzamento molto più ricco delle istruzioni in cui viene compilato il tuo codice, che a volte è stato utile per comprendere bug più sottili.

Non lasciarti scoraggiare dal titolo. La maggior parte della prima parte del libro è "Hacking" nel senso del termine Eric Raymond: modi creativi, sorprendenti, quasi subdoli per risolvere problemi difficili. Io (e forse tu) ero molto meno interessato agli aspetti di sicurezza.


7

Non mi concentrerei sul tentativo di scrivere programmi in assembly, almeno non all'inizio. Se sei su x86 (che presumo tu sia, dato che stai usando Windows), ci sono un sacco di strani casi speciali che è inutile imparare. Ad esempio, molte istruzioni presumono che tu stia operando su un registro che non chiami esplicitamente e altre istruzioni funzionano su alcuni registri ma non su altri.

Imparerei quel tanto che basta sulla tua architettura progettata per comprenderne le basi, quindi saltare subito e cercare di capire l'output del tuo compilatore. Armati dei manuali Intel e tuffati direttamente nell'output del tuo compilatore. Isola il codice di interesse in una piccola funzione, così puoi essere sicuro di capire l'intera cosa.

Considero le basi come:

  • registri: quanti sono, come si chiamano e quali sono le loro dimensioni?
  • ordine degli operandi: add eax, ebxsignifica "Aggiungi ebx a eax e salva il risultato in eax".
  • FPU: impara le basi dello stack in virgola mobile e come convertire in / da fp.
  • modalità di indirizzamento: [base + offset * moltiplicatore], ma il moltiplicatore può essere solo 1, 2 o 4 (o forse 8?)
  • convenzioni di chiamata: come vengono passati i parametri a una funzione?

Molto spesso sarà sorprendente ciò che il compilatore emette. Rendilo un puzzle per capire perché diavolo il compilatore ha pensato che sarebbe stata una buona idea. Ti insegnerà molto.

Probabilmente ti aiuterà anche ad armarti dei manuali di Agner Fog , specialmente quello con l'elenco delle istruzioni. Ti dirà approssimativamente quanto sia costosa ciascuna istruzione, anche se questo è più difficile da quantificare direttamente sui processori moderni. Ma aiuterà a spiegare perché, ad esempio, il compilatore si spinge così lontano per evitare di emettere idivun'istruzione.

Il mio unico altro consiglio è di usare sempre la sintassi Intel invece di AT&T quando hai una scelta. Ero abbastanza neutrale su questo punto, fino al giorno in cui mi sono reso conto che alcune istruzioni sono totalmente diverse tra i due (ad esempio, movslqnella sintassi AT&T è movsxdnella sintassi Intel). Poiché i manuali sono tutti scritti utilizzando la sintassi Intel, attenersi a quella.

In bocca al lupo!


3

Ho iniziato imparando MIPS che è un'architettura a 32 bit molto compatta. È un set di istruzioni ridotto, ma questo è ciò che lo rende facile da capire per i principianti. Sarai comunque in grado di capire come funziona l'assemblaggio senza essere sopraffatto dalla complessità. Puoi anche scaricare un bel piccolo IDE, che ti permetterà di compilare il tuo codice MIPS: clicky Una volta capito, penso che sarebbe molto più facile passare ad architetture più complesse. Almeno questo è quello che pensavo :) A questo punto avrai la conoscenza essenziale di allocazione e gestione della memoria, flusso logico, debug, test e così via.


3

Il suggerimento di usare il debug è divertente, molti trucchi possono essere fatti con quello. Tuttavia, per un sistema operativo moderno, l'apprendimento dell'assembly a 16 bit potrebbe essere leggermente meno utile. Considera, invece, l'utilizzo di ntsd.exe. È integrato in Windows XP (sfortunatamente è stato strappato in Server 2003 e versioni successive), il che lo rende uno strumento comodo da imparare poiché è ampiamente disponibile.

Detto questo, la versione originale in XP soffre di una serie di bug. Se vuoi davvero usarlo (o cdb o windbg, che sono essenzialmente interfacce diverse con la stessa sintassi dei comandi e il back-end di debug), dovresti installare il pacchetto gratuito degli strumenti di debug di Windows .

Il file debugger.chm incluso in quel pacchetto è particolarmente utile quando si cerca di capire la sintassi insolita.

La cosa grandiosa di ntsd è che puoi visualizzarlo su qualsiasi macchina XP vicino e usarlo per il montaggio o lo smontaggio. È uno strumento di apprendimento dell'assembly / great / X86. Ad esempio (utilizzando cdb poiché è in linea nel prompt dos, è altrimenti identico):

(errori di simboli saltati poiché irrilevanti - inoltre, spero che questa formattazione funzioni, questo è il mio primo 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>`

Inoltre, mentre giochi con IDA, assicurati di controllare l'IDA Pro Book di Chris Eagle (scollegato poiché StackOverflow non vuole lasciarmi pubblicare più di due link per il mio primo post). È senza dubbio il miglior riferimento in circolazione.


1
+1 per il libro di Chris Eagle. Devo mettere un po 'di amore lì per lo Sk3wl di r00t;)
mrduclaw

3

Recentemente ho seguito un corso di sistemi informatici. Uno degli argomenti era l'assemblaggio come strumento per comunicare con l'hardware.

Per me, la conoscenza dell'assemblaggio non sarebbe stata completa senza comprendere i dettagli di come funzionano i sistemi informatici. Capirlo, porta a una nuova comprensione del motivo per cui le istruzioni di assemblaggio su un'architettura del processore sono ottime ma sono terribili su un'altra architettura.

Detto questo, sono propenso a raccomandare il mio libro di testo di classe:

Sistemi informatici: la prospettiva di un programmatore .

Sistemi informatici: la prospettiva di un programmatore
(fonte: cmu.edu )

Riguarda l'assemblaggio x86 ma il libro è molto più ampio di così. Copre il rivestimento del tubo del processore e la memoria come cache, il sistema di memoria virtuale e molto altro ancora. Tutto ciò può influire sul modo in cui l'assieme potrebbe essere ottimizzato per le caratteristiche date.


2

Penso che tu voglia imparare i mnemonici del codice operativo ASCII (ei loro parametri), che sono emessi da un disassemblatore e che sono compresi da (possono essere usati come input per) un assemblatore.

Qualsiasi assemblatore (ad esempio MASM) andrebbe bene.

E / o potrebbe essere meglio per te leggere un libro a riguardo (ci sono stati libri consigliati su SO, non ricordo quale).


2

Stai facendo altri lavori di sviluppo su Windows? Su quale IDE? Se è VS, non è necessario un IDE aggiuntivo solo per leggere il codice disassemblato: esegui il debug della tua app (o collegala a un'app esterna), quindi apri la finestra di disassemblaggio (nelle impostazioni predefinite, è Alt + 8). Passa e guarda la memoria / i registri come faresti con il codice normale. Potresti anche voler mantenere aperta una finestra dei registri (Alt + 5 per impostazione predefinita).

Intel fornisce manuali gratuiti , che forniscono sia una panoramica dell'architettura di base (registri, unità processore, ecc.) Sia un riferimento completo alle istruzioni. Man mano che l'architettura matura e diventa più complessa, i manuali di "architettura di base" diventano sempre meno leggibili. Se riesci a mettere le mani su una versione precedente, probabilmente avresti un punto di partenza migliore (anche i manuali P3 - spiegano meglio lo stesso ambiente di esecuzione di base).

Se ti interessa investire in un libro, ecco un bel testo introduttivo. Cerca "x86" su Amazon e ne otterrai molti altri. Puoi ottenere molte altre indicazioni da un'altra domanda qui .

Infine, è possibile beneficiare di un po 'di lettura di alcune basso - livello blog. Questi bit di informazioni di dimensioni in byte funzionano meglio per me, personalmente.


2

Questo non ti aiuterà necessariamente a scrivere codice efficiente!

I codici operativi i86 sono più o meno un formato "legacy" che persiste a causa dell'enorme volume di codice e di binari eseguibili per Windows e Linux disponibili.

È un po 'come i vecchi studiosi che scrivevano in latino, un madrelingua italiano come Galileo scriverebbe in latino e il suo articolo potrebbe essere compreso da un parlante polacco come Copernico. Questo era ancora il modo più efficace per comunicare anche se il niether era particolarmente bravo in latino, e il latino è una lingua spazzatura per esprimere idee matematiche.

Quindi i compilatori generano codice x86 per impostazione predefinita e, i chip moderni leggono i codici Op anceint e transalano ciò che vedono in istruzioni di risc parallele, con esecuzione riordinata, esecuzione speculativa, pipelining ecc. Inoltre fanno pieno uso dei 32 o 64 registri del processore ha effettivamente (al contrario del patetico 8 che vedi nelle istruzioni x86.)

Ora tutti i compilatori che ottimizzano sanno che questo è ciò che accade realmente, quindi codificano sequenze di codici OP che sanno che il chip può ottimizzare in modo efficiente, anche se alcune di queste sequenze sembrerebbero inefficienti a un programmatore .asm del 1990 circa.

Ad un certo punto è necessario accettare che i decimi di migliaia di anni uomo di sforzi che gli scrittori di compilatori hanno messo in campo hanno dato i loro frutti e, fidati di loro.

Il modo più semplice e facile per ottenere un runtime più efficiente è acquistare il compilatore Intel C / C ++. Hanno un mercato di nicchia per i compilatori efficeint e hanno il vantaggio di poter chiedere ai progettisti di chip cosa succede all'interno.


La tua storia suggerisce in qualche modo che i processori CISC sono diventati internamente processori RISC. Potrei aver capito male, ma questo semplicemente non è vero. E il patetico 8? I processori moderni (diciamo dal 1999) includono molti altri: 10 gpr: EAX-EFLAGS, 80 bit FP0-FP7, 64 bit MMX0-MMX7, 128 bit XMM0-XMM7, segmento: CS-GS, speciali: CR0-CR4 , DR0-DR7, TR3-TR7, GDTR, IDTR, LDTR, MSR e su x86-64 anche R8-R15. Non tutti questi sono accessibili da ring-3, ma la maggior parte sono e la maggior parte sono utilizzati dai compilatori GCC / VC ++ recenti (post-2006). Complessivamente leggermente più del "patetico 8";).
Abel

2

Per fare quello che vuoi fare, ho appena preso l' Intel Instruction Set Reference (potrebbe non essere quello esatto che ho usato, ma sembra sufficiente) e alcuni semplici programmi che ho scritto in Visual Studio e ho iniziato a lanciarli in IDAPro / Windbg . Quando ho sviluppato i miei programmi, il software di crackmes è stato utile.

Presumo che tu abbia una conoscenza di base di come vengono eseguiti i programmi su Windows. Ma in realtà, per leggere l'assembly, ci sono solo poche istruzioni da imparare e alcuni tipi di queste istruzioni (ad esempio, c'è un'istruzione di salto, jump ha alcune versioni come jump-if-equal, jump-if-ecx-is-zero , eccetera). Una volta apprese le istruzioni di base, è abbastanza semplice ottenere il succo dell'esecuzione del programma. La visualizzazione grafica di IDA aiuta, e se stai tracciando il programma con Windbg, è abbastanza semplice capire cosa stanno facendo le istruzioni se non sei sicuro.

Dopo aver giocato un po 'in quel modo, ho comprato Hacker Disassembly Uncovered . In generale, sto lontano dai libri con la parola "Hacker" nel titolo, ma mi è piaciuto molto il modo in cui questo è andato davvero in profondità su come il codice compilato sembrava smontato. Si occupa anche delle ottimizzazioni del compilatore e di alcune cose interessanti sull'efficienza.

Tutto dipende davvero da quanto profondamente vuoi essere in grado di capire anche il programma. Se stai decodificando un obiettivo alla ricerca di vulnerabilità, se stai scrivendo codice di exploit o analizzando malware compresso per funzionalità, avrai bisogno di più tempo per accelerare davvero le cose (specialmente per il malware più avanzato ). D'altra parte, se vuoi solo essere in grado di cambiare il livello del tuo personaggio sul tuo videogioco preferito, dovresti stare bene in un lasso di tempo relativamente breve.


1

Uno dei linguaggi di assemblaggio pedagogico standard là fuori è MIPS. Puoi ottenere simulatori MIPS (spim) e vari materiali didattici per questo.

Personalmente, non sono un fan. Mi piace piuttosto IA32.


MIPS è carino. Anche 68000 lo è, e se impari 68000 puoi scrivere binari che girano in MAME. :-)
Nosredna

1

Il mio preferito è NASM, soprattutto perché è multipiattaforma e compila MMX, SSE, 64 bit ...

Ho iniziato a compilare un semplice file sorgente C con gcc e "transcodificare" le istruzioni dell'assemblatore dal formato gcc al formato NASM. Quindi è possibile modificare piccole porzioni di codice e verificare il miglioramento delle prestazioni che comporta.

La documentazione NASM è davvero completa, non ho mai avuto bisogno di cercare informazioni da libri o altre fonti.



0

Molte buone risposte qui. La programmazione di basso livello, l'assemblaggio, ecc. Sono popolari nella comunità della sicurezza, quindi vale la pena cercare suggerimenti e suggerimenti una volta che si inizia. Hanno anche alcuni buoni tutorial come questo sull'assemblaggio x86 .


0

Per raggiungere effettivamente il tuo obiettivo, potresti considerare di iniziare con l'IDE in cui ti trovi. Generalmente è una finestra di disassemblaggio, quindi puoi eseguire un singolo passaggio attraverso il codice. Di solito c'è una vista di qualche tipo per farti vedere i registri e guardare nelle aree di memoria.

L'esame del codice c / c ++ non ottimizzato aiuterà a creare un collegamento nel tipo di codice che il compilatore genera per i tuoi sorgenti. Alcuni compilatori hanno una sorta di parola riservata ASM che consente di inserire le istruzioni della macchina nel codice.

Il mio consiglio è di giocare con questo tipo di strumenti per un po 'e di bagnarti i piedi, poi salire? giù? al codice assembler diretto su qualsiasi piattaforma su cui stai eseguendo.

Ci sono molti ottimi strumenti là fuori, ma potresti trovarlo più divertente, per evitare la curva di apprendimento ripida all'inizio.


0

Abbiamo imparato l'assemblaggio con un kit di sviluppo per microcontrollore (Motorola HC12) e una scheda tecnica spessa.


0

Fuori tema lo so, ma dato che sei un programmatore Windows non posso fare a meno di pensare che potrebbe essere un uso più appropriato e / o migliore del tuo tempo per imparare MSIL. No, non è assembly, ma probabilmente è più rilevante in questa era .NET.


0

Conoscere l'assembly può essere utile per il debug, ma non sarei troppo entusiasta di usarlo per ottimizzare il tuo codice. I compilatori moderni di solito sono molto più bravi a ottimizzare che un essere umano oggigiorno.


Hmm. Puoi ancora strizzare un po 'di assembly di codifica in più da solo, ma ci vuole più lavoro per battere il compilatore rispetto a prima.
Nosredna

0

Puoi controllare il video corso su xorpd x86 Assembly . (L'ho scritto io). Il corso stesso è pagato, ma gli esercizi sono open source, su GitHub. Se hai una certa esperienza di programmazione, penso che dovresti essere in grado di lavorare solo con gli esercizi e capire tutto.

Si noti che il codice è per la piattaforma Windows ed è scritto utilizzando l' assembler Fasm . Il corso e gli esercizi non contengono costrutti di alto livello, tuttavia potresti usare Fasm per creare macro molto complicate, se lo desideri.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.