2016-09-03 5 views
1

NtDll이 x86 프로세스에서 작동하는 방식을 찾고 있었는데 IDA PRO를 사용하여 NtCreateFile 함수를 디버깅했습니다. 그것을위한 코드는 다음입니다 :x86- x64 어셈블리 코드 스위치 구현

mov  eax, 55h  ; NtCreateFile 
mov  edx, offset [email protected] ; 
call edx ; Wow64SystemServiceCall() ; 
retn 2Ch 

그리고 Wow64SystemServiceCall()을 :

mov  edx, large fs:30h 
mov  edx, [edx+464h] 
test edx, 2 
jz  short loc_7738B5C8 
int  2Eh    ; DOS 2+ internal - EXECUTE COMMAND 
         ; DS:SI -> counted CR-terminated command string 
retn 
loc_7738B5C8:       ; CODE XREF: 
jmp  far ptr byte_7738B8FF 

나는 jmp far ptr byte_7738B8FF 에 대한 명령 코드를 고개는 다른 세그먼트, 0x33을 jmp 0x33:0x7738b5cf에 점프입니다 EA CF B5 38 77 33 00이었다. 그래서 인터넷에서 읽은 것에서 이것은 64 비트 시스템의 프로세스를위한 x64 세그먼트 기반입니다. 불행하게도 나는 더 이상 디버그 할 수 없다. ida가 점프를 따라 가지 않기 때문이다. 하지만 난 64 용으로 컴파일 된 또 다른 간단한 C 응용 프로그램을 제작하고, 부착 64 IDA PRO 원격 디버거 CreateFile을 불러 분해를 보았다, 그리고 NtCreateFile은과 같이보고했다 :

x64_NtCreateFile proc near 
mov  r10, rcx 
mov  eax, 55h 
test byte ptr ds:7FFE0308h, 1 
jnz  short loc_7FFED6695B85 
syscall 
retn 
loc_7FFED6695B85:      
int  2Eh    ; DOS 2+ internal - EXECUTE COMMAND 
         ; DS:SI -> counted CR-terminated command string 
retn 

그래서 내가 어떻게하는지, 몇 가지 질문이 있습니다 x86 프로세스에서 점프가 ntdll이 연결된 점프 jmp 0x33:0x7738b5cfx64_NtCreateFile 첫 번째 명령어로 넘어 갔습니까? 이 경우 x86에서 x64 로의 전환은 어떻게됩니까? 기본적으로 나는 x86 애플리케이션을 만들고 점프로 세그먼트를 전환 할 수 있으며, 그냥 x32 코드를 실행합니다. db (0x00) ; x64 machine code commands과 같은 작업을 수행하여 만들 수 있습니다. 바로이게 맞습니까?

+0

읽기 업 이리. 먼저 16 비트 -> 32 비트 변환 후 32 -> 64 비트 전환. – enhzflep

+0

'Ida가 나쁜 디버거이기 때문에'ida가 점프를 따라 가지 않기 때문에'불행히도 더 이상 디버그 할 수 없습니다. windbg를 사용하십시오 - 당신이 점프에 들어가도록 허락합니다. – RbMm

+0

@RbMm Advice에게 감사드립니다. 나는 그것을 시도하고 덜 편안하지만, 분해의 측면에서 더 나은 – Vlad

답변

3

당신이 주소 0x7738b5cf에서 바이트를 보면, 단일 x86_64의 명령 jmp QWORD PTR [r15+0xf8]에 해당하는 것을

(당신이 윈도우 8.1에있어 적어도 경우 이상) 41 FF A7 F8 00 00 00

처럼 볼 것입니다.

R15 레지스터는 항상 wow64cpu.dll합니다 (R15 레지스터에서이 테이블을 가리 키도록 설정되어 64 비트에서 특별한 점프 테이블을 가리 킵니다 오른쪽 멀리 점프를 통해 64 비트 코드가 실행되는 32 비트에서 전환 한 후 응용 프로그램의 32 비트 진입 점보다 먼저 실행되는 코드).

[r15+0xf8]

그냥 syscall 명령을 사용하여 wow64cpu.dllCpupReturnFromSimulatedCode 방법을 가리, 어떤 설정을 할 것입니다 올바른 컨텍스트를하고 ( NtCreateFile에 대한 귀하의 경우) 실제 시스템 호출을 수행하기 위해 발생합니다.

이에 정성 들여 일부 내용

, 참조 :

부트 스트랩하는 OS가 당신에게 도움이 될 수있는 방법에 대한
+0

고마워, 정확히 내가 알아 내려고 시도했던 것. 이제는 sysenter로 Nt 함수를 호출 할 수 있습니다. – Vlad

2

예, 저는 64 비트 창에서 실행되는 32 비트 Windows 응용 프로그램에서 64 비트 코드를 실행할 수 있음을 확인했습니다.

Mixing x86 with x64 code에 대한 설명과 예를 제공합니다.

#define EM(a) asm("db " #a); 

#define X64_Start_with_CS(_cs) \ 
{ \ 
    EM(0x6A) EM(_cs)      /* push _cs     */ \ 
    EM(0xE8) EM(0) EM(0) EM(0) EM(0)  /* call $+5     */ \ 
    EM(0x83) EM(4) EM(0x24) EM(5)  /* add dword [esp], 5  */ \ 
    EM(0xCB)        /* retf       */ \ 
} 

#define X64_End_with_CS(_cs) \ 
{ \ 
    EM(0xE8) EM(0) EM(0) EM(0) EM(0)  /* call $+5     */ \ 
    EM(0xC7) EM(0x44) EM(0x24) EM(4)  /*        */ \ 
    EM(_cs) EM(0) EM(0) EM(0)   /* mov dword [rsp + 4], _cs */ \ 
    EM(0x83) EM(4) EM(0x24) EM(0xD)  /* add dword [rsp], 0xD  */ \ 
    EM(0xCB)        /* retf       */ \ 
} 

#define X64_Start() X64_Start_with_CS(0x33) 
#define X64_End() X64_End_with_CS(0x23) 

#define __break() asm("int3") 

int main(void) 
{ 
    __break(); 
    X64_Start(); 
    EM(0x48) EM(0x8D) EM(0x05) EM(0xF9) EM(0xFF) EM(0xFF) EM(0xFF) // lea rax, [$] ; rip-relative 
    X64_End(); 
    __break(); 
} 

내가 다음 디버거에서 그것을 실행하고 EAX는 64 비트 명령어의 주소를 포함하는 것이 "레아를 발견 :

내가 (적응 내 작은 C 컴파일러로 컴파일) 시도 것입니다 rax, [$] "두 번째 중단 점에 도달했을 때.

+0

대답 주셔서 감사합니다, 매우 도움이, 나는 코드를 찾아 꽤 괜찮은 이해했습니다. 만약 내가 예를 들어'VirtualAlloc'을 페이지 읽기/쓰기로하고 x86 프로세스에서 x64 명령어를 쓰면 뭔가를 물어볼 수 있습니까? 같은 세그먼트 스위치 트릭을해야할까요? – Vlad

+0

@Vlad 64 비트 코드를 실행하려면 CS에 64 비트 (AKA 긴 모드) 코드 설명 자의 선택기가로드되어 있어야합니다. 당신은 원거리 점프, 원거리 통화, 원거리 복귀로 CS를 변경합니다. –