понедельник, 15 июля 2013 г.

Windows RT and UEFI thoughts

As there is no jailbreak for 8.1 - I've started to look for other ways of running unsigned code on Windows RT tablets.
My main idea is the following: UEFI provides Windows several runtime services, like "SetVariable". Those services are located in RAM as their code needs to be relocated at runtime when virtual address mapping changes, and RAM can be easily patched from driver. And we can already run our own unsigned drivers under Windows RT 8.0.

So as a first investigation, I've made a Windows "complete memory" crashdump and started to look for the runtime services signature:
#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552 
It is "RUNTSERV" in ASCII. This should give a pointer to UEFI runtime services to call them from my future driver. And I was really disappointed not to find such a sting at all. I know that the string is present in RAM, but not in a crashdump I've made. There may be two reasons - Windows crashdumps only memory that it "owns", or that memory region is not mapped at all.

So the second attempt was to make a driver that maps physical memory with MmMapIoSpace and provides an interface to read/write it from user mode. As Microsoft was kind enough to give us Windows 8.1 WDK - process was easy. Those who are interested may see the driver and test program sources here. And Windows RT precompiled binaries here. Sources are based on Microsoft's "toaster" driver, so don't wonder the device name.
Program dumps the given amount of RAM starting from a given address to disk. As we on Terga have 2 gb physical memory starting at 0x80000000 - the whole memory range could be dumped with "dumper.exe 80000000 80000000" (addr and length in hex). There is a small internal RAM on CPU at 0x40000000, but there is nothing interesting there.

What interesting can you see from a dump? there are all UEFI variables, including the ones accessible only in boot mode, obviously PK, KEK and other certificates: 

You can see the BootXXXX bootmenu entries, "SecureBoot" and "PK" keys on the screenshot. GUID is located before, the value is after a unicode variable name.
And for some reason the whole decompressed contents of firmware volumes (FV0: and FV1:) is present in RAM. So you can "extract" EFI modules to analyze them later, look after 0xFF000000 addresses for strings like "/home/cca/TF600T/Tp1201/TF600T-ASUS-1101/Build/TF600TTZ/RELEASE_ARMLINUXGCC/ARM/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe/DEBUG/ConPlatformDxe.dll".

To test the "main" idea of patching UEFI data in RAM - I've made a small tool that patches given addresses RAM, modified "SecureBoot" and "SetupMode" variables to zero - and got nothing extraordinary. I was still unable to erase PK or KEK. Then I've modified the same tool to scan for PK or KEK and replace all their occurrences with my own certificate - even after that I was unable to add a new key to DB signed with that cert. Now I think that all UEFI variables are reread from NVRam when needed and not cached in RAM for too long.

The next step would be to reverse engineer and patch the SetVariable code, so that it would never check for a valid signature. But I'll do that later, as I've already found an interesting thing on Asus and playing with it now.

Commenting is closed for this topic, more info may be published on XDA.

воскресенье, 10 февраля 2013 г.

MFC in desktop Windows RT apps

As we can build desktop Windows RT applications now - it is a good idea to use MFC for GUI. But suddenly I've found that there is no MFC 11.0 for ARM in Visual Studio 2012, even with the ARM WDK installed! The program compiles fine as the headers are present, but you'll get linker errors stating that uafxcw.lib, uafxcwd.lib and similar files are not found. Only ATL is present for ARM.
The first thought was to use dll2lib to generate import library from a mfc110.dll, but that DLL exports functions only by ordinals. So I've decided to look for mfc*.def in the "Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\src" dir and was surprised not to find it there. And there was also no makefile, unlike older MFC versions.
I've decided to compile a static MFC library. In this case linker would ignore all extra/unnecessary files I could add into the project by mistake. Created a new Win32 project, selected "Use MFC as a static library", added the whole "src\mfc" directory except for dll*.cpp and localized resource files - and the project compiled successfully! But after adding the generated MFC.lib to a project - got errors complaining on the AfxRegisterMFCCtrlClasses. 
Googling on that function gave a link to a Microsoft blog describing its purpose. But there was no such function in whole MFC sources! After looking into the x86 uafxcwd.lib I've got that it is implemented in the afxctrlcontainer2.obj, so the file is probably named afxctrlcontainer2.cpp. Obviously I have not found that file. Several other functions were not present too:
CMFCControlContainer::UTF8ToString_AfxDispatchCall (it is implemented in x86/x64 ASM, and I was too lazy to rewrite it in THUMB), seems that they deal with MFC and OLE controls embedded into dialog resources. It would not be difficult to reimplement them by looking in disasm or implementation in older MFC versions, but I'm too lazy to do that myself.
I don't need OLE or MFC controls in my dialogs - so I've defined _AFX_NO_MFC_CONTROLS_IN_DIALOGS in stdafx.h of my project, and implement those functions as stubs.

