最終更新 1 month ago

Fiesta 2 AMF Raw Extract

Lucas Teske revised this gist 10 years ago. Go to revision

1 file changed, 1 deletion

f2rawextract.cpp

@@ -7,7 +7,6 @@
7 7
8 8 Fiesta 2 Raw Extract
9 9
10 - By: SkyFlow
11 10 */
12 11
13 12 #include "f2rawextract.h"

Lucas Teske revised this gist 11 years ago. Go to revision

1 file changed, 267 insertions

f2rawextract.cpp(file created)

@@ -0,0 +1,267 @@
1 + /*
2 + _____ _ _ _____ ____
3 + | ___(_) ___ ___| |_ __ _| ___/ ___|
4 + | |_ | |/ _ \/ __| __/ _` | |_ \___ \
5 + | _| | | __/\__ \ || (_| | _| ___) |
6 + |_| |_|\___||___/\__\__,_|_| |____/
7 +
8 + Fiesta 2 Raw Extract
9 +
10 + By: SkyFlow
11 + */
12 +
13 + #include "f2rawextract.h"
14 +
15 + using namespace std;
16 +
17 + char *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 +
46 + void 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 + }
51 + unsigned 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 +
89 + void base64_cleanup() {
90 + free(decoding_table);
91 + }
92 +
93 + int 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 +
186 + int 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 + }
Newer Older