wowarmhw dll что это

Сведения о реализации WOW64

Эмулятор WOW64 работает в пользовательском режиме. Он предоставляет интерфейс между 32-разрядной версией Ntdll.dll и ядром процессора и перехватывает вызовы ядра. Эмулятор WOW64 состоит из следующих библиотек DLL:

Эти библиотеки DLL, а также 64-разрядная версия Ntdll.dll являются единственными 64-разрядными двоичными файлами, которые можно загрузить в 32-разрядный процесс. в Windows 10 на ARM двоичные файлы чпе (скомпилированные гибридные переносимые исполняемые файлы) также могут быть загружены в 32-разрядный процесс x86.

При запуске Wow64.dll загружает версию x86 Ntdll.dll (или версию ЧПЕ, если она включена) и выполняет свой код инициализации, который загружает все необходимые 32-разрядные библиотеки DLL. почти все 32-разрядные библиотеки dll являются немодифицированными копиями 32-разрядных Windows двоичных файлов, хотя некоторые из них загружаются как чпе по соображениям производительности. некоторые из этих библиотек dll ведут себя по-разному на основе WOW64, чем в 32-разрядных Windows. обычно это обусловлено тем, что они совместно используют память с 64-разрядными компонентами системы. Все адресное пространство пользовательского режима свыше 32-разрядного предела резервируется системой. Дополнительные сведения см. в разделе Использование производительности и памяти в эмуляторе WOW64.

Вместо использования последовательности вызовов системной службы x86, 32-разрядных двоичных файлов, которые делают системные вызовы, перестраиваются для использования пользовательской последовательности вызова. Эта последовательность вызова недорога для перехвата WOW64, так как она полностью находится в пользовательском режиме. При обнаружении пользовательской последовательности вызовов ЦП WOW64 возвращается в собственный 64-разрядный режим и вызывается в Wow64.dll. Преобразователь выполняется в пользовательском режиме, чтобы снизить воздействие на 64-разрядное ядро и снизить риск ошибки в преобразователе, которая может привести к сбою в режиме ядра, повреждению данных или бреши в безопасности. Преобразователи извлекают аргументы из 32-битного стека, расширяют их до 64 бит, а затем выполняют собственный системный вызов.

Переменные среды

При создании 32-разрядного процесса с помощью 64-разрядного процесса или при создании 64-bit процесса в 32-разрядном процессе WOW64 устанавливает переменные среды для созданного процесса, как показано в следующей таблице.

Процесс Переменные среды
64-разрядный процесс _Архитектура процессора = amd64 или _ архитектура процессора = ia64 или _ архитектура процессора = ARM64
ProgramFiles =% ProgramFiles%
ProgramW6432 =% ProgramFiles%
CommonProgramFiles =% CommonProgramFiles%
CommonProgramW6432 =% CommonProgramFiles%
Windows server 2008, Windows Vista, Windows Server 2003 и Windows XP: переменные среды ProgramW6432 и CommonProgramW6432 были добавлены начиная с Windows 7 и Windows Server 2008 R2.
32-разрядный процесс _Архитектура процессора = x86
ПРОЦЕССОР _ ARCHITEW6432 =% _ архитектура процессора%
ProgramFiles =% ProgramFiles (x86)%
ProgramW6432 =% ProgramFiles%
CommonProgramFiles =% CommonProgramFiles (x86)%
CommonProgramW6432 =% CommonProgramFiles%

Глобальные перехватчики

Функцию сетвиндовшукекс можно использовать для внедрения библиотеки DLL в другой процесс при соблюдении следующих условий.

Имейте в виду, что в потоке, в котором установлен обработчик, а не поток, обрабатывающий обработчик, может быть вызвана _ мышь, что, в том, что для входа в систему, т _. е. _ Журнал * _, _ _. Для этих обработчиков возможно, что будут вызываться как 32-разрядные, так и 64-разрядные обработчики, если 32-разрядный обработчик впереди в цепочке прерываний до 64-разрядного обработчика. Дополнительные сведения см. в разделе Использование перехватчиков.

Источник

Что такое WOW64.dll, это безопасно удалить?

Обновление: Перестаньте получать сообщения об ошибках и замедляйте работу своей системы с помощью нашего инструмента оптимизации. Получите это сейчас на эту ссылку

Эти библиотеки DLL, а также 64-битная версия Ntdll.dll являются единственными 64-битными двоичными файлами, которые можно загрузить в 32-битный процесс. В Windows 10 на ARM двоичные файлы CHPE (скомпилированный переносной гибридный исполняемый файл) также могут быть загружены в процесс 32-bit x86.

Что такое Wow64.dll?

Часть имени «WOW64» относится здесь к программному обеспечению Microsoft «32-разрядная версия Windows на 64-разрядной версии Windows», которое является частью операционной системы. Таким образом, Windows может запускать 32-битные программы в 64-битной версии Windows. WoW64 перенаправляет доступ к файлам, чтобы программы работали правильно.

Например, если вы устанавливаете 32-битную программу в 64-битной версии Windows и пытаетесь записать ее в папку C: \ Program Files, WoW64 направляет ее в C: \ Program Files (x86). И если он хочет получить доступ к папке C: \ Windows \ System32, WoW64 направит его в C: \ Windows \ SysWOW64. Windows делает это с помощью перенаправителя файловой системы.

