Last active 1 month ago

Fiesta 2 AMF Raw Extract

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