본문 바로가기
Security/Windows System

Windows on Windows 64 : x64시스템에서 x86 프로그램 시스템 콜

by Winduck 2020. 5. 28.
반응형

주변에서 이전에 우연히 x64시스템에서 x86 API호출 과정에 대해 이야기가 나왔고 한번 찾아봐야지 하다가 이제야 작성하게 됐다.

 

먼저 Windows on Windows64 (일명 WoW64)는 쉽게 말해 x64시스템에서 x86프로그램을 실행시키기 위해 개발된 방법이다. 

 

기본 x86시스템에서는 기본 자료처리를 4바이트로 하지만 x64경우 기본 8바이트 자료처리를 하기 때문에 실행을 위해이에 대한 호환이 필요하다. 따라서 본 글에서는 해당 과정에 대해서 확인하고자 한다.

 

테스트 환경은 Windows 10 x64 ver.1803에서 실행되었으며 x86으로 빌드된 프로그램은 파라미터로 받은 프로세스를 실행시키는 방식(CreateProcessA)으로 진행하였다.

 

 

먼저, x86과 동일하게 KERNELBASE!CreateProcessA -> KERNELBASE!CreateProcessInternalA -> KERNELBASE!CreateProcessInternalW -> ntdll!NtCreateUserProcess까지는 동일하다.

 

하지만 NtCreateUserProcess내부에서 달라진다. 본래 x86에서는 KiFastSystemCall이 호출되는데

x64에서는 ntdll!Wow64SystemServiceCall가 호출된다.

 

이후 ntdll!Wow64SystemServiceCall은 wow64cpu!KiFastSystemCall를 호출하는데 이 모듈부터 x64로 진입한다.

wow64cpu!KiFastSystemCall -> wow64cpu!CpupReturnFromSimulatedCode를 호출한다.

 

CpupReturnFromSimulatedCode 내부에 ServiceNoTurbo가 호출되고 _wow64!Wow64SystemServiceEx 를 호출한다.

 

아래는 CpupReturnFromSimulatedCode실행흐름이다.

wow64cpu!CpupReturnFromSimulatedCode:
00000000`77d618d2 4987e6          xchg    rsp,r14
00000000`77d618d5 458b06          mov     r8d,dword ptr [r14]
00000000`77d618d8 4983c604        add     r14,4
00000000`77d618dc 4589453c        mov     dword ptr [r13+3Ch],r8d
00000000`77d618e0 45897548        mov     dword ptr [r13+48h],r14d
00000000`77d618e4 4d8d5e04        lea     r11,[r14+4]
00000000`77d618e8 41897d20        mov     dword ptr [r13+20h],edi
00000000`77d618ec 41897524        mov     dword ptr [r13+24h],esi
00000000`77d618f0 41895d28        mov     dword ptr [r13+28h],ebx
00000000`77d618f4 41896d38        mov     dword ptr [r13+38h],ebp
00000000`77d618f8 9c              pushfq
00000000`77d618f9 4158            pop     r8
00000000`77d618fb 45894544        mov     dword ptr [r13+44h],r8d
wow64cpu!TurboDispatchJumpAddressStart:
00000000`77d618ff 8bc8            mov     ecx,eax                     ; Service Index Info
00000000`77d61901 c1e910          shr     ecx,10h             
00000000`77d61904 41ff24cf        jmp     qword ptr [r15+rcx*8]  ; Jmp ServiceNoTurbo
wow64cpu!ServiceNoTurbo:
00000000`77d61908 8bc8            mov     ecx,eax                    ; param1 ( Service Index Info)
00000000`77d6190a 498bd3          mov     rdx,r11                   ; param2 ( Parmeter Info )
00000000`77d6190d ff157d280000    call    qword ptr [wow64cpu!_imp_Wow64SystemServiceEx (00000000`77d64190)] ds:00000000`77d64190={wow64!Wow64SystemServiceEx (00000000`77df77c0)}
00000000`77d61913 41894534        mov     dword ptr [r13+34h],eax
00000000`77d61917 e9c3feffff      jmp     wow64cpu!RunSimulatedCode+0x2f (00000000`77d617df)

위 내용을 설명하자면 Wow64SystemServiceEx내부를 확인해보았다.

x64 fastcall에서 파라미터 각각 1,2를 rcx와 rdx로 ServiceNoTurbo에서 'mov ecx,eax'를 수행하는데 이는 서비스 인덱스 정보이다.

또한 CpupReturnFromSimulatedCode에서 r11로 옮겨졌던  rdx로 전달하여 Wow64SystemServiceEx 호출한다

(x86시스템에서 커널모드 진입 KiFastSystemCall호출시 eax에 서비스 테이블 인덱스를 담는데 x64에서는 유저 레벨 서비스 테이블 인덱스 정보로 사용한다.)

 

Wow64SystemServiceEx의 역할은 서비스 테이블에서 서비스 주소를 가져오고 이를 호출하는 역할을 수행한다.

Index연산방식은 x86에서 eax로 전달받은 4바이트에서 상위 1바이트와 하위 3바이트를 나누어 서비스 접근을 수행한다. 연산방법은 아래와 같다.

 

Index = (indexinfo >> 0xC) & 3; 
 offset = indexinfo & 0xFFF;
*(*&ServiceTables[3 * v4] + 8 * v5); ServiceAddress = *(*&ServiceTables[3 * Index ] + 8 * offset );

이처럼 수행하여 서비스 주소를 가져와 파라미터 정보를 전달하여 wow64!whNtCreateUserProcess 를 호출한다.

최종 호출 스택 정보는 다음과 같다.

0:000> k
Child-SP          RetAddr           Call Site
00000000`0063db68 00000000`77e0310d ntdll!NtCreateUserProcess
00000000`0063db70 00000000`77e02854 wow64!Wow64NtCreateUserProcess+0xe1
00000000`0063dc40 00000000`77df7913 wow64!whNtCreateUserProcess+0x4a4
00000000`0063df20 00000000`77d61913 wow64!Wow64SystemServiceEx+0x153
00000000`0063e7e0 00000000`77d61389 wow64cpu!ServiceNoTurbo+0xb
00000000`0063e890 00000000`77dfcec6 wow64cpu!BTCpuSimulate+0x9
00000000`0063e8d0 00000000`77dfcdb0 wow64!RunCpuSimulation+0xa

이렇게 진입된 NtCreateUserProcess에서는 아래와 같은 코드로 커널모드에 진입한다.

ntdll!NtCreateUserProcess:
00007ffb`d3e5c1c0 4c8bd1          mov     r10,rcx
00007ffb`d3e5c1c3 b8c2000000      mov     eax,0C2h
00007ffb`d3e5c1c8 f604250803fe7f01 test    byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffb`d3e5c1d0 7503            jne     ntdll!NtCreateUserProcess+0x15 (00007ffb`d3e5c1d5)
00007ffb`d3e5c1d2 0f05            syscall
00007ffb`d3e5c1d4 c3              ret

이상으로 글을 마칩니다. 

틀린내용있다면 말씀해주시면 감사하겠습니다~!!

 

반응형

'Security > Windows System' 카테고리의 다른 글

Kernel API Prefix  (0) 2020.05.28
NT / Zw Native API 차이  (0) 2019.04.05
I/O Control Code를 정의하는 CTL_CODE  (0) 2018.07.31
Windows x64커널 진입 : 커널모드편  (1) 2018.04.14
x64 Calling Convention(Windows)  (0) 2018.04.14

댓글