1
0
mirror of https://github.com/valinet/ExplorerPatcher.git synced 2025-02-17 11:08:41 +01:00

Taskbar10: Revised the method of patching Task View so that it works on 22621.2134

This commit is contained in:
Amrsatrio 2023-09-21 18:41:09 +07:00
parent 82556f08e6
commit cd7396e8a0

View File

@ -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. 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: Step 1:
Scan within the DLL. We point to the assignment of the `GetWorkArea()` result. Scan within the DLL to find the beginning, which is the preparation of the 1st call.
```0F 10 00 F3 0F 7F 46 ?? 4C 8B C7 // movups - movdqu - mov``` It should be 4C 8B or 4D 8B (mov r8, ...).
22621.2283: 24A1CA For the patterns, they're +1 from the result since it can be either of those.
Step 2: Pattern 1 (up to 22621.2134):
Find the beginning, it should be 4C (mov) which is the preparation of the `UpdateWorkAreaAsync()` call. ```8B ?? 48 8D 55 C0 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8```
+8 from step 1. 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 22621.2283: 24A1D2
Step 3: Step 2:
Find the end, it should be before the next `IUnknown::operator=()` call. In place of the 1st call's call op (E8), we overwrite it with setting the value of the reference passed into the 2nd
```48 8D 4E 60 48 8B 54 24 ?? E8``` argument (rdx) to 0. This is to skip the cleanup that happens right after the 2nd call.
22621.2283: 24A1F4 ```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: Step 3:
NOP everything between step 2 and 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 twoCallsLength += 1; // Add 1 to the pattern length
// TODO ONLY TESTED ON 1992 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");
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
if (!step1) return FALSE; 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;
} }
step1 -= 1; // Point to the 4C/4D
PBYTE step1 = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x00\xF3\x0F\x7F\x46\x00\x4C\x8B\xC7", "xxxxxxx?xxx");
if (!step1) return FALSE;
printf("[TaskViewFrame::RuntimeClassInitialize()] step1 = %lX\n", step1 - (PBYTE)mi->lpBaseOfDll); 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); 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"); PBYTE step3 = step2 + 7;
if (!step3) return FALSE;
printf("[TaskViewFrame::RuntimeClassInitialize()] step3 = %lX\n", step3 - (PBYTE)mi->lpBaseOfDll);
// Execution // Execution
DWORD dwOldProtect = 0; DWORD dwOldProtect = 0;
if (!VirtualProtect(step2, step3 - step2, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; if (!VirtualProtect(step1, twoCallsLength, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE;
memset(step2, 0x90, step3 - step2); const BYTE step2Payload[] = { 0x48, 0xC7, 0x02, 0x00, 0x00, 0x00, 0x00 };
VirtualProtect(step2, step3 - step2, dwOldProtect, &dwOldProtect); memcpy(step2, step2Payload, sizeof(step2Payload));
memset(step3, 0x90, twoCallsLength - (step3 - step1));
VirtualProtect(step1, twoCallsLength, dwOldProtect, &dwOldProtect);
done:
printf("[TaskViewFrame::RuntimeClassInitialize()] Patched!\n"); printf("[TaskViewFrame::RuntimeClassInitialize()] Patched!\n");
return TRUE; return TRUE;
} }