So my idea is to "lift" 64-bits Windows executable to LLVM bitcode (or whatever is higher than assembly) and then compile it back to 32-bit executable.
I found that RetDec and McSema can lift PE binary to LLVM IR (and optionally C), but McSema requires IDA pro so I haven't tried it yet.
I have installed MSVC v143
and Windows SDK version 10.0.19041.0
:
Clang version:
clang version 13.0.1 (https://github.com/llvm/llvm-project 75e33f71c2dae584b13a7d1186ae0a038ba98838)
Target: x86_64-pc-windows-msvc
Thread model: posix
So I compile this Hello World code in C using Clang:
#include <stdio.h>
int main()
{
printf("Hello, world!\n");
}
then clang hello.c -o hello.exe
Check hello.exe
file type with WSL:
$ file hello.exe
hello.exe: PE32+ executable (console) x86-64, for MS Windows
You can download it here.
Then I use RetDec to lift it to LLVM IR:
python retdec-decompiler.py --no-memory-limit hello.exe
Output: here
After that we get:
Compile bitcode back to executable:
clang hello.exe.bc -m32 -v -Wl,/SUBSYSTEM:CONSOLE -Wl,/errorlimit:0 -fuse-ld=lld -o hello.x86.exe
Output: here
I guess functions like _WriteConsoleW
are Win32 APIs, but ___decompiler_undefined_function_0
might be generated from the decompiler by some way.
Also, the decompiled code has no main
function, but it had entry_point
function. From hello.exe.ll
:
hello.exe.c
also has entry_point
instead of main
:
And also, hello.exe.c
doesn't have ___decompiler_undefined_function_0
I also tried running the bitcode with lli
:
lli --entry-function=entry_point hello.exe.bc
Output: here
Here is the link to the files.
How to make this compile? Thanks!