2016-09-03 12 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はジャンプに従わないからです。しかし、私は、x64用にコンパイルされ、別の単純なCアプリケーションを作って、CreateFileと呼ばれる、添付のx64 IDA PROリモートデバッガ、および解体を見上げ、そして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アプリケーションを作成し、ジャンプセグメントを切り替えて、ちょうどdb (0x00) ; x64 machine code commandsのような何かを行うことによって作成することができますx64コードを実行する、これは正しいですか?

+0

ここに。最初に16ビット→32ビットトランジション、その後で32→64ビットスイッチとなります。 – enhzflep

+0

'残念ながら、私はさらにデバッグすることができません。なぜなら、idaは悪いデバッガであるため、idaはジャンプに従わないからです。 windbgを使用してください - あなたはジャンプに入ることができます – RbMm

+0

@RbMmアドバイスのおかげで。私はそれを試して、それはあまり快適ではなかったが、分解の面ではより良い – Vlad

答えて

3

あなたはアドレス0x7738b5cfでバイトを見れば、あなたは、単一のx86_64の命令jmp QWORD PTR [r15+0xf8]に対応

41 FF A7 F8 00 00 00のようなもの(あなたがWindowsの8.1またはそれ以降にしている少なくとも場合)

を見るでしょう。

右遠くにジャンプを経て、64ビットのコードが実行される32ビットから切り替えた後、R15レジスタは常にwow64cpu.dll内の特別なジャンプテーブルを指します(R15レジスタは、64ビットからこのテーブルを指すように設定されアプリケーションの32ビットエントリポイントより前に実行されるコード)。

[r15+0xf8]はちょうど、wow64cpu.dllCpupReturnFromSimulatedCode方法を指している意志のセットアップ右コンテキストとsyscall命令を使用して(NtCreateFileためのあなたのケースでは)実際のシステムコールを実行するために起こります。この時に詳しく説明いくつかの情報については

、以下を参照してください。OSがブートストラップされる方法についての読書アップがあなたに有益であるかもしれ

+0

ありがとう、それは私が把握しようとしていたものです。これで、sysenterでNt関数を呼び出そうとすることができます – Vlad

2

はい、私は、64ビットのWindowsで動作する32ビットのWindowsアプリケーションで64ビットのコードを実行できることを確認できます。

Mixing x86 with x64 codeには、説明とその実行例が示されています。

これは私が(するようになって、私の小型のCコンパイラでコンパイル)しようとしたものです:

#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ビット命令「リーのアドレスが含まれていることに気づきましたrax、[$] "と表示されます。

+0

答えのおかげで、非常に私を助け、私はコードを見て、それはかなりokを理解した。私はあなたに何かを尋ねることができます、もし私が例えば 'VirtualAlloc'をページの実行/読み書きをして、x86プロセスからx64命令を書いたら、私は同じセグメントスイッチのトリックをする必要がありますか? – Vlad

+0

@Vlad 64ビットコードを実行する場合、64ビット(AKAロングモード)コード記述子のセレクタをCSにロードする必要があります。あなたは、遠くのジャンプ、遠いコール、遠いリターンでCSを変えます。 –

関連する問題