Última atividade 1 month ago

Fiesta 2 AMF Raw Extract

Revisão 526372cf02f8bdafc27bf88e78bbe62c302e59b3

f2rawextract.cpp Bruto
1/*
2 _____ _ _ _____ ____
3| ___(_) ___ ___| |_ __ _| ___/ ___|
4| |_ | |/ _ \/ __| __/ _` | |_ \___ \
5| _| | | __/\__ \ || (_| | _| ___) |
6|_| |_|\___||___/\__\__,_|_| |____/
7
8Fiesta 2 Raw Extract
9
10By: SkyFlow
11*/
12
13#include "f2rawextract.h"
14
15using namespace std;
16
17char *base64_encode(const unsigned char *data,
18 size_t input_length,
19 size_t *output_length) {
20
21 *output_length = 4 * ((input_length + 2) / 3);
22
23 char *encoded_data = (char*)malloc(*output_length);
24 if (encoded_data == NULL) return NULL;
25
26 for (int i = 0, j = 0; i < input_length;) {
27
28 unsigned int octet_a = i < input_length ? data[i++] : 0;
29 unsigned int octet_b = i < input_length ? data[i++] : 0;
30 unsigned int octet_c = i < input_length ? data[i++] : 0;
31
32 unsigned int triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
33
34 encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
35 encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
36 encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
37 encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
38 }
39
40 for (int i = 0; i < mod_table[input_length % 3]; i++)
41 encoded_data[*output_length - 1 - i] = '=';
42
43 return encoded_data;
44}
45
46void build_decoding_table() {
47 decoding_table = (char *)malloc(256);
48 for (int i = 0; i < 64; i++)
49 decoding_table[(unsigned char) encoding_table[i]] = i;
50}
51unsigned char *base64_decode(const char *data,
52 size_t input_length,
53 size_t *output_length) {
54
55 if (decoding_table == NULL) build_decoding_table();
56
57 if (input_length % 4 != 0) return NULL;
58
59 *output_length = input_length / 4 * 3;
60 if (data[input_length - 1] == '=') (*output_length)--;
61 if (data[input_length - 2] == '=') (*output_length)--;
62
63 unsigned char *decoded_data = (unsigned char *)malloc(*output_length);
64
65 if (decoded_data == NULL) return NULL;
66
67 for (int i = 0, j = 0; i < input_length;) {
68
69 unsigned int sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
70 unsigned int sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
71 unsigned int sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
72 unsigned int sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
73
74 unsigned int triple = (sextet_a << 3 * 6)
75 + (sextet_b << 2 * 6)
76 + (sextet_c << 1 * 6)
77 + (sextet_d << 0 * 6);
78
79 if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
80 if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
81 if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
82 }
83
84 return decoded_data;
85}
86
87
88
89void base64_cleanup() {
90 free(decoding_table);
91}
92
93int gzipDecompress(char *body, char *outdata, int len, int outlen)
94{
95
96 z_stream inflate_stream;
97
98 // Set up the zlib stream
99 inflate_stream.zalloc = Z_NULL;
100 inflate_stream.zfree = Z_NULL;
101 inflate_stream.opaque = NULL;
102
103 if(inflateInit2(&inflate_stream, MAX_WBITS+32) != Z_OK)
104 {
105 return -1;
106 }
107
108 z_stream *zs = &inflate_stream;
109
110 // Guess at 50% compression
111 // int outlen = len*2; -- Receiving outputlen
112 //char *outbuf;
113 //outbuf = (char*) malloc(outlen);
114
115 // Tell zlib where to find the data
116 inflate_stream.next_in = (unsigned char*) body;
117 inflate_stream.avail_in = (unsigned int)len;
118
119 // Tell zlib where to put the data
120 inflate_stream.next_out = (unsigned char*) outdata;
121 inflate_stream.avail_out = (unsigned int) outlen;
122
123 // Keep decompressing
124 while (1) {
125
126 int ret;
127
128 ret = inflate(&inflate_stream, Z_SYNC_FLUSH);
129
130 if(ret == Z_OK) // End of a block - will process more blocks
131 {
132
133 // Clear the buffer
134 //outdata->append(outbuf);
135 inflate_stream.next_out = (unsigned char*) outdata;
136 inflate_stream.avail_out = (unsigned int) outlen;
137
138 }
139
140 else if(ret == Z_STREAM_END) // End of the stream - all data was processed
141 {
142
143 //outdata->append(outbuf);
144 //free(outbuf);
145
146 return 0;
147 break;
148
149 }
150
151 else if(ret == Z_BUF_ERROR)
152 {
153 cout << "Buffer error" << endl;
154 cout << inflate_stream.msg << endl;
155 return -1;
156 break;
157 }
158
159 else if(ret == Z_STREAM_ERROR)
160 {
161 cout << "Stream error" << endl;
162 cout << inflate_stream.msg << endl;
163 return -1;
164 break;
165 }
166
167 else if(ret == Z_DATA_ERROR)
168 {
169 cout << "Data error" << endl;
170 cout << inflate_stream.msg << endl;
171 return -1;
172 break;
173 }
174
175 else {
176 cout << "Return code was " << ret << endl;
177 cout << inflate_stream.msg << endl;
178 return -1;
179 break;
180 }
181
182 }
183}
184
185
186int main(int argc, char *argv[]) {
187 unsigned long long offset;
188 unsigned int size, uncsize;
189 char *shiftedkeyb64, *filename, *target, *key, *amffile;
190 bool nullrepacked = false, compressed = false;
191 if(argc < 9) {
192 cout << "Usage: rawextract offset size uncsize target filename compressed nullrepacked shiftedkey_b64 amffile" << endl;
193 return 1;
194 }
195
196 build_decoding_table();
197
198 offset = atol(argv[1]);
199 size = atol(argv[2]);
200 uncsize = atol(argv[3]);
201 target = argv[4];
202 filename = argv[5];
203 compressed = argv[6][0] == '1';
204 nullrepacked = argv[7][0] == '1';
205 shiftedkeyb64 = argv[8];
206 amffile = argv[9];
207
208 cout << "Extracting Name: " << filename << " Offset: " << hex << offset << " Size: " << dec << size << " Uncompressed size: "<< dec << uncsize << " Compressed: " << compressed << " Nullrepacked: "<< nullrepacked << " Key Encoded: " << shiftedkeyb64 << " "<< endl;
209
210
211 size_t ksize = strlen(shiftedkeyb64);
212 size_t k2size = 64;
213 key = (char *)base64_decode((const char *)shiftedkeyb64, ksize, &k2size);
214 /*cout << endl << "endl;
215 for (const unsigned char* p = (unsigned char *)key; *p; ++p)
216 {
217 printf("0x%02x ", *p);
218 }
219 cout << endl;*/
220 FILE *amf = fopen(amffile,"rb");
221 FILE *output = fopen(target, "wb");
222 fseek(amf, offset, SEEK_SET);
223 if(!compressed) {
224 //Decrypt file
225 int decryptedsize = 0;
226 while(decryptedsize != size) {
227 int readsize = (decryptedsize+CHUNK_SIZE)<size?CHUNK_SIZE:size-decryptedsize;
228 fread(readbuffer, readsize, 1, amf);
229 int blockcycles = decryptedsize >> 6;
230 unsigned int keyshift = (0xB * blockcycles) & 0xFFFFFFFF;
231 unsigned int chunkpos = 0;
232 while(chunkpos != readsize) {
233 int blocksize = (readsize-chunkpos)>64?64:readsize-chunkpos;
234 unsigned int poison = (blockcycles + (keyshift >> 6));
235 unsigned int keybump = (((blockcycles + (blockcycles >> 6)) & 0x3F));
236 blockcycles++;
237 keyshift += 11;
238 for(int z=0;z<blocksize;z++)
239 readbuffer[chunkpos+z] ^= (poison + key[keybump^z]) & 0xFF;
240 chunkpos += blocksize;
241 }
242 decryptedsize += readsize;
243 fwrite(readbuffer, readsize, 1, output);
244 }
245 }else{
246 //Decrypt compressed file
247 readbuffer = new char[size];
248 char *outbuffer = new char[uncsize];
249 fread(readbuffer, size, 1, amf);
250 int readsize = 64 > size ? size : 64;
251 if(readsize > 19) {
252 readbuffer[0] ^= readbuffer[16];
253 readbuffer[1] ^= readbuffer[17];
254 readbuffer[2] ^= readbuffer[18];
255 readbuffer[3] ^= readbuffer[19];
256 }
257 for(int z=0;z<readsize;z++)
258 readbuffer[z] = (readbuffer[z] + key[z]) & 0xFF;
259 gzipDecompress(readbuffer, outbuffer, size, uncsize);
260 fwrite(outbuffer, uncsize, 1, output);
261 }
262 fclose(amf);
263 fclose(output);
264
265 base64_cleanup();
266 return 0;
267}