2015-04-24 7 views
6

Mam funkcji Windows 7 callgate że używam wywołać funkcje NT bezpośrednio:Próbując stworzyć Windows 8 syscall funkcji callgate

//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); 
} 

staram się zrobić to samo dla Windows 8.1. Zaktualizowałem wszystkie indeksy wywołania funkcji; Zauważyłem jednak rzeczywista funkcja callgate jest zupełnie inny w systemie Windows 8.1:

Oto co rzeczywiste brama wywołanie wygląda (znajduje się w Ntdll.dll) dla funkcji 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 

Teraz tutaj jest dokładny ta sama funkcja NT (ZwCreateThreadEx) na Windows 8.1

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

staram wszelkiego rodzaju rzeczy, aby uzyskać ten działa na Windows 8.1, ale nie miałem bezskutecznie. Nie potrafię wyjaśnić, co to jest, ani co się dzieje, tylko wiem, że robię to poprawnie w Windows 7.

Z wyglądu funkcji W8.1 próbowałem wymyślić tę jedną funkcję (Nie działa):

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; 
    }; 
} 

Każda pomoc zostanie doceniona bardzo.

+1

Dlaczego ... och - dlaczego chcesz to zrobić bez pisania sterownika? –

Odpowiedz

2

Nowa funkcja callGate nie ustawić ramkę stosu chcesz, adres zwrotny na szczycie stosu jest zwrotny adres callGate nie dyspozycja po wywołaniu.

To właśnie stos wygląda po instrukcji CALL jest wykonywany w przykładzie ZwCreateThreadEx z systemu Windows 8.1:

  • adres zwrotny (retn 0x2c instrukcji)
  • adres zwrotny (Caller ZwCreateThreadEx)
  • argumenty (11 DWORD)

Oto, jak wygląda stos po wykonaniu instrukcji JMP w nowej funkcji callGate :

  • adres zwrotny (wywołujący callGate)
  • argumenty

Są też inne problemy z nową funkcją callGate. Zapisuje wartości w zmiennych globalnych, co oznacza, że ​​funkcja nie jest bezpieczna dla wątków. Dwa wątki nie mogą jednocześnie zadzwonić pod numer callBack, nie niszcząc zapisanych wartości. Wykorzystuje zarówno inline zespół, który sprawia, że ​​kod jest bardziej skomplikowana, że ​​to musi być i dokonać jego zachowanie zależy od nieudokumentowanych: jak kompilator utworzy stos dla funkcji.

Oto jak napisać wersję callGate Windows 8.1 w 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 

Implementacja ta jest ograniczona do MAXARGS argumentów (zmienić wartość, jeśli każde wezwanie systemu Windows, trwa dłużej niż 16 argumentów). Wykorzystuje makra wygenerować tabelę bloków CALL/code RET, aby uniknąć konieczności przechowywania liczbę argumentów gdzieś po drugiej stronie połączenia.Mam wersję, która obsługuje dowolną liczbę argumentów, ale jest bardziej skomplikowana i wolniejsza. Ta implementacja nie została przetestowana, nie mam systemu Windows 8.1.

+0

Wiem, że mówi się, aby nie zostawiać komentarzy po prostu dziękuję, ale szczególnie chciałem wrócić i podziękować, ponieważ twój kod otworzył mi pomysł tabeli retn, co pozwoliło mi napisać to: http: // pastebin. com/PBHTd5E9 – applecider