forked from divinebird/pacextractor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpacextractor.c
144 lines (133 loc) · 4.16 KB
/
pacextractor.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/stat.h>
typedef struct {
int16_t someField[24];
int32_t someInt;
int16_t productName[256];
int16_t firmwareName[256];
int32_t partitionCount;
int32_t partitionsListStart;
int32_t someIntFields1[5];
int16_t productName2[50];
int16_t someIntFields2[6];
int16_t someIntFields3[2];
} PacHeader;
typedef struct {
uint32_t length;
int16_t partitionName[256];
int16_t fileName[512];
uint32_t partitionSize;
int32_t someFileds1[2];
uint32_t partitionAddrInPac;
int32_t someFileds2[3];
int32_t dataArray[];
} PartitionHeader;
void getString(int16_t* baseString, char* resString) {
if(*baseString == 0) {
*resString = 0;
return;
}
int length = 0;
do {
*resString = 0xFF & *baseString;
resString++;
baseString++;
if(++length > 256)
break;
} while(baseString > 0);
*resString = 0;
}
int main(int argc, char** argv) {
if(argc < 2) {
printf("command format:\n capextractor <firmware name>.pac");
exit(EXIT_FAILURE);
}
int fd = open(argv[1], O_RDONLY);
if (fd == -1) {
printf("file %s is not find", argv[1]);
exit(EXIT_FAILURE);
}
// fseek(fd, 0, SEEK_END);
// int firmwareSize = (fd);
// fseek(fd, 0, SEEK_SET);
struct stat st;
stat(argv[1], &st);
int firmwareSize = st.st_size;
if(firmwareSize < sizeof(PacHeader)) {
printf("file %s is not firmware", argv[1]);
exit(EXIT_FAILURE);
}
PacHeader pacHeader;
size_t rb =read(fd, &pacHeader, sizeof(PacHeader));
if(rb <= 0) {
printf("Error while parsing PAC header");
exit(EXIT_FAILURE);
}
char buffer[256];
char buffer1[256];
getString(pacHeader.firmwareName, buffer);
printf("Firmware name: %s\n", buffer);
uint32_t curPos = pacHeader.partitionsListStart;
PartitionHeader** partHeaders = malloc(sizeof(PartitionHeader**)*pacHeader.partitionCount);
int i;
for(i = 0; i < pacHeader.partitionCount; i++) {
lseek(fd, curPos, SEEK_SET);
uint32_t length;
rb =read(fd, &length, sizeof(uint32_t));
if(rb <= 0) {
printf("Partition header error");
exit(EXIT_FAILURE);
}
partHeaders[i] = malloc(length);
lseek(fd, curPos, SEEK_SET);
curPos += length;
rb =read(fd, partHeaders[i], length);
if(rb <= 0) {
printf("Partition header error");
exit(EXIT_FAILURE);
}
getString(partHeaders[i]->partitionName, buffer);
getString(partHeaders[i]->fileName, buffer1);
printf("Partition name: %s\n\twith file name: %s\n\twith size %u\n", buffer, buffer1, partHeaders[i]->partitionSize);
}
for(i = 0; i < pacHeader.partitionCount; i++) {
if(partHeaders[i]->partitionSize == 0) {
free(partHeaders[i]);
continue;
}
lseek(fd, partHeaders[i]->partitionAddrInPac, SEEK_SET);
getString(partHeaders[i]->fileName, buffer);
remove(buffer);
int fd_new = open(buffer, O_WRONLY | O_CREAT, 0666);
printf("Extract %s\n", buffer);
uint32_t dataSizeLeft = partHeaders[i]->partitionSize;
while(dataSizeLeft > 0) {
uint32_t copyLength = (dataSizeLeft > 256) ? 256 : dataSizeLeft;
dataSizeLeft -= copyLength;
rb =read(fd, buffer, copyLength);
if(rb != copyLength) {
printf("Partition image extraction error");
exit(EXIT_FAILURE);
}
rb = write(fd_new, buffer, copyLength);
if(rb != copyLength) {
printf("Partition image extraction error");
exit(EXIT_FAILURE);
}
printf("\r\t%02d%%", (uint64_t)100 - (uint64_t)100*dataSizeLeft/partHeaders[i]->partitionSize);
}
printf("\n");
close(fd_new);
free(partHeaders[i]);
}
free(partHeaders);
close(fd);
return EXIT_SUCCESS;
}