Все это происходит автоматически и прозрачно в фоновом режиме. Программе даже не нужно знать, что она работает в 64-битной операционной системе, которая позволяет старым 32-битным программам работать в 64-битных версиях Windows без изменений. WOW64 также перенаправляет доступ к реестру и обеспечивает наличие отдельных областей в реестре для 64-битных и 32-битных программ.

Ноябрьское обновление 2021:

Безопасно ли удалять файл Wow64.dll DLL?

Настоятельно рекомендуется не удалять файлы «wow64.dll», «wow64cpu.dll» или «wow64win.dll», поскольку эти файлы очень важны для стабильности операционной системы и используются во многих обычных процессах. Также обратите внимание, что никакие файлы в каталоге «Windows» не следует удалять или заменять, поскольку все файлы в папке являются неотъемлемой частью операционной системы.
Ошибка, связанная с «wow64.dll».

Большинство пользователей беспокоились о файле, потому что он связан с некоторыми ошибками автоматического выполнения. Некоторые из этих ошибок:

Эти Ошибки DLL ни в коем случае не критичны и не препятствуют функционированию операционной системы. Фактически, инженеры Windows рекомендуют игнорировать эти ошибки, поскольку они не связаны с конкретной проблемой.

На эти ошибки в основном указывает тот факт, что «32-битные» файлы невидимы для 64-битных процессов, а «64-битные» файлы не видны «32-битным» процессам. Фактически это можно наблюдать, выполнив следующие действия:

Затем выполните следующую команду

Вы заметите, что он отображает только файл «wow32.dll» и некоторые другие файлы.

Теперь вернитесь в папку PowerShell и дважды щелкните обычный значок PowerShell.
Введите и выполните те же команды, и вы заметите, что на этот раз видны только файлы wow64.dll и некоторые другие связанные файлы.

CCNA, веб-разработчик, ПК для устранения неполадок

Я компьютерный энтузиаст и практикующий ИТ-специалист. У меня за плечами многолетний опыт работы в области компьютерного программирования, устранения неисправностей и ремонта оборудования. Я специализируюсь на веб-разработке и дизайне баз данных. У меня также есть сертификат CCNA для проектирования сетей и устранения неполадок.

Источник

WoW64 internals

. re-discovering Heaven’s Gate on ARM

MSDN offers brief article on WoW64 implementation details. We can find that WoW64 consists of (ignoring IA-64):

Besides Nt* system call translation, the wow64.dll provides the core emulation infrastructure.

If you have previous experience with reversing WoW64 on x64, you can notice that it shares plenty of common code with WoW64 subsystem on ARM64. Especially if you peeked into WoW64 of recent x64 Windows, you may have noticed that it actually contains strings such as SysArm32 and that some functions check against IMAGE_FILE_MACHINE_ARMNT (0x1C4) machine type:

Those similarities can help anyone who is fluent in x86/x64, but not that much in ARM. Also, HexRays decompiler produce much better output for x86/x64 than for ARM32/ARM64.

Initially, my purpose with this blogpost was to get you familiar with how WoW64 works for ARM32 programs on ARM64. But because WoW64 itself changed a lot with Windows 10, and because WoW64 shares some similarities between x64 and ARM64, I decided to briefly get you through how WoW64 works in general.

Table of contents

Terms

Througout this article I’ll be using some terms I’d like to explain beforehand:

Kernel

This section shows some points of interest in the ntoskrnl.exe regarding to the WoW64 initialization. If you’re interested only in the user-mode part of the WoW64, you can skip this part to the Initialization of the WoW64 process.

Kernel (initialization)

Initalization of WoW64 begins with the initialization of the kernel:

nt!PspSystemDlls appears to be array of pointers to some structure, which holds some NTDLL-related data. The order of these NTDLLs corresponds with this enum (included in the PDB):

Now, let’s look how such structure looks like:

The nt!PspLocateSystemDll function intializes fields of this structure. The layout of this structure isn’t unfortunatelly in the PDB, but you can find a reconstructed version in the appendix.

x64 ARM64
(0) LdrInitializeThunk (0) LdrInitializeThunk
(1) RtlUserThreadStart (1) RtlUserThreadStart
(2) KiUserExceptionDispatcher (2) KiUserExceptionDispatcher
(3) KiUserApcDispatcher (3) KiUserApcDispatcher
(4) KiUserCallbackDispatcher (4) KiUserCallbackDispatcher
(5) KiUserCallbackDispatcherReturn
(5) KiRaiseUserExceptionDispatcher (6) KiRaiseUserExceptionDispatcher
(6) RtlpExecuteUmsThread
(7) RtlpUmsThreadYield
(8) RtlpUmsExecuteYieldThreadEnd
(9) ExpInterlockedPopEntrySListEnd (7) ExpInterlockedPopEntrySListEnd
(10) ExpInterlockedPopEntrySListFault (8) ExpInterlockedPopEntrySListFault
(11) ExpInterlockedPopEntrySListResume (9) ExpInterlockedPopEntrySListResume
(12) LdrSystemDllInitBlock (10) LdrSystemDllInitBlock
(13) RtlpFreezeTimeBias (11) RtlpFreezeTimeBias
(14) KiUserInvertedFunctionTable (12) KiUserInvertedFunctionTable
(15) WerReportExceptionWorker (13) WerReportExceptionWorker
(16) RtlCallEnclaveReturn
(17) RtlEnclaveCallDispatch
(18) RtlEnclaveCallDispatchReturn

