-
Notifications
You must be signed in to change notification settings - Fork 1
/
remover.c
129 lines (113 loc) · 4.24 KB
/
remover.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/** @file
* Patch Remover Source File.
*
* This Program will help you revert patched instructions in a patched kernel.
*
* It only supports several formats of kernel:
* 1. Image file compile from source
* 2. Qualcomm patched kernel.
* 3. Image file kernel with efi stub.
*
* Copyright (c) 2021-2024 The DuoWoa authors. All rights reserved.
* MIT License
*
*/
#include "utils.h"
/**
* Receive args and handle status.
*
* @param argc argc is numbers of argues given in cmdline.
* @param argv argv is a array that contains all given values.
* @return program status
*/
int main(int argc, char *argv[]) {
printf("WOA-msmnile DualBoot Patch Remover v1.2.0.0\n");
printf("Copyright (c) 2021-2024 The DuoWoA authors\n\n");
if (argc != 3) {
// Print usage if arg numbers not meet.
printf("args: %d\n", argc);
printf("Usage: <Input Patched Kernel> <Output Kernel>\n");
return -EINVAL;
}
// Program status.
int status = 0;
// Get file paths.
FileContent patchedImage = {.filePath = argv[1]};
FileContent outputImage = {.filePath = argv[2]};
// Read buffer from patched kernel.
if (!get_file_size(&patchedImage)) {
status = -EINVAL;
goto free_and_exit;
}
patchedImage.fileBuffer = malloc(patchedImage.fileSize);
read_file_content(&patchedImage);
// Remove!
Remove(&patchedImage, &outputImage);
// Output buffer to new kernel.
if (outputImage.fileBuffer != NULL) {
write_file_content(&outputImage);
} else {
printf("Error Removing Patch.\n");
status = -EINVAL;
goto free_and_exit;
}
// Free buffers we allocated.
free_and_exit:
free(patchedImage.fileBuffer);
free(outputImage.fileBuffer);
// Everything goes well
printf("Patch successfully removed.\n");
printf("Please check the unpatched kernel image at %s.\n", outputImage.filePath);
return status;
}
/**
* Revert patch in kernel and return output file buffer.
*
* @param patchedKernel Input Patched kernel.
* @param outputKernel Output Reverted kernel.
* @return Reverted kernel buffer, NULL if error processing.
*/
uint8_t *Remove(pFileContent patchedKernel, pFileContent outputKernel) {
// Get previous config from patched kernel.
size_t originKernelSize = *(uint64_t *) (patchedKernel->fileBuffer + 0x30);
// Check if kernel has UNCOMPRESSED_IMG Header.
char kernelHeader[0x11] = {0};
uint8_t hasHeader = 0;
memcpy(kernelHeader, patchedKernel->fileBuffer, 0x10);
if (strcmp(kernelHeader, "UNCOMPRESSED_IMG") == 0) {
printf("Kernel has UNCOMPRESSED_IMG header.\n");
originKernelSize = *(uint64_t *) (patchedKernel->fileBuffer + 0x30 + 0x14) + 0x14;
hasHeader |= 0b1;
}
// Allocate output buffer
outputKernel->fileSize = originKernelSize;
outputKernel->fileBuffer = malloc(outputKernel->fileSize);
// Copy new buffer into outputBuffer.
memcpy(outputKernel->fileBuffer, patchedKernel->fileBuffer, outputKernel->fileSize);
// After copying, jump over header
if (hasHeader & 0b1)
outputKernel->fileBuffer += 0x14;
// Now check if it is a patched kernel
if (outputKernel->fileBuffer[3] == 0x14 && outputKernel->fileBuffer[7] == 0x14) {
printf("Patched kernel detected.");
// Recover Code1 jump instruction, jump to linux kernel directly.
*(uint32_t *) outputKernel->fileBuffer =
((*(uint32_t *) (outputKernel->fileBuffer + 4) & ~(0xFF << 24)) + 1) | (0x14 << 24);
// Clean Code2
*(uint32_t *) (outputKernel->fileBuffer + 4) = 0;
} else {
printf("Not an valid kernel.");
return NULL;
}
// Move back our pointer and recalculate kernel size in kernel
// header if the patched kernel buffer has UNCOMPRESSED_IMG header.
if (hasHeader & 0b1) {
outputKernel->fileBuffer -= 0x14;
size_t newKernelSize = outputKernel->fileSize - 0x14;
outputKernel->fileBuffer[0x10] = newKernelSize >> 0 & 0xFF;
outputKernel->fileBuffer[0x11] = newKernelSize >> 8 & 0xFF;
outputKernel->fileBuffer[0x12] = newKernelSize >> 16 & 0xFF;
outputKernel->fileBuffer[0x13] = newKernelSize >> 24 & 0xFF;
}
return outputKernel->fileBuffer;
}