Here is the code of all stubs:

    void __cdecl AfxRegisterMFCCtrlClasses(void)
    {
    }
    extern "C" int __afxNoMFCControlContainerInDialogs=1;
    extern "C" DWORD_PTR AFXAPI
    _AfxDispatchCall(AFX_PMSG pfn, void* pArgs, UINT nSizeArgs)
    {
       __debugbreak();
       return 0;
    }
    int __cdecl CMFCControlContainer::UTF8ToString(char const *,class 
        ATL::CStringT<wchar_t,class StrTraitMFC<wchar_t,
        class ATL::ChTraitsCRT<wchar_t> > > &,int)
    {
       __debugbreak();
       return 0;
    }

After adding that code to MFC lib sources - my project compiled and works correctly on Windows RT.
Debug MFC library is 157 Mb in size, and release version is 1.2 Gb. This is much more than the same x86 LIBs. Probably this is due to embedded debugger and incremental linker information. 

The compiled LIB files are published in this post on XDA. Do not forget to add 
    #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS 
to your stdafx.h and avoid using custom MFC controls in dialog designer.

Added on 28 april:
There is an implementation of UTF8ToString and AfxRegisterMFCCtrlClasses functions here:
  https://github.com/mpc-hc/mpc-hc/blob/master/src/thirdparty/mfc/afxctrlcontainer.cpp
And here I've found the THUMB implementation of _AfxDispatchCall function:
  http://computer-programming-forum.com/86-vc-windows-ce/dc1b0159dbb16d4e.htm
It is probably taken from Windows CE MFC library.
I've recompiled MFC libs with that code, uploaded sources and libs here:
https://drive.google.com/folderview?id=0B25hIeyRmniUZzk0c3hNZmVDSms&usp=sharing

Added on 7 may:
danesh110 on XDA found that beta version of Visual Studio 2012 (it was called Visual Studio 11) contained the MFC libraries and DLLs for Windows RT. More info here: http://forum.xda-developers.com/showthread.php?p=41133829#post41133829
VS 11 beta can be downloaded from the links in this blog: http://www.kunal-chowdhury.com/2012/03/download-visualstudio11-beta.html
Beta has more sources, for example the managed mfc and ARM assembler version of _AfxDispatchCall function, but they are still incomplete.

No ARM code on Windows on ARM

He-he. No ARM code on Windows on ARM. Period.
Though MS called their new OS "Windows on ARM" (sometimes Windows on Snapdragon, Windows on Tegra and now Windows RT) - you can't see ARM code in it. Everything is THUMB2.
I don't know the reason of such a limitation - but that caused me several days of debugging while I was working on a DosBox dynamic core WinRT port last year. The dynamic code generated by DosBox is ARM, even the original THUMB generator was using small ARM thunks. Original DosBox works fine on ARM Linux, but on Windows RT it behaves differently. The generated code executes once, twice, but on the 100500 time - it crashes.
The reason was simple. If you read the ARM developer's manual, you'll see that OS should determine the previous mode (ARM or THUMB) on kernel mode entrance (via SWI, interrupt, ...). Seems that MS decided to simplify the handler's code - and assume that the user's code is always THUMB. And they always set the T bit on return to the user land.
So if you are running generated ARM code in your program - you may be forced to the THUMB mode any moment by an interrupt or a task switch.