On the other hand, all NtdllWow*Exports contain the same set of function names:

Those addresses are actually targets of the pointers in the NtdllWow*Exports structure. Also, those functions combined with PsWow*SharedInformation might give you hint that they’re related to this enum (included in the PDB):

Notice how the order of the SharedNtdll32BaseAddress corellates with the empty field in the previous screenshot (highlighted). The set of WoW64 NTDLL functions is same on both x64 and ARM64.

(The C representation of this data can be found in the appendix.)

Kernel (create process)

Initialization of the WoW64 process

The fun part begins!

NOTE: Initialization of the wow64.dll is same on both x64 and ARM64. Eventual differences will be mentioned.

Wow64DetectMachineTypeInternal determines the machine type of the executed process and returns it. Wow64SelectSystem32PathInternal selects the “emulated” System32 directory based on that machine type, e.g. SysWOW64 for x86 processes or SysArm32 for ARM32 processes.

Finally, the RunCpuSimulation function is called. This function just calls BTCpuSimulate from the binary-translator DLL, which contains the actual emulation loop that never returns.

wow64!ProcessInit

If any of these functions wouldn’t be exported, the DLL would be immediately unloaded.

If we’d drop custom wow64log.dll (which would export functions mentioned above) into the %SystemRoot%\System32 directory, it would actually get loaded into every WoW64 process. This way we could drop a custom logging DLL, or even inject every WoW64 process with native DLL!

For more details, you can check my injdrv project which implements injection of native DLLs into WoW64 processes, or check this post by Walied Assar.

wow64!ServiceTables

(More detailed definition of this structure is in the appendix.)

ServiceTables array is populated as follows:

These two symbols mentioned above are the only symbols that wow64.dll requires wow64win.dll to export.

Let’s have a look at sdwhnt32 service table:

The job of these wh* functions is to correctly convert any arguments and return values from the 32-bit version to the native, 64-bit version. Keep in mind that that it not only includes conversion of integers and pointers, but also content of the structures. Interesting note might be that each of the wh* functions has only one argument, which is pointer to an array of 32-bit values. This array contains the parameters passed to the 32-bit system call.

The ntdll.dll and win32u.dll are obvious and they represent the same thing as their native counterparts. The service tables used by kernel32.dll and user32.dll contain functions for transformation of particular csrss.exe calls into their 64-bit version.

wow64!Wow64SystemServiceEx

The system call number isn’t just an index, but also contains index of a system table which needs to be selected (this is also true for ntoskrnl.exe ):

wow64!ProcessInit (cont.)

We can see that there is no wow64cpu.dll on ARM64. Instead, there is xtajit.dll used for x86 emulation and wowarmhw.dll used for ARM32 emulation.

wow64.dll then loads one of the selected DLL and tries to find there following exported functions:

BTCpuProcessInit (!) BTCpuProcessTerm
BTCpuThreadInit BTCpuThreadTerm
BTCpuSimulate (!) BTCpuResetFloatingPoint
BTCpuResetToConsistentState BTCpuNotifyDllLoad
BTCpuNotifyDllUnload BTCpuPrepareForDebuggerAttach
BTCpuNotifyBeforeFork BTCpuNotifyAfterFork
BTCpuNotifyAffinityChange BTCpuSuspendLocalThread
BTCpuIsProcessorFeaturePresent BTCpuGetBopCode (!)
BTCpuGetContext BTCpuSetContext
BTCpuTurboThunkControl BTCpuNotifyMemoryAlloc
BTCpuNotifyMemoryFree BTCpuNotifyMemoryProtect
BTCpuFlushInstructionCache2 BTCpuNotifyMapViewOfSection
BTCpuNotifyUnmapViewOfSection BTCpuUpdateProcessorInformation
BTCpuNotifyReadFile BTCpuCfgDispatchControl
BTCpuUseChpeFile BTCpuOptimizeChpeImportThunks
BTCpuNotifyProcessExecuteFlagsChange BTCpuProcessDebugEvent
BTCpuFlushInstructionCacheHeavy

wow64!ThreadInit

ThreadInit does some little thread-specific initialization, such as:

x86 on x64

Entering 32-bit mode

RunSimulatedCode runs in a loop and performs transitions into 32-bit mode either via:

NOTE: Explanation of segmentation and “why does it work just by changing a segment register” is beyond scope of this article. If you’d like to know more about “long mode” and segmentation, you can start here.

You can see the simplest form of switching into the 32-bit mode. Also, at the beginning you can see that TurboThunkDispatch address is moved into the r15 register. This register stays untouched during the whole RunSimulatedCode function.

Leaving 32-bit mode

The Wow64SystemServiceCall is just a simple jump to the Wow64Transition :

If you remember, the Wow64Transition value is resolved by the wow64cpu!BTCpuGetBopCode function:

