2016-04-26 22 views
6

Ich versuche, alle Aufrufe und Rets von einer ausführbaren Datei mit ptrace analysieren. In Übereinstimmung mit der x64opcode, fand ich Opcodes für Aufrufe: 0xe8 und für Rets: 0xc3, 0xc2, 0xca, 0xcb.Parsing Call und Ret mit Ptrace.

Seit ich sie analysiert habe, habe ich mehr Rets als Calls gefunden.

Es ist das Programm, das ich verfolgen:

void func()                      
{                        
    write(1, "i", 1);                    
}                        

int main(int ac)                    
{                        
    func();                      
    return(0);                     
} 

Es ist mein Tracer:

int      tracer(t_info *info)             
{                        
    int     status;                 
    long     ptr;                 
    int     ret = 0;                     
    int     call = 0;                     


    waitpid(info->pid, &status, 0);                
    while (WIFSTOPPED(status))                 
    {                       
     ptrace(PTRACE_GETREGS, info->pid, NULL, info->regs);          
     ptr = ptrace(PTRACE_PEEKDATA, info->pid, info->regs->rip);        
     if (((ptr & 0x000000ff) == 0xe8)) // Opcode for call                
     {                      
      call++;                    
     }                      
     else if (((ptr & 0x000000ff) == 0xc3) // Opcodes for rets         
       || ((ptr & 0x000000ff) == 0xc2)             
       || ((ptr & 0x000000ff) == 0xca)             
       || ((ptr & 0x000000ff) == 0xcb))             
     {                      
      ret++;                    
     }                      
     ptrace(PTRACE_SINGLESTEP, info->pid, 0, 0);            
     waitpid(info->pid, &status, 0);               
    }                       
    printf("Calls: %i\nRets: %i\nDiff: %i\n", call, ret, call - ret);            
    return (0);                     
} 

Da meine Ausgabe ist:

Calls: 656 
Rets: 666 
Diff: -10 

Warum gibt es nicht die gleiche Anzahl von rets und ruft? Vermisse ich einige Opcodes? Gibt es Funktionen, die nicht zurückkehren?

+0

BTW Sie nicht _parse_ hier, aber Sie lieber _trace_. –

Antwort

4

Sie zum Beispiel verpassen indirekte Anrufe wie

callq *(<expr>) 

die andere Opcodes verwenden. Libc-Standard-Initialisierungsroutinen nutzen diese. Je nach Ausdruck sind mehrere Opcodes möglich, zwei Beispiele:

ff d0     callq *%rax 
41 ff 14 dc    callq *(%r12,%rbx,8) 

Es ist wahrscheinlich nicht einfach, sie alle zu bekommen. Vielleicht wäre es einfacher und sauberer, die Anweisungen mit einer Bibliothek wie libbfd und libopcodes zu entschlüsseln

+2

Auch technisch müssen Sie nicht "ret" und "call" paaren, obwohl es eine gute Idee ist, dies zu tun. Im 32-Bit-Code zum Beispiel 'rufen Sie weiter; weiter: pop eax ist eine gängige Redewendung, um den aktuellen "eip" zu erhalten. Es ist besser, es in eine richtige Funktion zu zerlegen, aber es ist nicht immer getan. – Jester