Another ARM-code error I've came across.
In my project I need to emulate dialog procedures of the x86 program. Windows calls my own DlgProc, where I pass its parameters to the original x86 function through the emulation layer. But where to store the x86 dialog function address to call it from my code? You can't use SetProp() as the window is not created yet. CreateDialogXxxParam can't be used too - parameter is sent in WM_INITDIALOG message, while it is not the first message you receive (WM_SETFONT and other messages precede it).
So I've decided to generate a small thunk that calls my DlgProc prepending the x86 address before a first parameter. Generated THUMB2 code is simple, tested it in a separate project - idea works fine. But in main project it works once, twice, but on 10th time - the program crashes. And in the exception you see that the lowest bit of LR register points to your code, but is zero. This means that the previous code was executed as ARM, not THUMB2 as I've expected! It took me 2 days to debug. The reason was simple - I've forgot to set the bit 0 of the generated thunk address to one while passing it as DlgProc to the Windows API to indicate that it points to THUMB code. For normal functions Visual Studio does this automatically - but for generated code you should do that yourself.
Windows kernel was "kind enough" to fix that for me 9 times, but on 10th - something went different and my thunk was executed as ARM code. Setting the lowest bit of an address to one - fixed the problem immediately.

During debugging I've found a good article on the internals of Windows kernel to user mode callbacks here. Though it is about a desktop - it is worth reading anyway.

воскресенье, 27 января 2013 г.

I'm currently working on a project that would allow running the existing Windows x86 apps on the Windows RT devices. Unlike the previous project where I've statically recompiled Heroes of Might and Magic 1/2 for Windows Phone - this one would have a dynamic recompilation engine, so that it would theoretically allow to run almost any program without manual modifications.
There is a working prototype that can already run the Heroes of Might and Magic 3 with a rather good speed (yes, I'm a fan of the HOMM series). But HOMM here is used only for testing purposes.
Here is the video showing the gameplay on my Asus VivoTab. And here is the discussion on XDA forum.

This project would be partially opensource. I'm planning to provide sources of the modified DosBox and Bochs emulation engines, headers and samples for making WinAPI DLL wrappers, but the rest of the project core would be closed. The core currently consists of the PE loader, CPU and API emulation/compatibility layers. Later I'll add an automatic program launcher, so you would not need to manually specify the emulated program.

When the sufficient part of Windows API would be implemented and the set of popular programs like WinRAR and Total Commander would be running - I'll try to make my own CPU emulation library based on the previous experience. As I don't need to emulate pagetables, 16-bit code, AF CPU flag, and CPU instructions that are never used under Windows (like DAA for example) - this library would be rather simple and fast. Self-modifying code that is used in some of the protectors would be supported too via the MEM_WRITE_WATCH flag.

There is a possibility that there would be a commercial "professional" version of this project in some distant future, similar to WinAmp. But I can tell that this would not happen while I'm using the DosBox and Bochs code as main emulation engines, and while there is no legal way of running custom desktop applications on Windows RT.

In case you wish to offer me some beer for brain stimulation - here are my electronic purses.
Webmoney:wmz: Z588578204369, 
wmr: R339434335513, 
wme: E230290760889
Paypal:

mamaich, 27.01.2013

четверг, 24 января 2013 г.

This is an english part of my blog.
Russian variant is here: http://mamaich-rus.blogspot.ru/

This blog would contain mainly links and info on my computer-based hobbies - reverse engineering, windows server adminstration, etc. The russian part would be mainly about real life.
Lets hope that I would not violate any copyrights in these blogs. Anyway feel free to contact me by mail for any reason.

mamaich, 24.01.2012