It selects either KiFastSystemCall or KiFastSystemCall2 based on the CpupSystemCallFast value.

The KiFastSystemCall2 looks like this (used when CpupSystemCallFast == 0 ):

Clearly, the KiFastSystemCall is faster, so why it’s not used used every time?

It turns out, CpupSystemCallFast is set to 1 in the wow64cpu!BTCpuProcessInit function if the process is not executed with the ProhibitDynamicCode mitigation policy and if NtProtectVirtualMemory(&KiFastSystemCall, PAGE_READ_EXECUTE) succeeds.

This is because KiFastSystemCall is in a non-executable read-only section ( W64SVC ) while KiFastSystemCall2 is in read-executable section ( WOW64SVC ).

But the actual reason why is KiFastSystemCall in non-executable section by default and needs to be set as executable manually is, honestly, unknown to me. My guess would be that it has something to do with relocations, because the address in the jmp 33h:$+9 instruction must be somehow resolved by the loader. But maybe I’m wrong. Let me know if you know the answer!

Turbo thunks

I hope you didn’t forget about the TurboThunkDispatch address hanging in the r15 register. This value is used as a jump-table:

There are 32 items in the jump-table.

CpupReturnFromSimulatedCode is the first code that is always executed in the 64-bit mode when 32-bit to 64-bit transition occurs. Let’s recapitulate the code:

You might be confused now, because few sections above we’ve defined the service number like this:

…therefore, after right-shifting this value by 16 bits we should get always 0, right?

It turns out, on x64, the WOW64_SYSTEM_SERVICE might be defined like this:

Let’s examine few WoW64 system calls:

Let’s finally explain “turbo thunks” in proper way.

The notation of Thunk* labels is as follows:

Let’s take the NtWaitForSingleObject and its turbo thunk Thunk3ArgSpNSpNSpReloadState as an example:

When we cross-check this information with its function prototype, it makes sense:

Disabling Turbo thunks

On Windows x64, the Turbo thunk optimization can be actually disabled!

The function prototype might look like this:

NOTE: This function prototype has been reconstructed with the help of the wow64!Wow64CallFunction64Nop function code, which just logs the parameters.

wow64cpu!BTCpuTurboThunkControl then checks the input parameter.

This means 2 things:

With all this in mind, we can achieve disabling Turbo thunks by this call:

What it might be good for? I can think of 3 possible use-cases:

x86 on ARM64

The x86 emulation on Windows ARM64 consists also of other “XTA” components:

With a simple Python script, we can mass-rename all functions referenced in this array:

I’d like to thank Milan Boháček for providing me this script.

Windows\SyCHPE32 & Windows\SysWOW64

One thing you can observe on ARM64 is that it contains two folders used for x86 emulation. The difference between them is that SyCHPE32 contains small subset of DLLs that are frequently used by applications, while contents of the SysWOW64 folder is quite identical with the content of this folder on Windows x64.

The CHPE DLLs are not pure-x86 DLLs and not even pure-ARM64 DLLs. They are “compiled-hybrid-PE”s. What does it mean? Let’s see:

We can see it contains regular x86 function prologue, immediately followed by x86 function epilogue and then jump somewhere, where it looks like that there’s just garbage. That “garbage” is actually ARM64 code of that function.

NOTE: Again, if you’re feeling adventurous, you can patch FileHeader.Machine field in the PE header to IMAGE_FILE_MACHINE_ARM64 (0xAA64) and open this file in IDA. You will see a whole lot of correctly resolved ARM64 functions. Again, I’d like to thank to Milan Boháček for this tip.

If your question is “how are these images generated?”, I would answer that I don’t know, but my bet would be on some internal version of Microsoft’s C++ compiler toolchain. This idea appears to be supported by various occurences of the CHPE keyword in the ChakraCore codebase.

ARM32 on ARM64

The loop inside of the wowarmhw!BTCpuSimulate is fairly simple compared to wow64cpu.dll loop:

nt!KiEnter32BitMode / SVC 0xFFFF

Let’s peek for a moment into the kernel to see how is this SVC instruction handled:

nt!KiExit32BitMode / UND #0xF8

Let’s look at the NtMapViewOfSection system call in the SysArm32\ntdll.dll :

Let’s peek into the kernel again:

NOTE: It can be noticed that Windows uses UND instruction for several purposes. Common example might also be UND #0xFE which is used as a breakpoint instruction (equivalent of __debugbreak() / int3 )

Источник

Help.. I am being targeted. I’m at the end of my rope.

have been having major issues with viruses, hijacking, hacking. I’m on my 3rd PC in 45 days. No matter how much I secure my gateway, hard resets, change passwords, all the remote in sessions with HP and MS, AV removals.. I can’t get rid of what is plaguing me. HP spent almost 4hrs remoted to my PC I have had for 4 days, and only used on Microsoft and my ISP’s website and was already removing viruses, securing my Gateway and my connection settings. Everything was fine last night, then today McAfee had a critical windows update to install. and since that I have had over 2000 blocked intruders to my network, My sharing keeps getting turned on, I have almost 200 services going on right now in task mgr. I ran adware cleaner and this is the report I got back.

