forked from pret/ds_disassembly_tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ntruncompbw.c
107 lines (101 loc) · 3.05 KB
/
ntruncompbw.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
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
static inline uint32_t READ32(const unsigned char * ptr)
{
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
}
static uint32_t MIi_UncompressBackwards(unsigned char ** out_p, size_t compsize)
{
unsigned char * out = *out_p;
// Read the pointer to the end of the compressed image
uint8_t * endptr = out + compsize - 8;
uint32_t size = READ32(endptr);
uint32_t offset = READ32(endptr + 4);
out = realloc(out, compsize + offset);
if (out == NULL)
return -1u;
endptr = out + compsize;
uint8_t * dest_p = endptr + offset;
uint8_t * end = endptr - ((uint8_t)(size >> 24));
uint8_t * start = endptr - (size & ~0xFF000000);
while (end > start) {
uint8_t r5 = *--end;
for (int i = 0; i < 8; i++) {
if ((r5 & 0x80) == 0)
*--dest_p = *--end;
else {
int ip = *--end;
int r7 = *--end;
r7 = ((r7 | (ip << 8)) & ~0xF000) + 2;
ip += 0x20;
while (ip >= 0) {
dest_p[-1] = dest_p[r7];
dest_p--;
ip -= 0x10;
}
}
if (end <= start)
break;
r5 <<= 1;
}
}
*out_p = out;
return compsize + offset;
}
int main(int argc, char ** argv)
{
if (argc < 4) {
fprintf(stderr, "usage: %s FILE VMA END\n\ninsufficient arguments\n", argv[0]);
return 1;
}
char * infname = argv[1];
uint32_t vma = strtoul(argv[2], NULL, 0);
uint32_t end = strtoul(argv[3], NULL, 0);
if (end == 0) {
fprintf(stderr, "compressed size is 0, no action taken\n");
return 0;
}
FILE * infile = fopen(infname, "r+b");
if (infile == NULL) {
fclose(infile);
fprintf(stderr, "unable to open file %s for reading\n", infname);
return 1;
}
fseek(infile, 0, SEEK_END);
long infsize = ftell(infile);
fseek(infile, 0, SEEK_SET);
if (infsize != end - vma) {
fclose(infile);
fprintf(stderr, "compressed size does not match file size, I am cowardly doing nothing\n");
return 0;
}
unsigned char * inbuf = malloc(infsize);
if (inbuf == NULL) {
fclose(infile);
fprintf(stderr, "error: malloc(%d)\n", (int)infsize);
return 1;
}
if (fread(inbuf, 1, infsize, infile) != infsize) {
fclose(infile);
free(inbuf);
fprintf(stderr, "error reading from %s\n", infname);
return 1;
}
uint32_t outsize = MIi_UncompressBackwards(&inbuf, end - vma);
if (outsize == -1u) {
fclose(infile);
fprintf(stderr, "fatal error reallocating for decompression\n");
return 1;
}
fseek(infile, 0, SEEK_SET);
if (fwrite(inbuf, 1, outsize, infile) != outsize) {
fclose(infile);
free(inbuf);
fprintf(stderr, "error writing back to %s\n", infname);
return 1;
}
fclose(infile);
free(inbuf);
return 0;
}