2012-09-04 15 views
5

Ho letto questo articolo: http://static.patater.com/gbaguy/day3pc.htmCosa succederebbe se il registro dei segmenti CS venisse modificato?

Esso comprende la frase

NON MAI CAMBIO CS !!

Ma cosa accadrebbe esattamente se si modificasse il registro di segmento CS? Perché è così pericoloso?

+2

'CS' = segmento di codice. Suppongo che cambiarlo sia equivalente (in un certo senso) a un 'jmp' pervertito. – valdo

+5

Questo documento sembra abbastanza inaffidabile: "NON SEMPRE CAMBIARE 'CS' !!, ma puoi leggere' CS' in questo modo: 'mov ds, cs'; metti il ​​valore di' CS' in 'D'S." Bene, in x86 non esiste un'istruzione come "mov ds, cs" né alcun altro "mov segreg, segreg". Per leggere il valore di 'cs' puoi usare' mov reg, cs; mov ds, reg' (dove 'reg' può essere' ax', 'bx',' cx' ecc ...), o 'push cs; pop ds'. Inoltre, se si decide di non * mai * cambiare 'cs', tutte le chiamate di interruzione sono fuori questione (ad esempio, BIOS, DOS e servizi Linux). http://web.itu.edu.tr/kesgin/mul06/intel/instr/mov.html – nrz

+1

@nrz: Non esiste una cosa come "servizi Linux" accessibile attraverso chiamate 'lontano' (interrupt/syscalls funzionano in modo diverso, anche se questi portano a un cambiamento in' cs ', il _caller_ non può controllare quale sarà il target' cs', deciso dal sistema operativo quando si impostano le voci IDT/syscall msrs). Ack con tutto il resto, ovviamente 'cs'_can_ essere cambiato, solo che a meno che il segmento del codice di destinazione esista e sia impostato in modo tale che l'obiettivo' eip' sia raggiungibile, qualsiasi chiamata di questo tipo causerà un errore '# GP' e l'app si interromperà. –

risposta

7

cs è il segmento di codice. cs:ip, che significa insieme a ip (puntatore di istruzioni) punta alla posizione dell'istruzione successiva. Quindi qualsiasi modifica a cs o ip o ad entrambi cambia l'indirizzo da cui verrà recuperata ed eseguita l'istruzione successiva.

Di solito si cambia cs con un (salto in lungo) jmp, call (lunga chiamata), retf, int3, int o iret. In 8088 e 8086 è anche disponibile pop cs (codice 0x0F). pop cs non funziona con 186+, in cui l'opcode 0x0F è riservato per istruzioni multibyte. http://en.wikipedia.org/wiki/X86_instruction_listings

Non c'è nulla di intrinsecamente pericoloso nel salto in lungo o in una lunga chiamata. Devi solo sapere dove si salta o si chiama e in modalità protetta è necessario disporre di privilegi sufficienti per farlo. Nella modalità reale a 16 bit (es. DOS) puoi saltare e chiamare qualsiasi indirizzo desideri, ad es. jmp 0xF000:0xFFF0 imposta cs a 0xF000 e ip a 0xFFF0, che è l'indirizzo iniziale del codice BIOS e quindi riavvia il computer. Diversi indirizzi di memoria hanno un codice diverso e quindi generano diversi tipi di risultati, in teoria tutto può accadere (se si passa al codice BIOS utilizzato per la formattazione del disco rigido, con valori di registro e/o stack validi, il disco rigido verrà formattato 'come richiesto'). In pratica, jmp e call alla maggior parte degli indirizzi probabilmente causano codice operativo non valido o qualche altra eccezione (divisione per zero, divisione overflow, ecc.) Molto presto.

+0

Cambiare solo 'cs' è di solito sbagliato. Normalmente 'cs' e' xip' sono cambiati insieme o solo 'xip' cambia. –

+3

@AlexeyFrunze Bene, l'unico modo per cambiare solo 'cs' senza modificare/impostare' ip'/'eip' /' rip' è 'pop cs', che è disponibile solo in 8088 e 8086. In 186+ si puo ' t cambia 'cs' senza modificare/impostare anche' ip'/'eip' /' rip'. 'pop cs' potrebbe essere usato nel codice di offuscamento mirato per 8088/8086 (o emulatore 8088/8086). – nrz

0

In modalità protetta e in modalità lunga (vale a dire non in modalità a 16 bit), i registri di segmento inclusi CS non sono più solo 4 bit aggiuntivi di indirizzo. Indicano nella tabella dei descrittori di segmento, con un limite di base + (base normale = 0 limite = 4GiB, cioè un modello di memoria piatta), ma anche con altri attributi.

Il descrittore del segmento di codice determina la modalità CPU (ad esempio modalità compat a 32 bit rispetto alla modalità a 64 bit). Su un kernel a 64 bit, un processo dello spazio utente a 64 bit potrebbe rendere un far jmp un codice a 32 bit. Questo non è utile nella pratica e potrebbe persino interrompersi quando l'OS ritorna al tuo processo dopo un cambio di contesto.

TODO: scavare un link dove qualcuno ha mostrato come fare questo. Penso che ci fosse anche una domanda recente su questo con una risposta dettagliata su come trovare anche i numeri di segmento giusti.