I also ran a few of the Rkills, and they reported nothing. I thought it was funny that I have 2 Userinit running. My AV is cleaning up 1800 files everytime I exit edge or explorer browsers. I am getting spam mails out the wazoo on my Comcast email address, and I am getting spam calls with threats. My iPhone seems to be compromised as well, I charged it on my 2nd New PC that was a Spectre360 that had all the same issue. HP told me to return it. Then now I have this 360 Envy. Apple doesn’t want to admit that its been compromised.

What can I do. I checked my gateway with Comcast and I see that I am connected under one IP, but when I go to my Xfi page it shows that I am not connected to my network. On this PC is as different IP than what my gateway says I am, and it says I am Privately connected, but I shouldn’t have all these intrusion attempts.

I had another router that was 2 numbers off my router model number set up on this PC that HP says they removed. There was a computer called Full_Ford in my network settings. I couldn’t rightclick on the wrong router to remove it.

# Updated on 24/04/2017 by Malwarebytes

# Database : 2017-05-05.1 [Server]

# Operating System : Windows 10 Home (X64)

# Running from : C:\Users\does1\Downloads\adwcleaner_6.046.exe

Источник

MOV AX, BX

Code depilation salon: Articles, Code samples, Processor code documentation, Low-level programming, Working with debuggers

WoW64 internals …re-discovering Heaven’s Gate on ARM

WoW64 — aka Windows (32-bit) on Windows (64-bit) — is a subsystem that enables 32-bit Windows applications to run on 64-bit Windows. Most people today are familiar with WoW64 on Windows x64, where they can run x86 applications. WoW64 has been with us since Windows XP, and x64 wasn’t the only architecture where WoW64 has been available — it was available on IA-64architecture as well, where WoW64 has been responsible for emulating x86. Newly, WoW64 is also available on ARM64, enabling emulation of both x86 and ARM32 appllications.

MSDN offers brief article on WoW64 implementation details. We can find that WoW64 consists of (ignoring IA-64):

Besides Nt* system call translation, the wow64.dll provides the core emulation infrastructure.

If you have previous experience with reversing WoW64 on x64, you can notice that it shares plenty of common code with WoW64 subsystem on ARM64. Especially if you peeked into WoW64 of recent x64 Windows, you may have noticed that it actually contains strings such as SysArm32 and that some functions check against IMAGE_FILE_MACHINE_ARMNT (0x1C4) machine type:

WoW on x64 systems cannot emulate ARM32 though — it just apparently shares common code. But SysX8664 and SysArm64 sound particularly interesting!

Those similarities can help anyone who is fluent in x86/x64, but not that much in ARM. Also, HexRays decompiler produce much better output for x86/x64 than for ARM32/ARM64.

Initially, my purpose with this blogpost was to get you familiar with how WoW64 works for ARM32 programs on ARM64. But because WoW64 itself changed a lot with Windows 10, and because WoW64 shares some similarities between x64 and ARM64, I decided to briefly get you through how WoW64 works in general.

Everything presented in this article is based on Windows 10 — insider preview, build 18247.

Terms

Througout this article I’ll be using some terms I’d like to explain beforehand:

Kernel

This section shows some points of interest in the ntoskrnl.exe regarding to the WoW64 initialization. If you’re interested only in the user-mode part of the WoW64, you can skip this part to the Initialization of the WoW64 process.

Kernel (initialization)

Initalization of WoW64 begins with the initialization of the kernel:

nt!PspSystemDlls appears to be array of pointers to some structure, which holds some NTDLL-related data. The order of these NTDLLs corresponds with this enum (included in the PDB):

Now, let’s look how such structure looks like:

The nt!PspLocateSystemDll function intializes fields of this structure. The layout of this structure isn’t unfortunatelly in the PDB, but you can find a reconstructed version in the appendix.

Now let’s get back to the nt!Phase1Initialization — there’s more:

It looks like it’s some sort of array, again, ordered by the enum _SYSTEM_DLL_TYPE mentioned earlier. Let’s examine NtdllExports :

Nothing unexpected — just tuples of function name and function pointer. Did you notice the difference in the number after the NtdllExports field? On x64 there is 19 meanwhile on ARM64 there is 14. This number represents number of items in NtdllExports — and indeed, there is slightly different set of them:

x64 ARM64
(0) LdrInitializeThunk (0) LdrInitializeThunk
(1) RtlUserThreadStart (1) RtlUserThreadStart
(2) KiUserExceptionDispatcher (2) KiUserExceptionDispatcher
(3) KiUserApcDispatcher (3) KiUserApcDispatcher
(4) KiUserCallbackDispatcher (4) KiUserCallbackDispatcher
(5) KiUserCallbackDispatcherReturn
(5) KiRaiseUserExceptionDispatcher (6) KiRaiseUserExceptionDispatcher
(6) RtlpExecuteUmsThread
(7) RtlpUmsThreadYield
(8) RtlpUmsExecuteYieldThreadEnd
(9) ExpInterlockedPopEntrySListEnd (7) ExpInterlockedPopEntrySListEnd
(10) ExpInterlockedPopEntrySListFault (8) ExpInterlockedPopEntrySListFault
(11) ExpInterlockedPopEntrySListResume (9) ExpInterlockedPopEntrySListResume
(12) LdrSystemDllInitBlock (10) LdrSystemDllInitBlock
(13) RtlpFreezeTimeBias (11) RtlpFreezeTimeBias
(14) KiUserInvertedFunctionTable (12) KiUserInvertedFunctionTable
(15) WerReportExceptionWorker (13) WerReportExceptionWorker
(16) RtlCallEnclaveReturn
(17) RtlEnclaveCallDispatch
(18) RtlEnclaveCallDispatchReturn

