Dia 04

NO MIREN ESTA INFORMACIÓN, TODAVIA NO LA HE ACTUALIZADO

Identificando variables locales en assembly

En assembly, las variables locales se pueden almacenar en displacemente negativos con relacion al EBP o displacemente positivos con relacion al ESP

---- ESP : direccion menor
----
----
----
---- EBP: direccion mayor

Por ejemplo, las siguientes guardan el valor 42 a una variable local (no necesariamente la misma):

mov 0x2a, -0x4(%ebp)

y

mov 0x2a, 0x10(%esp)

Organización común de stack frame

esp ---> argumento
         argumento   
         argumento 


         var local
         var local
         var local
ebp ---> ebp viejo
         ret address

Identificando argumentos en assembly

Ejemplo (adapatado de wikipedia)

int foo(int a, int b, int c) {
   return a + b + c;
}

int main()
{
    int ret;

    ret = foo(1, 2, 3);
    ret += 5;
    return ret;
}

main:
push   %ebp           ; \
mov    %esp,%ebp      ; } The prologue
sub    $0x1c,%esp     ; /

movl   $0x3,0x8(%esp) ; \ 
movl   $0x2,0x4(%esp) ; } Pushing the arguments in the stack
movl   $0x1,(%esp)    ; /

call   80483ed <foo>  ; calling the function

mov    %eax,-0x4(%ebp) ; \
addl   $0x5,-0x4(%ebp) ; } reading the ret value, adding 5,...
mov    -0x4(%ebp),%eax ; /

leave  
ret 
foo:
push   %ebp             ;
mov    %esp,%ebp        ; prologue

mov    0xc(%ebp),%eax   ; \
mov    0x8(%ebp),%edx   ; } - reading the arguments
add    %eax,%edx        ; }
mov    0x10(%ebp),%eax  ; /

add    %edx,%eax        ; setting the return value

pop    %ebp             ; epilogue
ret   

El stack justo antes de llamar a foo,

El cuando se está ejecutando foo,

LEA vs MOV

LEA -- Load Effective Address

LEA calculates the effective address and stores it in the specified register.

Ejemplo: La siguiente instrucción copy a EAX el resultado de la expresión EBP - 0x10. Si EBP contiene 0xfff8090, luego de esta instrucción EAX contendrá 0xfff8080.

lea    -0x10(%ebp),%eax

La expresión del source puede contener varios términos. Por ejemplo: La siguiente instrucción copia a EAX el resultado de la expresion EDX - 0x6 + EDX * 4. Si EDX contiene 0x1100, luego de la instrucción EAX contiene 0x54fa.

 leal -0x6 (%edx, %edx, 4   )
      ----  ----  ----  ----
        \     \     \   \_ scalar factor
         \     \     \_ register
          \     \__ base register
           \___ displacement

MOV -- Move Data

MOV copies (the content) the source to the destination.

La siguiente instrucción copia el contenido de EBX a EAX. Por ejemplo, si EBX contiene 0xfff8080, luego de la instrucción EAX también contendrá 0xfff8080.

mov %ebx, %eax

La siguiente instrucción copia el contenido de la memoria apuntada por EBX a EAX. Por ejemplo, si EBX contiene 0xfff8080, luego de la instrucción EAX contendrá los 4 bytes que están en la dirección de memoria 0xfff8080.

mov (%ebx), %eax

La siguiente instrucción copia el contenido de la memoria cuya dirección es el resultado de la expresión EBX - 0x10 a EAX. Por ejemplo, si EBX contiene 0xfff8080, luego de la instrucción EAX contendrá los 4 bytes que están en la dirección de memoria 0xfff8070.

mov -0x10(%ebx), %eax

En resumen, si la variable a vive en el -0x10(%ebp), la variable b en -0x18(%ebp) y la variable c en -0x20(%ebp)

El siguiente es equivalente a c = &b.

lea -0x18(%ebp), %ebx
mov %ebx, -0x20(%ebp)

El siguiente es equivalente a b = a.

mov -0x10(%ebp), %ebx
mov %ebx, -0x18(%ebp)

