
Preface
It has been a long time since I have last written about Windows Phone on my blog. I have recently continued to explore the platform further, thanks to developments that have happened in the Windows Phone enthusiast community that have enabled more exploratory work that nobody I know has yet done.
For this year’s exploration, I have purchased a disposable Lumia 925 to tinker with, to preserve my museum collection in pristine condition while having something in my backpack wherever I go. The phone model itself is not important for what I am working on since most of the Lumias by now have jailbreaks available online. The jailbreaks have made it possible to unlock the bootloader, enable root access, boot the phone to mass storage mode, enable interop unlock, and sideload applications (using official deployment tooling).
With these jailbreaks in place, the platform is fully open for further exploration, and this is something I have worked on this week.
A big shout out to Fadil Fasz and his work on CMD Injector, which is a tool that enables access to a phone’s CMD.exe over telnet. This is a key enabler for my exploration that is documented here. Fadil has also developed tools to enable sideloading that can be found on his GitHub pages.
This episode’s main goal is to write a Hello World program in C that will run inside a Windows Phone 8 device like the native executables available under C:\WINDOWS\SYSTEM32 on the platform. Meaning the Hello World can be run over the telnet shell provided by the CMD Injector.
I will not discuss how to install the SDKs or how to jailbreak a phone or how to install CMD Injector in this post, as these have been covered by other hobbyists many times over. I will assume if the reader wants to follow they will have a Windows Phone device that has been fully unlocked (bootloader, interop, sideloading, root access) and that the device has CMD Injector installed and injected into the system permanently for telnet access.
Prerequisites
- Windows Phone 8.1 SDK
- Windows Device Kit 8.1
- Microsoft Visual Studio 2013 or 2015
- Fully unlocked Windows Phone with CMD Injector injected for telnet access
- Telnet client
- Windows Phone Internals software (To boot the phone into Mass Storage Mode)
Note about Visual Studio 2013
I use two toolchains, Visual Studio 2013 and 2015, but for this particular exploration journey I have chosen to use Visual Studio 2013 Professional as I have a genuine licence for it and because we are using C/C++ Compiler, it may have less issues to solve because it did not come with ucrt and instead still used msvcrt.
UCRT (Universal C Runtime) was implemented from Windows 10 onwards so it is not included out of the box for Windows 8 series, so I will be trying to avoid having to patch the UCRT into the platform.
VS2013 is no longer supported by Microsoft and when trying to sign in using my account I got a connection failure error. To fix this, I had to enable strong cryptography for the .Net Framework version used by VS2013.
This can be done as follows:
- Press Windows Key + R, type
regedit, and Hit Enter. - Navigate to:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319 - Right-click, select New > DWORD (32-bit) Value.
- Name it
SchUseStrongCrypto. - Set its value to
1. - Repeat the steps for
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NetFramework\v4.0.30319.
This forces Visual Studio 2013 to use TLS1.2 and then signing in is possible with your Microsoft account.
The Journey
Beginning
Initially I tried to convince Visual Studio to produce binaries for ARM by changing the build target and making sure that Windows Phone libraries were included properly, but soon I found that the resulting binaries did not run in the target platform. The binaries would only output a newline character and exit.
Looking for the root cause, I checked the return value by running ECHO %ERRORLEVEL% and this revealed that
the exit code was -1073741515 or 0xC0000135 which means DLL NOT FOUND. Whatever the binary was getting
linked against was not present on the Windows Phone device itself.
A Simplified Hello World for a New Era
After this I decided to keep things simpler so for further exploration I decided to use VS2013 ARM Cross Tools Command Prompt. This would make sure that I have the proper environment variables set for cross-compiling for an ARM target. Shortcut to this Command Prompt can be found under Start Menu -> Visual Studio Tools -> VS2013 ARM Cross Tools Command Prompt. And to simplify even further, I decided to try to avoid linking against CRT, going in with bare minimum dependencies.
So at this stage my Hello World hello.c looked as follows:
#include <windows.h>
void __cdecl main(void) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
const char *msg = "Hello, Windows Phone!\r\n";
DWORD written;
WriteFile(hOut, msg, lstrlenA(msg), &written, NULL);
ExitProcess(0);
}
This looks much more complex than a regular C Hello World usually does, but using Win32 WriteFile() avoids issues with CRT initialisation and console subsystem dependencies.
I then tried to compile it, but was getting warnings about undefined functions, indicating that things were not
being included properly. After some debugging, I found out that the issue was /D WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP
in my CL.exe command. It was blocking access to APIs needed for this experiment. The solution was to use
WINAPI_FAMILY_DESKTOP_APP instead. I hardcoded this definition into my source code:
#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
#include <windows.h>
void __cdecl main(void) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
const char *msg = "Hello, Windows Phone!\r\n";
DWORD written;
WriteFile(hOut, msg, lstrlenA(msg), &written, NULL);
ExitProcess(0);
}
This got me somewhat further in the experiment as I was now running into another error:
Fatal error C1186 compiling desktop applications for the ARM platform is unsupported.
Someone really did not want us to compile applications like this, but luckily I found there was a bypass for
this error. Adding /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 to the CL.exe command solved this. It could
also be added as a #define in the source code, but I opted to keep it in the CL.exe line.
This define is specifically the bypass Microsoft built into the headers for exactly this scenario, compiling desktop-style Win32 code for ARM. It was intended for the Windows RT / Surface RT ecosystem but works here too. It tells the header guard that you acknowledge you are doing something unsupported and wish to proceed anyway.
So now the full compilation command was:
cl /nologo /W3 /O1 /c /MT ^
/D_WIN32_WINNT=0x0603 ^
/D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 ^
/I"C:\Program Files (x86)\Windows Kits\8.1\Include\um" ^
/I"C:\Program Files (x86)\Windows Kits\8.1\Include\shared" ^
/I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include" ^
hello.c ^
/Fohello.obj
And the full linker command was:
link /NOLOGO /MACHINE:ARM /SUBSYSTEM:CONSOLE /ENTRY:main /NODEFAULTLIB /LIBPATH:"C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\arm" /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib\arm" hello.obj kernel32.lib /OUT:hello.exe
This time the program compiled and linked without errors! I then proceeded to move the executable file into the phone using Mass Storage Mode and then rebooting it back to normal mode for telnet connection.
Running the executable still yielded the same issues as before. It would output only a newline character and
the error level was indicating a missing DLL. Checking with dumpbin /dependents hello.exe confirmed that we only
depend on KERNEL32.DLL. But turns out it does not exist on the phone’s C:\WINDOWS\SYSTEM32 folder.
The logical next step was to record and trace what is available on the platform vs. what is available in the various SDKs and Visual Studio libraries, and to try to find substitutes to use to get the program working.
A Deep Dive into SDKs and DLLs
Looking at what DLLs were available on the phone itself was easy through Mass Storage Mode. Here’s an extract of DLLs available in the C:\WINDOWS\SYSTEM32 on the phone (Windows Phone 8.1 GDR1):
Next up I gathered a list of all the ARM libraries that were available on my development PC.
- Visual Studio 2013 Professional default ARM libraries
- Windows Device Kit 8.1 ARM libraries
- Windows Phone 8.1 SDK ARM libraries
From the list of DLLs on the device itself, it was clear that the device used MinWin architecture. There was no kernel32.dll, but there were k32.dll and KERNEL32LEGACY.DLL. There was also APISETSCHEMA.DLL that implied MinWin architecture and it provides virtual DLLs that redirect imports to their real implementations.
The device had KERNELBASE.DLL present, but there was no matching library file available on the development PC, so that was not an answer either. But remembering that the device followed the MinWin architecture, it could be seen that MINCOREDLOAD.DLL is present on the device, and we had mincore.lib on the development PC.
To link against mincore.lib, the linking command needed to be changed as follows:
link /NOLOGO /MACHINE:ARM /SUBSYSTEM:CONSOLE /ENTRY:main /NODEFAULTLIB /LIBPATH:"C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\arm" hello.obj mincore.lib /OUT:hello.exe
Trying this with the Hello World program code from before yielded hello.obj LNK2019: unresolved external symbol __imp_lstrlenA referenced in function main and it would not link.
This implied that mincore does not provide the function, to continue testing it made sense to hardcode the value to see if it could help get further in the experiment:
#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
#include <windows.h>
void __cdecl main(void) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
const char *msg = "Hello, Windows Phone!\r\n";
DWORD written;
WriteFile(hOut, msg, 23, &written, NULL);
ExitProcess(0);
}
I compiled it again with the following command:
cl /nologo /W3 /O1 /c /MT /D_WIN32_WINNT=0x0603 /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 /I"C:\Program Files (x86)\Windows Kits\8.1\Include\um" /I"C:\Program Files (x86)\Windows Kits\8.1\Include\shared" /I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include" hello.c /Fohello.obj
And linked it as follows:
link /NOLOGO /MACHINE:ARM /SUBSYSTEM:CONSOLE /ENTRY:main /NODEFAULTLIB /LIBPATH:"C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\arm" hello.obj mincore.lib /OUT:hello.exe
Doing all this we finally got a clean compilation and linking result! Moving this into the phone finally yielded the expected output using this minimum imports Hello World C program over telnet connection.

Summary Thus Far
Before venturing further in this adventure, let’s summarise what we have learned so far:
- Windows Phone 8.1 has no
kernel32.dlland it uses MinWin architecture - The correct import lib for kernel functions is
mincore.libfrom Windows Device Kit 8.1 /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1is needed to bypass the ARM desktop app block in the headers/D WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APPis needed to unlock the Win32 API surface- Mincore, as its name implies, has a limited set of functions available
- To avoid CRT startup dependencies
/ENTRY:main /NODEFAULTLIBis needed
This was probably one of the very few if not first documented case of someone successfully compiling and running a native Win32 ARM binary on Windows Phone 8.1 via telnet.
But What About Standard C Library?
In my next blog post I will discuss moving forward with this experiment and getting a standard K&R style Hello World C program to compile, link, and run on the platform. Stay tuned!