On the other hand, all NtdllWow*Exports contain the same set of function names:

Those addresses are actually targets of the pointers in the NtdllWow*Exports structure. Also, those functions combined with PsWow*SharedInformation might give you hint that they’re related to this enum (included in the PDB):

Notice how the order of the SharedNtdll32BaseAddress corellates with the empty field in the previous screenshot (highlighted). The set of WoW64 NTDLL functions is same on both x64 and ARM64.

(The C representation of this data can be found in the appendix.)

Now we can tell what the nt!PspInitializeSystemDlls function does — it gets image base of each NTDLL ( nt!PsQuerySystemDllInfo ), resolves all Ntdll*Exports for them ( nt!RtlFindExportedRoutineByName ). Also, only for all WoW64 NTDLLs ( if ((SYSTEM_DLL_TYPE)SystemDllType > PsNativeSystemDll) ) it assigns the image base to the SharedNtdll32BaseAddress field of the PsWow*SharedInformation array ( nt!PspWow64GetSharedInformation ).

Kernel (create process)

Let’s talk briefly about process creation. As you probably already know, the native ntdll.dll is mapped as a first DLL into each created process. This applies for all architectures — x86, x64 and also for ARM64. The WoW64 processes aren’t exception to this rule — the WoW64 processes share the same initialization code path as native processes.

Initialization of the WoW64 process

The fun part begins!

NOTE: Initialization of the wow64.dll is same on both x64 and ARM64. Eventual differences will be mentioned.

Wow64DetectMachineTypeInternal determines the machine type of the executed process and returns it. Wow64SelectSystem32PathInternal selects the “emulated” System32 directory based on that machine type, e.g. SysWOW64 for x86 processes or SysArm32 for ARM32 processes.

Finally, the RunCpuSimulation function is called. This function just calls BTCpuSimulate from the binary-translator DLL, which contains the actual emulation loop that never returns.

wow64!ProcessInit

If any of these functions wouldn’t be exported, the DLL would be immediately unloaded.

If we’d drop custom wow64log.dll (which would export functions mentioned above) into the %SystemRoot%\System32 directory, it would actually get loaded into every WoW64 process. This way we could drop a custom logging DLL, or even inject every WoW64 process with native DLL!

For more details, you can check my injdrv project which implements injection of native DLLs into WoW64 processes, or check this post by Walied Assar.

wow64!ServiceTables

typedef struct _WOW64_ERROR_CASE <
ULONG Case;
NTSTATUS TransformedStatus;
> WOW64_ERROR_CASE, *PWOW64_ERROR_CASE;
typedef struct _WOW64_SERVICE_TABLE_DESCRIPTOR <
KSERVICE_TABLE_DESCRIPTOR Descriptor;
WOW64_ERROR_CASE ErrorCaseDefault;
PWOW64_ERROR_CASE ErrorCase;
> WOW64_SERVICE_TABLE_DESCRIPTOR, *PWOW64_SERVICE_TABLE_DESCRIPTOR;

(More detailed definition of this structure is in the appendix.)

ServiceTables array is populated as follows:

These two symbols mentioned above are the only symbols that wow64.dll requires wow64win.dll to export.

Let’s have a look at sdwhnt32 service table:

The job of these wh* functions is to correctly convert any arguments and return values from the 32-bit version to the native, 64-bit version. Keep in mind that that it not only includes conversion of integers and pointers, but also content of the structures. Interesting note might be that each of the wh* functions has only one argument, which is pointer to an array of 32-bit values. This array contains the parameters passed to the 32-bit system call.

The ntdll.dll and win32u.dll are obvious and they represent the same thing as their native counterparts. The service tables used by kernel32.dll and user32.dll contain functions for transformation of particular csrss.exe calls into their 64-bit version.

NOTE: I’ll be talking about one of these functions — namely Wow64CallFunctionTurboThunkControl — later in the Disabling Turbo thunks section.

wow64!Wow64SystemServiceEx

This function is similar to the kernel’s nt!KiSystemCall64 — it does the dispatching of the system call. This function is exported by the wow64.dll and imported by the emulation DLLs. Wow64SystemServiceEx accepts 2 arguments:

The system call number isn’t just an index, but also contains index of a system table which needs to be selected (this is also true for ntoskrnl.exe ):

typedef struct _WOW64_SYSTEM_SERVICE
<
USHORT SystemCallNumber : 12 ;
USHORT ServiceTableIndex : 4 ;
> WOW64_SYSTEM_SERVICE, *PWOW64_SYSTEM_SERVICE;

wow64!ProcessInit (cont.)

We can see that there is no wow64cpu.dll on ARM64. Instead, there is xtajit.dll used for x86 emulation and wowarmhw.dll used for ARM32 emulation.

wow64.dll then loads one of the selected DLL and tries to find there following exported functions:

BTCpuProcessInit (!) BTCpuProcessTerm
BTCpuThreadInit BTCpuThreadTerm
BTCpuSimulate (!) BTCpuResetFloatingPoint
BTCpuResetToConsistentState BTCpuNotifyDllLoad
BTCpuNotifyDllUnload BTCpuPrepareForDebuggerAttach
BTCpuNotifyBeforeFork BTCpuNotifyAfterFork
BTCpuNotifyAffinityChange BTCpuSuspendLocalThread
BTCpuIsProcessorFeaturePresent BTCpuGetBopCode (!)
BTCpuGetContext BTCpuSetContext
BTCpuTurboThunkControl BTCpuNotifyMemoryAlloc
BTCpuNotifyMemoryFree BTCpuNotifyMemoryProtect
BTCpuFlushInstructionCache2 BTCpuNotifyMapViewOfSection
BTCpuNotifyUnmapViewOfSection BTCpuUpdateProcessorInformation
BTCpuNotifyReadFile BTCpuCfgDispatchControl
BTCpuUseChpeFile BTCpuOptimizeChpeImportThunks
BTCpuNotifyProcessExecuteFlagsChange BTCpuProcessDebugEvent
BTCpuFlushInstructionCacheHeavy

Interestingly, not all functions need to be found — only those marked with the “(!)”, the rest is optional. As a next step, the resolved BTCpuProcessInit function is called, which performs binary-translator-specific process initialization. We’ll cover that in later section.

wow64!ThreadInit

ThreadInit does some little thread-specific initialization, such as:

x86 on x64

Entering 32-bit mode

RunSimulatedCode runs in a loop and performs transitions into 32-bit mode either via:

NOTE: Explanation of segmentation and “why does it work just by changing a segment register” is beyond scope of this article. If you’d like to know more about “long mode” and segmentation, you can start here.

You can see the simplest form of switching into the 32-bit mode. Also, at the beginning you can see that TurboThunkDispatch address is moved into the r15 register. This register stays untouched during the whole RunSimulatedCode function. Turbo thunks will be explained in more detail later.

Leaving 32-bit mode

The switch back to the 64-bit mode is very similar — it also uses far jumps. The usual situation when code wants to switch back to the 64-bit mode is upon system call:

The Wow64SystemServiceCall is just a simple jump to the Wow64Transition :

If you remember, the Wow64Transition value is resolved by the wow64cpu!BTCpuGetBopCode function:

It selects either KiFastSystemCall or KiFastSystemCall2 based on the CpupSystemCallFast value.

The KiFastSystemCall2 looks like this (used when CpupSystemCallFast == 0 ):

Clearly, the KiFastSystemCall is faster, so why it’s not used used every time?

It turns out, CpupSystemCallFast is set to 1 in the wow64cpu!BTCpuProcessInit function if the process is not executed with the ProhibitDynamicCode mitigation policy and if NtProtectVirtualMemory(&KiFastSystemCall, PAGE_READ_EXECUTE) succeeds.

This is because KiFastSystemCall is in a non-executable read-only section ( W64SVC ) while KiFastSystemCall2 is in read-executable section ( WOW64SVC ).

But the actual reason why is KiFastSystemCall in non-executable section by default and needs to be set as executable manually is, honestly, unknown to me. My guess would be that it has something to do with relocations, because the address in the jmp 33h:$+9 instruction must be somehow resolved by the loader. But maybe I’m wrong. Let me know if you know the answer!

Turbo thunks

I hope you didn’t forget about the TurboThunkDispatch address hanging in the r15 register. This value is used as a jump-table:

There are 32 items in the jump-table.

CpupReturnFromSimulatedCode is the first code that is always executed in the 64-bit mode when 32-bit to 64-bit transition occurs. Let’s recapitulate the code:

You might be confused now, because few sections above we’ve defined the service number like this:

typedef struct _WOW64_SYSTEM_SERVICE
<
USHORT SystemCallNumber : 12 ;
USHORT ServiceTableIndex : 4 ;
> WOW64_SYSTEM_SERVICE, *PWOW64_SYSTEM_SERVICE;

…therefore, after right-shifting this value by 16 bits we should get always 0, right?

It turns out, on x64, the WOW64_SYSTEM_SERVICE might be defined like this:

typedef struct _WOW64_SYSTEM_SERVICE
<
ULONG SystemCallNumber : 12 ;
ULONG ServiceTableIndex : 4 ;
ULONG TurboThunkNumber : 5 ; // Can hold values 0 — 31
ULONG AlwaysZero : 11 ;
> WOW64_SYSTEM_SERVICE, *PWOW64_SYSTEM_SERVICE;

Let’s examine few WoW64 system calls:

Let’s finally explain “turbo thunks” in proper way.

Turbo thunks are an optimalization of WoW64 subsystem — specifically on Windows x64 — that enables for particular system calls to never leave the wow64cpu.dll — the conversion of parameters and return value, and the syscall instruction itself is fully performed there. The set of functions that use these turbo thunks reveals, that they are usually very simple in terms of parameter conversion — they receive numerical values or handles.

The notation of Thunk* labels is as follows:

