Dia 05

Removiendo símbolos del ejecutable

strip: strip removes or modifies the symbol table attached to the output of the assembler and link editor. This is useful to save space after a program has been debugged and to limit dynamically bound symbols.

Part of a symbol table from a executable:

Symbol table '.symtab' contains 74 entries:
....       
62: 0804b038     0 NOTYPE  GLOBAL DEFAULT   25 _end
63: 080485fd   200 FUNC    GLOBAL DEFAULT   13 dolor
64: 08048450     0 FUNC    GLOBAL DEFAULT   13 _start
65: 080490b8     4 OBJECT  GLOBAL DEFAULT   15 _fp_hw
66: 0804b034     0 NOTYPE  GLOBAL DEFAULT   25 __bss_start
67: 080486c5  2400 FUNC    GLOBAL DEFAULT   13 main
68: 0804854d   176 FUNC    GLOBAL DEFAULT   13 placer
69: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
70: 00000000     0 FUNC    GLOBAL DEFAULT  UND __isoc99_scanf@@GLIBC_2.7
71: 0804b034     0 OBJECT  GLOBAL HIDDEN    24 __TMC_END__
72: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
73: 0804839c     0 FUNC    GLOBAL DEFAULT   11 _init

After stripping the executable, there is no symbol table. Disassemblers won't label the beggining of main or other local functions :-(, however.... you may still find the beggining of main, just look for

__libc_start_main

