Analysing Win32 Content Prep Tool
In my quest to build an open-source, cross platform, tool that packages Win32 apps from Winget for Intune WingetIntune on GitHub, I’ve been looking at the Win32 Content Prep Tool. This tool is used by administrators to prepare Win32 apps for deployment in Intune. It’s a closed source application requiring windows to run. In this post I’ll be looking at the tool and how it works.

Detection.xml file from .intunewin
What is the Win32 Content Prep Tool
Use the Microsoft Win32 Content Prep Tool to pre-process Windows Classic apps. The packaging tool converts application installation files into the .intunewin format. The packaging tool also detects the parameters required by Intune to determine the application installation state. After you use this tool on your apps, you will be able to upload and assign the apps in the Microsoft Intune console. source.
The readme also contains some additional hints on how the tool works:
.NET Framework 4.7.2is required.For MSI setup file, this tool will retrieve required information for Intune.
And may the most important information:
Note: The generated .intunewin file contains all compressed and encrypted source setup files and the encryption information to decrypt it. Please keep it in the safe place as your source setup files.
You must also agree with the licenses before you can use the tool.
How does it work
It you run this tool it will ask you for a directory containing the setup files, mind you files so multiple files. It will also ask for a setup file inside that directory. And it asks for an output directory. After that it will start processing the files and create an .intunewin file in the output directory.
This .intunewin file is a compressed and encrypted file according to the readme. I’ve just given it a try by renaming the file to .zip and extracted it. This gives me the following files:
IntuneWinPackage
- Metadata
- Detection.xml
- Contents
- IntunePackage.intunewin
I noted the following observations:
- The top
.intunewinfile is a zip file, which is not encrypted as specified in the readme. - There is a
Detection.xmlfile in theMetadatafolder. - There is a
IntunePackage.intunewinfile in theContentsfolder, which is a bit smaller then the combination of all the files in the source directory, but it grows if I add more files. This file must contain the compressed source files. - The
IntunePackage.intunewinfile from theContentsfolder is actually encrypted, I tried the renaming trick and failed miserably.
Detection.xml
Here is a sample of the Detection.xml file:
<ApplicationInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ToolVersion="1.8.4.0">
<Name>install-amd64.exe</Name>
<UnencryptedContentSize>5957009</UnencryptedContentSize>
<FileName>IntunePackage.intunewin</FileName>
<SetupFile>install-amd64.exe</SetupFile>
<EncryptionInfo>
<EncryptionKey>D+ybCjTETXC8MoVN50MHzD46e44S7utjv+joT3Z7beM=</EncryptionKey>
<MacKey>UXblbITBQud2iQguE4Xrb0odDH3RVSIwEiPokQaBydE=</MacKey>
<InitializationVector>KIkWu3WQuFiJdYGqerI1+Q==</InitializationVector>
<Mac>5Gu4ndv6RhtRBPaeNzHjMZJcSDJc9yy7l9zqZTPvevE=</Mac>
<ProfileIdentifier>ProfileVersion1</ProfileIdentifier>
<FileDigest>0mRcAQNg2d0h0yvjTnCUQ/ZcuNeQXaYZ1BUUBNTILaU=</FileDigest>
<FileDigestAlgorithm>SHA256</FileDigestAlgorithm>
</EncryptionInfo>
</ApplicationInfo>
I already figured out that this detection file contained all the information needed to publish a Win32 app to Intune, in a previous post. If I take the same installer and run it through the tool again, I get a slightly different detection file. Some properties change like the EncryptionKey, MacKey, InitializationVector and Mac. The FileDigest and FileDigestAlgorithm stay the same.
Just by looking at the detection file and the changes I can make a few assumptions:
- The
EncryptionKey,MacKeyandInitializationVectorare generated each time the tool runs. - The
EncryptionKeyandInitializationVectormight be used to decrypt theIntunePackage.intunewinfile. - The
MacandMacKey, if their name is derived from HMAC, are somehow used to verify the integrity of theIntunePackage.intunewinfile. - The
FileDigestandFileDigestAlgorithmare used to verify the integrity of the installer files? - There seems to be some sort of base64 encoding going on.
- All the setup files are compressed into the
IntunePackage.intunewinfile, let’s assume it’s a zip file as well, but this time encrypted. - Why would you need the
UnencryptedContentSize, if you’re not going to use it? Maybe because they embed encryption or integrity information in the file itself? Then you would need to have the original size to be able to decrypt it.
IntunePackage.intunewin
Let’s summarize all findings on this secretive IntunePackage.intunewin so far:
- It’s a compressed file, presumably a zip file.
- It’s encrypted, presumably using the
EncryptionKey, andInitializationVectorthat are saved in theDetection.xmlfile. - There is some sort of file integrity check using a
Macand aMacKey, since the MacKey changes every time I run the tool, I assume they use HMAC, with a randomly generated key. - The
UnencryptedContentSizeis saved, so let’s assume the encrypted file is appended or prepended with some sort of encryption or integrity information. - The
EncryptionKeyseems to be exactly 32 bytes or 256 bits. - The
IntunePackage.intunewinfile is5957072bytes and theUnencryptedContentSizeis5957009bytes, so the difference is63bytes. This is probably the size of the encryption and/or integrity information.
I’m by no means an expert in file encryption, but when I searched for InitializationVector with my favorite search engine, I found Initialization Vector on Wikipedia. This page mentions AES, so that’s where I’ll point my attention to. Taking the size of the encryption key in mind, my best guess is AES-256. Taking the Mac and the MacKey into account I found that they may be doing something like Authenticated encryption. This is a way to encrypt and verify the integrity of a file at the same time. This would also explain the UnencryptedContentSize property, since the encrypted file would be bigger then the original file.
Decryption time
To check all my assumptions I’ve asked GitHub CoPilot to help me out.
Question:
Can you explain how to decrypt a file that was encrypted using AES encryption with an initialization vector and a keyed hash message authentication code (HMAC) for integrity verification in C#?
Answer:
Apart from giving me a complete explanation on the topic (I’m really loving GitHub CoPilot, I makes my life as a developer a whole bunch easier), it also provided some code to get me started.
private static async Task DecryptFileWithIVAsync(
string sourceFile,
string targetFile,
byte[] encryptionKey,
byte[] hmacKey,
CancellationToken cancellationToken)
{
byte[]? decryptedFileHash = null;
using (Aes aes = Aes.Create())
using (HMACSHA256 hmac = new HMACSHA256(hmacKey))
using (FileStream sourceFileStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.None, bufferSize: 4096, useAsync: true))
using (MemoryStream encryptedData = new MemoryStream())
{
int offset = hmac.HashSize / 8;
byte[] buffer = new byte[offset + aes.IV.Length];
await sourceFileStream.ReadAsync(buffer, 0, offset + aes.IV.Length, cancellationToken);
byte[] iv = buffer.Skip(offset).ToArray();
byte[] hmacHash = buffer.Take(offset).ToArray();
await sourceFileStream.CopyToAsync(encryptedData, 2097152, cancellationToken);
encryptedData.Seek(0L, SeekOrigin.Begin);
byte[] computedHash = await hmac.ComputeHashAsync(encryptedData, cancellationToken);
if (!computedHash.SequenceEqual(hmacHash))
{
throw new CryptographicException("HMAC validation failed. The encrypted file may have been tampered with.");
}
encryptedData.Seek(0L, SeekOrigin.Begin);
using (ICryptoTransform cryptoTransform = aes.CreateDecryptor(encryptionKey, iv))
using (CryptoStream cryptoStream = new CryptoStream(encryptedData, cryptoTransform, CryptoStreamMode.Read))
using (FileStream targetFileStream = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
cancellationToken.ThrowIfCancellationRequested();
await cryptoStream.CopyToAsync(targetFileStream, 2097152, cancellationToken);
targetFileStream.Flush();
decryptedFileHash = await hmac.ComputeHashAsync(targetFileStream, cancellationToken);
}
}
}
Series: Intune
- Get your apps in Intune
- Package apps for Intune
- Publish apps to Intune
- Remove platform dependency for WingetIntune
- Analysing Win32 Content Prep Tool
- Decrypting intunewin files
- Introducing Content Prep PowerShell
- Creating IntuneWin files with C#
- Hyper-V template for Intune
- Intune requirement for ARM64 devices
Conclusion
I’ve not tested the above code, but I feel I made some big steps in dissecting the mysterious IntunePackage.intunewin file. Being able to decrypt the file would also give me insight into how I could possibly create those files. It’s all part of my journey to be able to create those files myself, without the need for the Win32 Content Prep Tool. And thus making my WingetIntune tool cross platform and cloud ready.
I hope you enjoyed this post, and if you have any feedback, please let me know on Twitter or LinkedIn. All details about this tool are gained by thorough analysis of publicly available data.