On windows 10 when we create a program named main.exe or rename a program to main.exe, the program will show a pop up as seen here :
There is 2 different pop up than can be shown :
-the game bar one (French and English version):
-the screenshot one :
(In English: Press Win + Alt + PrintScreen to take a screenshot)
I originally discovered the problem while using python and cx_freeze,
I have tested this on multiple programs, including (as seen above) renaming notepad++.exe to main.exe, and each time, one of the pop up was there,
We can also note that the pop up appears alternatively (one game pop up, then one sreenshot pop up, then one game pop up...)
I run windows10 via virtual box, but as described below, the problem also happend on physical machines.
Any idea on how this happend?
Note : BoltClock also tested it (on a physical machine) and found that, on his machine this behavior is only happening with "Main.exe" while, on my machine the behavior happened whatever may be the uppercase/lowercase distribution of the "main" (IE: it works with main.exe,Main.exe or even MaIN.exe)
I've done some digging over the weekend and I have found over 2000 special exe names which will trigger the same behaviour, not just main.exe
.
Explorer has a component called BroadcastDVR
(located in the twinui
dll) which, upon a process creation, will compare the executable properties against a "store" of games and will launch GameLauncher.exe
if there is a match.
I've not managed to pinpoint where the comparison is done since it's hidden behind a RPC call, which is a PITA to reverse.
Anyway, explorer.exe
has a handle on the following file C:\Users\YOUR_USERNAME\AppData\Local\Microsoft\GamesDVR\KnownGameList.bin
(there is a copy in C:\Windows\broadcastdvr
) which list all the special executables which triggers the XBox recorder popup. You can see the main.exe
entry here (entry #1007):
I've written a 010 template file to parse the entry list and it comes with 2089 entries on my computer. From what I've seen by reversing the binary file, there is three types of entry:
the "simple" one where there is only a match on the executable name.
For example : main.exe
or ai.exe
the more complex one where there is a match on the executable name and the path where the exe is stored must contains some strings.
For example : acu.exe
must be located in a subfolder of Assassin's Creed Unity
.
NB : the Win32 subsystem is case-insensitive so it makes sense that the executable name's case does not matter.
Here is the template (you can install 010 Editor from here, there is an evaluation period I think) :
typedef struct {
BYTE Reserved[0x300];
}HEADER;
typedef struct {
WORD ByteLen;
BYTE RawString[ByteLen];
//local string sName=ReadWString(RawString);
} GAME_WSTR <read=ReadGame>;
typedef struct {
DWORD Reserved;
DWORD ByteLen;
BYTE RawString[ByteLen] <fgcolor=cLtRed>;
} OPTION_STR <read=ReadOption>;
typedef struct {
local int StartAddr = FTell();
DWORD EntrySize;
// Executable game name
GAME_WSTR GameName <fgcolor=cLtBlue>;
// Optional magic
if (ReadUShort() == 0xca54)
WORD OptReserved;
// Optional structs based on switch values
WORD AdditionalNamesCount;
WORD SwitchOption2;
// Additional names (probably like a hint).
local int i =0;
for (i = 0; i < AdditionalNamesCount; i++){
OPTION_STR Option;
if (ReadUShort() == 0xca54)
WORD OptReserved;
}
// Look for a magic
local int Find20h = 0;
while(!Find20h){
Find20h = (0x20 == ReadByte());
BYTE Res;
}
GAME_WSTR GameId;
WORD Reserved;
// Sometimes there is an additionnal name
// sometimes not. I check the current entry
// is at less than the EntrySize declared.
if (FTell()-StartAddr < EntrySize)
{
switch (SwitchOption2)
{
case 3:
OPTION_STR Option3;
break;
case 2:
OPTION_STR Option2;
case 1:
break;
}
}
} ENTRY <read=ReadGameName>;
string ReadOption(OPTION_STR &Game)
{
local wstring GameName = L"";
local int i ;
for (i= 0; 2*i < Game.ByteLen; i++){
WStrcat(GameName, Game.RawString[2*i]);
}
return WStringToString(GameName);
}
string ReadGame(GAME_WSTR &Game)
{
local wstring GameName = L"";
local int i ;
for (i= 0; 2*i < Game.ByteLen; i++){
WStrcat(GameName, Game.RawString[2*i]);
}
return WStringToString(GameName);
}
string ReadGameName(ENTRY &Entry)
{
local string GameName = ReadGame(Entry.GameName);
local string OptionGameName = "";
if (Entry.AdditionalNamesCount)
OptionGameName = " : "+ReadOption(Entry.Option);
return GameName + OptionGameName;
}
//------------------------------------------
LittleEndian();
Printf("Parse KnownGameList.bin Begin.\n");
HEADER UnkwownHeader <bgcolor=cLtGray>;
while(1)
{
ENTRY Entry <bgcolor=cLtPurple>;
//Printf("Entry : %s -> %d.\n",ReadGameName(Entry) ,Entry.AdditionalNamesCount);
}
Printf("Parse KnownGameList.bin End.\n");
If that behavior annoy you, you can always globally disable it by setting the ShowStartup
registry key to 0. It is located in HKEY_CURRENT_USER\Software\Microsoft\GameBar
.
I haven't found how to disable specifically an executable from triggering it, but I might be possible just by looking at the machine code in twinui
.
We have a situation where we can launch a process just by changing the name of an executable. That might be dangerous.
The game launcher command line is located in HKEY_LOCAL_MACHINE\Software\Microsoft\GameOverlay
which needs admin level to write into, so there is not UAC or Integrity level bypass possible here.
(I did not found an authorative link from the msdn, so here a SO answer confirming it : What registry access can you get without Administrator privleges?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With