ATT vs INTEL

Formato ATT

int a = 42;
int b = a;
movl   $0x2a,-0x10(%ebp)
mov    -0x10(%ebp),%eax
mov    %eax,-0xc(%ebp)

Formato Intel

int a = 42;
int b = a;
mov    [ebp-0x10],0x2a
mov    eax,[ebp-0x10]
mov    [ebp-0xc],eax

Estructuras de control en el 80386

El orden para comparar en formato ATT

La siguente instrucción esta la variable -0x8(%ebp) - 0x9

cmpl   $0x9,-0x8(%ebp)   

Jumps condicionales en x86

Opcode Description CPU Flags
JA Above CF = 0 and ZF = 0
JAE Above or equal CF = 0
JB Bellow CF
JBE Bellow or equal CF or ZF
JC Carry CF
JE Equality ZF
JG Greater(s) ZF = 0 and SF = OF
JGE Greater or equal(s) SF = OF
JL Less(s) SF ≠ OF
JLE Less equal(s) ZF or SF ≠ OF
JNA Not above CF or ZF
JNAE Neither above nor equal CF
JNB Not bellow CF = 0
JNBE Neither bellow nor equal CF = 0 and ZF = 0
JNC Not carry CF = 0
JNE Not equal ZF = 0
JNG Not greater ZF or SF ≠ OF
JNGE Neither greater nor equal SF ≠ OF
JNL Not less SF = OF
JNLE Not less nor equal ZF = 0 and SF = OF
JNO Not overflow OF = 0
JNP Not parity PF = 0
JNS Not negative SF = 0
JNZ Not zero ZF = 0
JO Overflow(s) OF
JP Parity PF
JPE Parity PF
JPO Not parity PF = 0
JS Negative(s) SF
JZ Null ZF

Ejemplo: ¿Cuándo brinca al label02?

cmpl   $0x9,-0x8(%ebp)  
jge    label02

Cómo las instrucciones cambian los flags

Aqui pueden ver como las instrucciones modifican los flags: http://css.csail.mit.edu/6.858/2013/readings/i386/appc.htm

Bit Name Function
0 CF Carry Flag: Set on high-order bit carry or borrow; cleared otherwise.
2 PF Parity Flag -- Set if low-order eight bits of result contain an even number of 1 bits; cleared otherwise.
4 AF Adjust flag -- Set on carry from or borrow to the low order four bits of AL; cleared otherwise. Used for decimal arithmetic.
6 ZF Zero Flag -- Set if result is zero; cleared otherwise.
7 SF Sign Flag -- Set equal to high-order bit of result (0 is positive, 1 if negative).
11 OF Overflow Flag -- Set if result is too large a positive number or too small a negative number (excluding sign-bit) to fit in destination operand; cleared otherwise.

Status Flag Summary

Key to Codes
T     = instruction tests flag
M     = instruction modifies flag
        (either sets or resets depending on operands)
0     = instruction resets flag
--    = instruction's effect on flag is undefined
blank = instruction does not affect flag

Instruction            OF   SF   ZF   AF   PF   CF
AAA                    --   --   --   TM   --   M
AAS                    --   --   --   TM   --   M
AAD                    --   M    M    --   M    --
AAM                    --   M    M    --   M    --
DAA                    --   M    M    TM   M    TM
DAS                    --   M    M    TM   M    TM
ADC                    M    M    M    M    M    TM
ADD                    M    M    M    M    M    M
SBB                    M    M    M    M    M    TM
SUB                    M    M    M    M    M    M
CMP                    M    M    M    M    M    M
CMPS                   M    M    M    M    M    M
SCAS                   M    M    M    M    M    M
NEG                    M    M    M    M    M    M
DEC                    M    M    M    M    M
INC                    M    M    M    M    M
IMUL                   M    --   --   --   --   M
MUL                    M    --   --   --   --   M
RCL/RCR 1              M                        TM
RCL/RCR count          --                       TM
ROL/ROR 1              M                        M
ROL/ROR count          --                       M
SAL/SAR/SHL/SHR 1      M    M    M    --   M    M
SAL/SAR/SHL/SHR count  --   M    M    --   M    M
SHLD/SHRD              --   M    M    --   M    M
BSF/BSR                --   --   M    --   --   --
BT/BTS/BTR/BTC         --   --   --   --   --   M
AND                    0    M    M    --   M    0
OR                     0    M    M    --   M    0
TEST                   0    M    M    --   M    0
XOR                    0    M    M    --   M    0

