mirror of
https://github.com/valinet/ExplorerPatcher.git
synced 2024-11-23 23:21:08 +01:00
Taskbar10: Revised the method of patching Task View so that it works on 22621.2134
This commit is contained in:
parent
82556f08e6
commit
cd7396e8a0
@ -10078,60 +10078,78 @@ BOOL Moment2PatchTaskView(LPMODULEINFO mi)
|
||||
{
|
||||
/***
|
||||
If we're using the old taskbar, it'll be stuck in an infinite loading since it's waiting for the new one to respond.
|
||||
Let's skip those.
|
||||
Let's safely skip those by NOPing the `TaskViewFrame::UpdateWorkAreaAsync()` and `WaitForCompletion()` calls, and
|
||||
turning off the COM object cleanup.
|
||||
|
||||
Step 1:
|
||||
Scan within the DLL. We point to the assignment of the `GetWorkArea()` result.
|
||||
```0F 10 00 F3 0F 7F 46 ?? 4C 8B C7 // movups - movdqu - mov```
|
||||
22621.2283: 24A1CA
|
||||
Scan within the DLL to find the beginning, which is the preparation of the 1st call.
|
||||
It should be 4C 8B or 4D 8B (mov r8, ...).
|
||||
For the patterns, they're +1 from the result since it can be either of those.
|
||||
|
||||
Step 2:
|
||||
Find the beginning, it should be 4C (mov) which is the preparation of the `UpdateWorkAreaAsync()` call.
|
||||
+8 from step 1.
|
||||
Pattern 1 (up to 22621.2134):
|
||||
```8B ?? 48 8D 55 C0 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8```
|
||||
22621.1992: 7463C
|
||||
22621.2134: 3B29C
|
||||
|
||||
Pattern 2 (22621.2283+):
|
||||
```8B ?? 48 8D 54 24 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8```
|
||||
22621.2283: 24A1D2
|
||||
|
||||
Step 3:
|
||||
Find the end, it should be before the next `IUnknown::operator=()` call.
|
||||
```48 8D 4E 60 48 8B 54 24 ?? E8```
|
||||
22621.2283: 24A1F4
|
||||
Step 2:
|
||||
In place of the 1st call's call op (E8), we overwrite it with setting the value of the reference passed into the 2nd
|
||||
argument (rdx) to 0. This is to skip the cleanup that happens right after the 2nd call.
|
||||
```48 C7 02 00 00 00 00 mov qword ptr [rdx], 0```
|
||||
Start from -13 of the byte after 2nd call's end.
|
||||
22621.1992: 74646
|
||||
22621.2134: 3B2A6
|
||||
22621.2283: 24A1DD
|
||||
|
||||
Step 4:
|
||||
NOP everything between step 2 and 3.
|
||||
Step 3:
|
||||
NOP the rest of the 2nd call.
|
||||
|
||||
Summary:
|
||||
```
|
||||
48 8B ?? 48 8D 55 C0 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8 ?? ?? ?? ?? // ~22621.2134
|
||||
48 8B ?? 48 8D 54 24 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8 ?? ?? ?? ?? // 22621.2283~
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
1st: TaskViewFrame::UpdateWorkAreaAsync() 2nd: WaitForCompletion()
|
||||
48 8B ?? 48 8D 54 24 ?? 48 8B ?? 48 C7 02 00 00 00 00 90 90 90 90 90 90 // Result
|
||||
-------------------------------- xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxx
|
||||
We need rdx Step 2 Step 3
|
||||
```
|
||||
|
||||
Notes:
|
||||
- In 22621.1992 and 22621.2134, `~AsyncOperationCompletedHandler()` is inlined, while it is not in 22621.2283. We
|
||||
can see `unconditional_release_ref()` calls right in `RuntimeClassInitialize()` in 1992 and 2134.
|
||||
- In 22621.2134, there is `33 FF xor edi, edi` before the jz for inlined cleanup. The value of edi is used in two
|
||||
more cleanup calls after our area of interest, therefore we can't just NOP all those calls. And I think detecting
|
||||
such things is too much work.
|
||||
***/
|
||||
|
||||
if (!IsWindows11Version22H2Build2134OrHigher())
|
||||
int twoCallsLength = 1 + 18 + 4; // 4C/4D + pattern length + 4 bytes for the 2nd call's call address
|
||||
PBYTE step1 = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x8B\x00\x48\x8D\x55\xC0\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\x08\xE8", "x?xxxxxx?x????xxxx");
|
||||
if (!step1)
|
||||
{
|
||||
// 1413-1992, just short circuit the if
|
||||
// TODO ONLY TESTED ON 1992
|
||||
PBYTE step1 = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x74\x27\x4D\x8B\xC6\x48\x8D\x55\xC0\x48\x8B\xCF", "xxxxxxxxxxxx"); // jz short - mov - lea - mov
|
||||
twoCallsLength += 1; // Add 1 to the pattern length
|
||||
step1 = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x8B\x00\x48\x8D\x54\x24\x00\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\x08\xE8", "x?xxxx?xx?x????xxxx");
|
||||
if (!step1) return FALSE;
|
||||
|
||||
DWORD dwOldProtect = 0;
|
||||
if (!VirtualProtect(step1, 1, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE;
|
||||
step1[0] = 0xEB;
|
||||
VirtualProtect(step1, 1, dwOldProtect, &dwOldProtect);
|
||||
goto done;
|
||||
}
|
||||
|
||||
PBYTE step1 = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x00\xF3\x0F\x7F\x46\x00\x4C\x8B\xC7", "xxxxxxx?xxx");
|
||||
if (!step1) return FALSE;
|
||||
step1 -= 1; // Point to the 4C/4D
|
||||
printf("[TaskViewFrame::RuntimeClassInitialize()] step1 = %lX\n", step1 - (PBYTE)mi->lpBaseOfDll);
|
||||
|
||||
PBYTE step2 = step1 + 8;
|
||||
PBYTE step2 = step1 + twoCallsLength - 13;
|
||||
printf("[TaskViewFrame::RuntimeClassInitialize()] step2 = %lX\n", step2 - (PBYTE)mi->lpBaseOfDll);
|
||||
if (*step2 != 0x4C) return FALSE;
|
||||
|
||||
PBYTE step3 = FindPattern(step2 + 1, 128, "\x48\x8D\x4E\x60\x48\x8B\x54\x24\x00\xE8", "xxxxxxxx?x");
|
||||
if (!step3) return FALSE;
|
||||
printf("[TaskViewFrame::RuntimeClassInitialize()] step3 = %lX\n", step3 - (PBYTE)mi->lpBaseOfDll);
|
||||
PBYTE step3 = step2 + 7;
|
||||
|
||||
// Execution
|
||||
DWORD dwOldProtect = 0;
|
||||
if (!VirtualProtect(step2, step3 - step2, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE;
|
||||
memset(step2, 0x90, step3 - step2);
|
||||
VirtualProtect(step2, step3 - step2, dwOldProtect, &dwOldProtect);
|
||||
if (!VirtualProtect(step1, twoCallsLength, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE;
|
||||
const BYTE step2Payload[] = { 0x48, 0xC7, 0x02, 0x00, 0x00, 0x00, 0x00 };
|
||||
memcpy(step2, step2Payload, sizeof(step2Payload));
|
||||
memset(step3, 0x90, twoCallsLength - (step3 - step1));
|
||||
VirtualProtect(step1, twoCallsLength, dwOldProtect, &dwOldProtect);
|
||||
|
||||
done:
|
||||
printf("[TaskViewFrame::RuntimeClassInitialize()] Patched!\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user