GUIDA Decodificare la lunghezza delle istruzioni di x86 e x64

DispatchCode

Utente Attivo
877
548
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
HDD
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
GPU
Nvidia Geforce GTX 960M, 4GB
Audio
Realtek
Net
30Mbps/3Mbps con Eolo
OS
Windows 10 64bit
MCA - Machine Code Analyzer

Vi avevo già parlato di un mio progetto qualche mese fa. MCA è parte di quel progetto. Si tratta di una parte così importante che ho preferito "scorporare" e pubblicare separatamente, aggiungendo un pò di cose che mi ero perso. Ma andiamo con ordine.
Il compito di MCA è decodificare il codice macchina che ha come target le architetture x86 e x64.

Le architetture CISC hanno un gran numero di opcodes, e la lunghezza delle istruzioni non è fissa (varia da 1 a 15bytes). Quindi se si ha bisogno di decodifcare il codice macchina di queste architetture l'unica soluzione è decodificare ogni byte, per capire di quale operazione si tratta.
La struttura di un'istruzione è mostrata di seguito:

Codice:
// con [ ] vengono indicati i campi opzionali
[prefix] opcode [modrm] [sib] [disp] [imm]

A questi vanno aggiunti anche alcuni altri prefissi, come REX e VEX, che si trovano sempre prima dell'opcode. Gli opcode possono essere a 1byte, 2byte o 3byte (in due forme differenti).

Per mostrarvi il funzionamento di MCA, riporto un esempio preso dal README del progetto:

Codice:
008910BC  |.  C785 68FFFFFF 00000000  MOV DWORD PTR SS:[LOCAL.38],0
008910C6  |.  8D45 CC                 LEA EAX,[LOCAL.13]
008910C9  |.  8D5D 9C                 LEA EBX,[LOCAL.25]
008910CC  |.  33C9                    XOR ECX,ECX
008910CE  |>  83F9 30                 /CMP ECX,30
008910D1  |.  7D 18                   |JGE SHORT 008910EB
008910D3  |.  0F100408                |MOVUPS XMM0,DQWORD PTR DS:[ECX+EAX]
008910D7  |.  0F100C0B                |MOVUPS XMM1,DQWORD PTR DS:[ECX+EBX]
008910DB  |.  0F58C1                  |ADDPS XMM0,XMM1
008910DE  |.  0F11840D 6CFFFFFF       |MOVUPS DQWORD PTR SS:[ECX+EBP-94],XMM0
008910E6  |.  83C1 04                 |ADD ECX,4
008910E9  |.^ EB E3                   \JMP SHORT 008910CE

Decodificando il file binario che contiene quel codice macchina e stampando ogni istruzioni riga per riga (così da riuscire a leggerla meglio), MCA decodifica:

Codice:
C7 85 68 FF FF FF 00 00 00 00
8D 45 CC
8D 5D 9C
33 C9
83 F9 30
7D 18
0F 10 04 08
0F 10 0C 0B
0F 58 C1
0F 11 84 0D 6C FF FF FF
83 C1 04

Come si può osservare il codice è quello che si vede sopra (avevo disassemblato un'istruzione in meno, mi sono perso quindi il JMP...). MCA mantiene un array di 15bytes (opzionale) con i byte dell'istruzione; la stampa qui sopra avviene proprio utilizzando quell'array.

Ovviamente mantiene tutte le altre informazioni che riguardano l'istruzione. Ne ho scelte 2 tra quelle mostrate sopra:

Codice:
MOV DWORD PTR SS:[LOCAL.38],0
MOVUPS DQWORD PTR SS:[ECX+EBP-94],XMM0

Queste sono le informazioni raccolte da MCA sulle due istruzioni:

Codice:
RAW bytes (hex): C7 85 68 FF FF FF 00 00 00 00
Instr. length: 10
Print instruction fields:
        Located Prefixes 0:

        OP: 0xC7
        mod_reg_rm: 0x85
        disp (4): 0xFFFFFF68
        Iimm: 0x0


RAW bytes (hex): 0F 11 84 0D 6C FF FF FF
Instr. length: 8
Print instruction fields:
        Located Prefixes 1:
                0xF
        OP: 0x11
        mod_reg_rm: 0x84
        SIB byte: 0xD
        disp (4): 0xFFFFFF6C

Attualmente è ancora in versione Beta, e necessita quindi di qualche "prova sul campo".
Manca il supporto per il prefisso EVEX (AVX-512), 3DNow! e XOP (di AMD). Attualmente non è presente una trasformazione in mnemonici, ma diciamo che è tra le cose che vorrei implementare in futuro, dopo al supporto per EVEX.

Per tutte le altre info e il codice vi rimando al README di MCA: https://github.com/DispatchCode/Machine-Code-Analyzer
 

Entra

oppure Accedi utilizzando

Hot: PS5 VS XBOX X/S?

  • Playstation 5

    Voti: 249 61.0%
  • XBOX Series X/S

    Voti: 159 39.0%

Discussioni Simili