El instruction set completo está disponible en http://css.csail.mit.edu/6.858/2013/readings/i386/c17.htm

Ejemplo: instrucción TEST

TEST computes the bit-wise logical AND of its two operands. The result of the operation is discarded and only the flags are modified.

Usos comúnes: Si deseas probar si el contenido de EAX es 0:

TEST EAX,EAX

y luego verificas el zero flag (usando JE).

Por ejemplo, este pedazo verifica si el resultado de un strcmp fue 0.

 80484dd:call 8048350 <strcmp@plt>    
 80484e2:test %eax,%eax              
 80484e4:jne  80484f4 <main+0x57>    
 80484e6:movl $0x80485b0,(%esp)      
 80484ed:call 8048370 <puts@plt>     
 80484f2:jmp  8048500 <main+0x63>    
 80484f4:movl $0x80485b8,(%esp)      
 80484fb:call 8048370 <puts@plt>     
 8048500:mov  $0x0,%eax              

Figura ilustrando el flujo en esta parte del programa

Como revertir para invertir la lógica del flujo? reemplazar el jne por un je.

Truco mongo para saltar verificación por password :

La única forma de obtener 0 al hacer un AND entre un registro y si mismo es cuando el registro contiene 0.

La operación XOR entre un registro y si mismo siempre dará como resultado 0 (y encenderá el Z flag).

Suponga que tiene una situación como la siguiente. Esta caso si EAX no contiene 0 después de regresas de strcmp, el programa seguirá la ruta del dolor.

 80484dd: call 8048350 <strcmp@plt>
 80484e2: test %eax,%eax
 80484e4: je   placer 
 80484e6: dolor

Si usted quisiera evitarse el dolor (sin importar cuál fue el resultado de strcmp) puede cambiar el test por xor. Como xor siempre da 0, el zero flag se enciende y el je siempre bricará (de placer drumroll).

 80484dd: call 8048350 <strcmp@plt>
 80484e2: xor  %eax,%eax
 80484e4: je   placer 
 80484e6: dolor

Si fueras a cambiar es instrucción en el ejecutable, eso implica buscar el código de xor %eax,%eax. No te angusties, usa: https://defuse.ca/online-x86-assembler.htm. Algunos editores de hex te permiten entrar la instrucción en assembly, e.g. xor eax,eax, y lo insertan en hex, e.g. 31 c0.

Ejemplos de expresiones relacionales compuestas

if ( a > 20 && a < 78) then do A else do B

is changed to if ( a <= 20) jump to labelDoB if ( a > 77 ) jump to labelDoB do A jump to labelAfter labelDoB: do B labelAfter:

804842e: cmpl $0x14,0x1c(%esp)     ;}  if a <= 20 then jump to do B
8048433: jle  804844a <main+0x2d>  ;}

8048435: cmpl $0x4d,0x1c(%esp)     ;}  if a > 77 then jump to do B
804843a: jg   804844a <main+0x2d>  ;}

804843c: movl $0x80484f0,(%esp)    ;} do A
8048443: call 80482f0 <puts@plt>   ;}
8048448: jmp  8048456 <main+0x39>  ;} jump to after

804844a: movl $0x80484f8,(%esp)    ;} do B
8048451: call 80482f0 <puts@plt>   ;} 

8048456: mov  $0x0,%eax


Programas útiles para explorar ejecutables

objdump

objdump: desplega informacion sobre archivos binarios (.o, ejecutables, .so). Algunos de los modos que utilizo:

readelf: también desplega información sobre archivos de tipo ELF.

hexedit: para modificar archivos en binario

* F3 - guardar
* Ctrl-C - salir

strings: despliega los strings que encuentra en un archivo binario.