Che cosa significa mov qword rbx, '// bin / sh'?

4

Seguo questo tutorial per capire come funziona lo shellcode a 64 bit.

Quindi, codifico questo shellcode e funziona:

BITS 64

xor rax, rax
mov qword rbx, '//bin/sh'
shr rbx, 0x8
push rbx
mov rdi, rsp
push rax
mov rdx, rsp
push rdi
mov rsi, rsp
mov al, 59
syscall

Comprendo tutto questo codice tranne due istruzioni:

mov qword rbx, '//bin/sh'
shr rbx, 0x8

Capisco che una qword sia un dato di dimensione 64 bit ma quando rimuovo qword lo shellcode non funziona. Perché devo aggiungere qword?

E dopo che le istruzioni si sono ridotte, le mie stringhe dovrebbero essere come '% 00 // bin / s' no? Perché non usare shl invece di shr?

    
posta sushi 31.12.2016 - 17:11
fonte

1 risposta

2

I understand that a qword is a data of size 64 bits but when I remove qword the shellcode doesn't work. Why I need to add qword?

Perché stai spostando una costante qword. Quando digiti '//bin/sh' stai esprimendo un array di 8 caratteri. Premendo il prefisso con qword si sta istruendo l'assemblatore a trattare l'operando a destra come un intero in linea a 64 bit. Di default lo tratterà probabilmente come un puntatore a quella stringa, o qualche altro comportamento.

And after the instruction shr, my strings should be looks like '%00//bin/s' no?

I numeri interi dei processori di architettura x86 sono memorizzati come little-endian . Se il tuo compilatore l'ha preso alla lettera, la tua stringa verrebbe codificata in ASCII come segue:

/  /  b  i  n  /  s  h
2f 2f 62 69 6e 2f 73 68 

Che puoi anche mostrare nelle seguenti istruzioni:

mov rbx, 0x2f2f62696e2f7368

Questo codifica come segue:

48 BB 68 73 2F 6E 69 62 2F 2F

Possiamo dividerlo in 3 sezioni:

48        BB                     68 73 2F 6E 69 62 2F 2F
|         |                      |---------------------|
 \         \                             literal
  64-bit     B8 = MOV instr
  prefix        + reg operand
                + r/m operand

In questo caso il byte dell'istruzione mov ( BB ) contiene anche un campo a 7 bit che descrive il registro in cui ci stiamo spostando ( rbx ) e il tipo di operando a destra (letterale).

Ma attenzione: il letterale è non nello stesso ordine della rappresentazione ASCII che abbiamo visto sopra. Invece è invertito a causa di little-endianness.

Il problema qui, naturalmente, è che questo non può essere ciò che accade nel tuo shellcode. Se il nome è stato invertito nei byte, la funzione chiamata vedrebbe hs/nib// e fallirà. Invece, il tuo assemblatore è abbastanza intelligente da capire che vuoi quei caratteri ASCII in ordine di byte, il che significa che codifica davvero le seguenti istruzioni:

mov rbx, 0x68732f6e69622f2f

Questo produce le seguenti istruzioni codificate:

48 BB 2F 2F 62 69 6E 2F 73 68

Come puoi vedere, // viene prima ( 2F 2F ) nella rappresentazione dell'ordine dei byte.

Why not use shl instead of shr?

Fai entrambi. Nel tuo codice manca un'istruzione, che può essere vista nel tutorial. Dopo il shl rbx, 0x8 segue immediatamente un shr rbx, 0x8 .

La loro spiegazione non rende giustizia:

After shifting 0x08 to the left (think of each numeric placeholder in the string as a 4, so moving 8 bytes over actually moves us two spaces) pushes the 11 right off the end. Now we have this:

0x68732f6e69622f00

Then we put it back like before by using shr by the same value, and we get this:

0x0068732f6e69622f

This successfully gives us our string terminated by a nullbyte without generating a single nullbyte in the machine code.

La prima barra è semplicemente un carattere sacrificale che viene scartato durante shl .

Il motivo di questo trucco, invece di caricare il null al primo posto o mascherare il byte più a destra con zero è che non richiede byte null nel payload di exploit, che è molto utile se l'input viene ignorato dopo un null ( ad esempio se una stringa viene copiata con strcpy).

    
risposta data 31.12.2016 - 18:20
fonte

Leggi altre domande sui tag