Let’s take the NtWaitForSingleObject and its turbo thunk Thunk3ArgSpNSpNSpReloadState as an example:

When we cross-check this information with its function prototype, it makes sense:

Disabling Turbo thunks

On Windows x64, the Turbo thunk optimization can be actually disabled!

The function prototype might look like this:

typedef enum _WOW64_FUNCTION <
Wow64Function64Nop,
Wow64FunctionQueryProcessDebugInfo,
Wow64FunctionTurboThunkControl,
Wow64FunctionCfgDispatchControl,
Wow64FunctionOptimizeChpeImportThunks,
> WOW64_FUNCTION;
NTSYSCALLAPI
NTSTATUS
NTAPI
NtWow64CallFunction64 (
_In_ WOW64_FUNCTION Wow64Function,
_In_ ULONG Flags,
_In_ ULONG InputBufferLength,
_In_reads_bytes_opt_ (InputBufferLength) PVOID InputBuffer,
_In_ ULONG OutputBufferLength,
_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
_Out_opt_ PULONG ReturnLength
);

NOTE: This function prototype has been reconstructed with the help of the wow64!Wow64CallFunction64Nop function code, which just logs the parameters.

wow64cpu!BTCpuTurboThunkControl then checks the input parameter.

This means 2 things:

With all this in mind, we can achieve disabling Turbo thunks by this call:

What it might be good for? I can think of 3 possible use-cases:

x86 on ARM64

The x86 emulation on Windows ARM64 consists also of other “XTA” components:

The whole “XTA” and its internals are not in the focus of this article, but they would definitely deserve a separate article.

With a simple Python script, we can mass-rename all functions referenced in this array:

begin = 0x 01800A8C20
end = 0x 01800B7B4F
struct_size = 24
ea = begin
while ea end:
ea += struct_size
name = idc.GetString(idc.Qword(ea))
idc.MakeName(idc.Qword(ea + 8 ), name)

I’d like to thank Milan Boháček for providing me this script.

Windows\SyCHPE32 & Windows\SysWOW64

One thing you can observe on ARM64 is that it contains two folders used for x86 emulation. The difference between them is that SyCHPE32 contains small subset of DLLs that are frequently used by applications, while contents of the SysWOW64 folder is quite identical with the content of this folder on Windows x64.

The CHPE DLLs are not pure-x86 DLLs and not even pure-ARM64 DLLs. They are “compiled-hybrid-PE”s. What does it mean? Let’s see:

We can see it contains regular x86 function prologue, immediately followed by x86 function epilogue and then jump somewhere, where it looks like that there’s just garbage.

My guess is that the reason for this prologue is probably compatibility with applications that check whether some particular functions are hooked or not — by checking if the first bytes of the function contain real prologue.

NOTE: Again, if you’re feeling adventurous, you can patch FileHeader.Machine field in the PE header to IMAGE_FILE_MACHINE_ARM64 (0xAA64) and open this file in IDA. You will see a whole lot of correctly resolved ARM64 functions. Again, I’d like to thank to Milan Boháček for this tip.

If your question is “how are these images generated?”, I would answer that I don’t know, but my bet would be on some internal version of Microsoft’s C++ compiler toolchain. This idea appears to be supported by various occurences of the CHPE keyword in the ChakraCore codebase.

ARM32 on ARM64

The loop inside of the wowarmhw!BTCpuSimulate is fairly simple compared to wow64cpu.dll loop:

nt!KiEnter32BitMode / SVC 0xFFFF

I won’t be explaining here how system call dispatching works in the ntoskrnl.exe — Bruce Dang already did an excellent job doing it. This section is a follow up on his article, though.

SVC instruction is sort-of equivalent of SYSCALL instruction on ARM64 — it basically enters the kernel mode. But there is a small difference between SYSCALL and SVC : while on Windows x64 the system call number is moved into the eax register, on ARM64 the system call number can be encoded directly into the SVC instruction.

Let’s peek for a moment into the kernel to see how is this SVC instruction handled:

Simply said, in the X15 register, there is an address that will be executed once we leave the kernel-mode and enter the user-mode — which happens with the ERET instruction at the end.

nt!KiExit32BitMode / UND #0xF8

Alright, we’re in the 32-bit ARM mode now, how exactly do we leave? Windows solves this transition via UND instruction — which is similar to the UD2 instruction on the Intel CPUs. If you’re not familiar with it, you just need to know that it is instruction that basically guarantees that it’ll throw “invalid instruction” exception which can OS kernel handle. It is defined-“undefined instruction”. Again there is the same difference between the UND and UD2 instruction in that the ARM can have any 1-byte immediate value encoded directly in the instruction.

Let’s look at the NtMapViewOfSection system call in the SysArm32\ntdll.dll :

Let’s peek into the kernel again:

Keep in mind that meanwhile the 32-bit code is running, it cannot modify the value of the previously stored X30 register — it is not visible in 32-bit mode. It stays there the whole time. Upon UND #0xF8 execution, following happens:

NOTE: It can be noticed that Windows uses UND instruction for several purposes. Common example might also be UND #0xFE which is used as a breakpoint instruction (equivalent of __debugbreak() / int3 )

Источник

Читайте также:  Что такое малоподвижный образ жизни
Информ портал о технике и не только