2015-04-24 9 views
6

Ho una funzione di Windows 7 callgate che uso per chiamare direttamente le funzioni NT:Cercando di creare una funzione di Windows 8 callgate syscall

//Windows 7 syscall 

__declspec(naked) 
NTSTATUS __fastcall wow64 (DWORD ecxId, char *edxArgs) 
{ 
    __asm 
    { 
     mov eax, ecx; 
     mov ecx, m_param; 
     call DWORD ptr fs:[0xc0]; 
     add esp, 0x4; 
     retn; 
    }; 
} 

NTSTATUS callGate (DWORD id, ...) 
{ 
    va_list valist; 
    va_start(valist,id); 
    return wow64(id,valist); 
} 

//Example NTClose function 
NTSTATUS closeHandle (void *object) 
{ 
    m_param = 0; 
    return callGate (0xc, object); 
} 

che sto cercando di fare la stessa cosa per le finestre 8.1. Ho aggiornato tutti gli indici di chiamata di funzione; tuttavia ho notato la funzione callgate reale è molto diversa su Windows 8.1:

Ecco cosa la porta chiamata effettiva assomiglia (situato nel ntdll.dll) per la funzione ZwCreateThreadEx

mov eax, 0xA5 //the call index 
xor ecx, ecx //(m_param) 
lea edx, dword ptr ss:[esp + 0x4] //this causes an sp-analysis failure in IDA 
call dword ptr fs:[0xC0] 
add esp, 0x4 
retn 0x2C 

Ora qui è l'esatto stessa funzione NT (ZwCreateThreadEx) su Windows 8.1

mov eax, 0xB0 //the call index 
call dword ptr fs:[0xC0] 
retn 0x2C //2c/4 = 11 parameters 

ho cercato tutti i tipi di roba per ottenere questo lavoro su Windows 8.1, ma non hanno avuto alcun risultato. Non riesco a spiegare qual è il problema o cosa sta andando male, tutto quello che so è che sto facendo correttamente su Windows 7.

Dall'aspetto della funzione W8.1, ho tentato di creare questa singola funzione (Non funziona):

DWORD dwebp,dwret,dwparams; //for saving stuff 

NTSTATUS __cdecl callGate (DWORD id, DWORD numparams, ...) 
{ 
    _asm 
    { 
     pop dwebp; //save ebp off stack 
     pop dwret; //save return address 
     pop eax; //save id 
     pop dwparams; //save param count 
     push dwret; //push return addy back onto stack cuz thats how windows has it 
     JMP DWORD ptr fs:[0xc0]; //call with correct stackframe (i think) 
     mov ecx, numparams; //store num params 
     imul ecx, 4; //multiply numparams by sizeof(int) 
     add esp, ecx; //add to esp 
     ret; 
    }; 
} 

Qualsiasi aiuto sarebbe molto apprezzato.

+1

Perché-oh-perché vuoi farlo senza scrivere un autista? –

risposta

2

La nuova funzione callGate non imposta il frame stack desiderato, l'indirizzo di ritorno nella parte superiore della pila è l'indirizzo di ritorno di callGate non l'istruzione dopo la chiamata.

Questo è ciò che lo stack si presenta come dopo l'istruzione CALL viene eseguita nel tuo esempio ZwCreateThreadEx da Windows 8.1:

  • indirizzo di ritorno (retn 0x2c istruzioni)
  • indirizzo di ritorno (chiamante del ZwCreateThreadEx)
  • argomenti (11 DWORD)

Ecco come appare lo stack dopo l'esecuzione dell'istruzione JMP nella nuova funzione callGate :

  • indirizzo di ritorno (chiamante del Callgate)
  • argomenti

Ci sono altri problemi con la vostra nuova funzione Callgate. Salva valori in variabili globali, il che significa che la funzione non è thread-safe. Due thread non possono chiamare callBack allo stesso tempo senza cestinare questi valori salvati. Usa assembly inline che rendono il tuo codice più complicato e deve essere dipendente da un comportamento non documentato: come il compilatore imposterà lo stack per la funzione.

Ecco come scrivo la versione di Windows 8.1 di Callgate in MASM:

_text SEGMENT 

MAXARGS = 16 

do_call MACRO argcount 
@@call&argcount: 
    call DWORD PTR fs:[0C0h] 
    ret argcount * 4 
    ENDM 

call_table_entry MACRO argcount 
    DD OFFSET @@call&argcount 
    ENDM 

_callGate PROC 

    pop edx  ; return address 
    pop eax  ; id 
    pop ecx  ; numparams 
    push edx  ; return address 

    cmp ecx, MAXARGS 
    jg @@fail 

    jmp [@@call_table + ecx * 4] 

@@args = 0 
    REPT MAXARGS + 1 
     do_call %@@args 
    @@args = @@args + 1 
    ENDM 

@@fail: 
    ; add better error handling 
    int 3 
    jmp @@fail 

@@call_table: 
@@args = 0 
    REPT MAXARGS + 1 
     call_table_entry %@@args 
    @@args = @@args + 1 
    ENDM 


_callGate ENDP 

_TEXT ENDS 

    END 

Questa implementazione è limitata a MAXARGS argomenti (cambiare il valore eventuale chiamata di sistema di Windows richiede più di 16 argomenti). Usa macro per generare una tabella di blocchi di codice CALL/RET per evitare di dover memorizzare il numero di argomenti da qualche parte attraverso la chiamata.Ho una versione che supporta un numero qualsiasi di argomenti, ma è più complicata e un po 'più lenta. Questa implementazione non è stata testata, non ho Windows 8.1.

+0

So che è stato detto di non lasciare commenti solo per dire grazie, ma in particolare volevo tornare e ringraziarti perché il tuo codice mi ha aperto l'idea di un nuovo tavolo, permettendomi così di scrivere questo: http: // pastebin. com/PBHTd5E9 – applecider

Problemi correlati