The __libc_start_main() ` function performs any necessary initialization of the execution environment, calls the main function with appropriate arguments, and handles the return from main().

08048450 <.text>:
 8048450: 31 ed                 xor    %ebp,%ebp
 8048452: 5e                   pop    %esi
 8048453: 89 e1                 mov    %esp,%ecx
 . . . . . 
 8048467: 68 c5 86 04 08       push   $0x80486c5
 804846c: e8 af ff ff ff       call   8048420 <__libc_start_main@plt>
 . . . . 

Compilación para AMD64 (x86-64)

Los registros en AMD64.

registros en AMD64

Organización de registros 64 bits

Si comienza con R, tiene 64-bits. Apoya legacy mode en que solo utiliza la parte de 32-bits (se llama E)

Pase de parámetros x86-64 (al menos en gcc linux)

From http://www.agner.org/optimize/calling_conventions.pdf page 10.

Passing Once arguments are classified, the registers get assigned (in left-to-right order) for passing as follows:

Ejemplo compilando en AMD64 para observar el orden de los parámetros

void func1(int a, int b, int c, int d, int e) {
   a = 0x1;
   b = 0x2;
   c = 0x3;
   d = 0x4;
   e = 0x5;
}

int main() {
  func1(0x11,0x22,0x33,0x44,0x55);
  return 0;
}

func1(int, int, int, int, int):
 push %rbp
 mov %rsp,%rbp
 mov %edi,-0x4(%rbp)  ; notice how the parameters
 mov %esi,-0x8(%rbp)  ; are copied onto the local 
 mov %edx,-0xc(%rbp)  ; variables...
 mov %ecx,-0x10(%rbp)
 mov %r8d,-0x14(%rbp)

 movl $0x1,-0x4(%rbp)
 movl $0x2,-0x8(%rbp)
 movl $0x3,-0xc(%rbp)
 movl $0x4,-0x10(%rbp)
 movl $0x5,-0x14(%rbp)
 nop
 pop %rbp
 retq 

main:
 push %rbp
 mov %rsp,%rbp
 mov $0x55,%r8d   ; notice how the various
 mov $0x44,%ecx   ; parameters are copied
 mov $0x33,%edx   ; onto certain registers
 mov $0x22,%esi
 mov $0x11,%edi
 callq 4004d7 <func1(int, int, int, int, int)>
 mov $0x0,%eax
 pop %rbp
 retq 
 nopl 0x0(%rax,%rax,1)

Patrones en assembly

Recorriendo un arreglo

// Given an array A, and its size, 
// return the sum of its elements

int sum(int *A, int size) {
    int i = 0;
    int accum = 0;
    for (i = 0; i < size; i++) {
      accum = ctr + A[i];
    }
    return accum;
}

int main() { 
    int A[] = {0x11,0x22,0x33}; 
    return sum(A,3);
}

sum:
 8048374: push   %ebp
 8048375: mov    %esp,%ebp
 8048377: sub    $0x10,%esp

 804837a: movl   $0x0,-0x8(%ebp)      ; i = 0
 8048381: movl   $0x0,-0x4(%ebp)      ; accum = 0
 8048388: movl   $0x0,-0x8(%ebp)      ; i = 0
 804838f: jmp    80483a3 <sum+0x2f>

 8048391: mov    -0x8(%ebp),%eax      ; eax = i
 8048394: shl    $0x2,%eax'           ; eax = eax * 4;
 8048397: add    0x8(%ebp),%eax       ; eax = eax + arg1
 804839a: mov    (%eax),%eax          ; eax = *eax
 804839c: add    %eax,-0x4(%ebp)      ; accum = accum + eax
 804839f: addl   $0x1,-0x8(%ebp)      ; i++

 80483a3: mov    -0x8(%ebp),%eax      ; eax = i
 80483a6: cmp    0xc(%ebp),%eax       ; eax < size ? 
 80483a9: jl     8048391 <sum+0x1d>   ; jump if true

 80483ab: mov    -0x4(%ebp),%eax      ; eax = acum, to return it
 80483ae: leave  
 80483af: ret    

main:
  40048d: push   %rbp
  40048e: mov    %rsp,%rbp
  400491: sub    $0x10,%rsp

  400495: movl   $0x11,-0x10(%rbp)
  40049c: movl   $0x22,-0xc(%rbp)
  4004a3: movl   $0x33,-0x8(%rbp)
  4004aa: lea    -0x10(%rbp),%rdi
  4004ae: mov    $0x3,%esi
  4004b3: callq  400448 <sum>

  4004b8: leaveq 
  4004b9: retq   

Loop examples

         push ebp
         mov ebp, esp
         mov esi, [ebp + 8]
         mov ebx, 0
         mov eax, 0
         mov ecx, 0

Label01: mov ecx, [esi + ebx * 4]
         add eax, ecx
         inc ebx
         cmp ebx, 100
         jne Label01

         mov esp, ebp
         pop ebp
         ret

Example taken from csaw2012reversing.exe:

00401030  /$ 55             PUSH EBP
00401031  |. 8BEC           MOV EBP,ESP
00401033  |. 51             PUSH ECX
00401034  |. C745 FC 000000>MOV DWORD PTR SS:[EBP-4],0

0040103B  |> 8B45 08        /MOV EAX,DWORD PTR SS:[EBP+8]; [EBP+8] is a param which is a pointer
0040103E  |. 0FB608         |MOVZX ECX,BYTE PTR DS:[EAX] ; move BYTE to reg with 0 ext  
00401041  |. 85C9           |TEST ECX,ECX                ; 
00401043  |. 74 24          |JE SHORT csaw2012.00401069  ; jump if byte is zero

00401045  |. 8B55 08        |MOV EDX,DWORD PTR SS:[EBP+8] ;Once again access the param
00401048  |. 0FB602         |MOVZX EAX,BYTE PTR DS:[EDX]  ;Put a character to EAX
0040104B  |. 35 FF000000    |XOR EAX,0FF                  ;Xor it with 0xFF
00401050  |. 8B4D 08        |MOV ECX,DWORD PTR SS:[EBP+8] ;Copy it back
00401053  |. 8801           |MOV BYTE PTR DS:[ECX],AL     
00401055  |. 8B55 08        |MOV EDX,DWORD PTR SS:[EBP+8] ;Increment the param
00401058  |. 83C2 01        |ADD EDX,1
0040105B  |. 8955 08        |MOV DWORD PTR SS:[EBP+8],EDX ;
0040105E  |. 8B45 FC        |MOV EAX,DWORD PTR SS:[EBP-4] ; Get a local var
00401061  |. 83C0 01        |ADD EAX,1                    ; Increment
00401064  |. 8945 FC        |MOV DWORD PTR SS:[EBP-4],EAX ; And store back
00401067  |.^EB D2          \JMP SHORT csaw2012.0040103B
00401069  |> 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
0040106C  |. 8BE5           MOV ESP,EBP
0040106E  |. 5D             POP EBP
0040106F  \. C3             RETN

Branch example

         push ebp
         mov ebp, esp

         mov eax, 0
         mov ecx, [ebp + 8]
         cmp ecx, 0
         jne Label01
         inc eax
         jmp Label02
Label01: dec eax
Label02: mov ecx, [ebp + 12]
         cmp ecx, 0
         jne Label03
         inc eax
Label03: mov esp, ebp
         pop ebp
         ret

A nice reference for x86: http://www.cs.virginia.edu/~evans/cs216/guides/x86.html