KAPITALSIN > TUTORIA
Programa para extraer los videos (MP4) de los ficheros .resource (motor Unity)
(1/1)
Fl0ppy:
El programa extrae los datos en ese formato:
nombrefichero.resource_offset_tamaño.mp4 (todo en hexadecimal), si eres ripeador y no sabias como extraer estos datos pues ahora ya tienes esta utilidad, ah y el código está en perl y C (se compila facilmente con GCC [gcc nombre.c] y ya está), recomiendo usar el C ya muchisimo más rápido, por ejemplo en Tad Jones tarda 12 segundos y en Perl tarda unos 4 minutos.
Cabe recordar que este código ES EXPERIMENTAL y puede corromper los datos del videojuego, cuidado pues.
Como usarlo:
-Descarga por ejemplo el Blasphemous o el Tad adventure (tiene casi 800mb's de videos en 4k)
-Si usas el perl pues escribe perl extract_mp4.pl (o el nombre que le has dado) sharedassets01.resource y así con todos los ficheros .resource
Código en perl
Spoiler for Hiden: #!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
# Define buffer size
my $BUFFER_SIZE = 4096;
# Function to find the next occurrence of a marker
sub find_marker {
my ($file, $marker) = @_;
my $marker_len = length($marker);
my $buffer;
# Seek to the start of the file (position is already at the right place)
seek($file, 0, 1);
# Read the file in chunks to find the marker
while (read($file, $buffer, $BUFFER_SIZE)) {
for (my $i = 0; $i <= length($buffer) - $marker_len; $i++) {
if (substr($buffer, $i, $marker_len) eq $marker) {
return tell($file) - length($buffer) + $i;
}
}
}
return -1;
}
# Function to extract the MP4 segment
sub extract_mp4 {
my ($input_file, $start, $end, $output_filename) = @_;
open my $input_fh, '<:raw', $input_file or die "Cannot open input file: $!";
open my $output_fh, '>', $output_filename or die "Cannot open output file: $!";
seek($input_fh, $start, 0);
my $length = $end - $start;
my $buffer;
while ($length > 0 && read($input_fh, $buffer, $BUFFER_SIZE)) {
my $bytes_to_write = $length < length($buffer) ? $length : length($buffer);
print $output_fh substr($buffer, 0, $bytes_to_write);
$length -= $bytes_to_write;
}
close $input_fh;
close $output_fh;
}
# Function to get the basename without the extension
sub get_basename_without_extension {
my ($input_filename) = @_;
return basename($input_filename, '.mp4');
}
# Main logic
if (@ARGV != 1) {
die "Usage: $0 <input_filename>\n";
}
my $input_filename = $ARGV[0];
my $start_marker = "\x00\x00\x00\x18\x66\x74\x79"; # 'ftyp'
my $end_marker = "\x00\x00\x00\x18\x66\x74\x79"; # 'Xtra'
my $file_count = 0;
my $current_pos = 0;
open my $input_fh, '<:raw', $input_filename or die "Cannot open input file: $!";
# Get the base name of the file without the extension
my $basename = get_basename_without_extension($input_filename);
while (1) {
# Find the start marker (e.g., 'ftyp')
my $start = find_marker($input_fh, $start_marker);
last if $start == -1;
# Find the end marker ('Xtra')
my $end = find_marker($input_fh, $end_marker);
if ($end == -1) {
# If the end marker is not found, use the end of the file
seek($input_fh, 0, 2); # Seek to the end of the file
$end = tell($input_fh);
}
# Calculate the size of the segment to extract
my $segment_size = $end - $start;
# Create an output filename with the start position and segment size in hexadecimal
my $output_filename = sprintf("%s_%.8lx_%.8lx.mp4", $basename, $start, $segment_size);
# Extract the MP4 segment
extract_mp4($input_filename, $start, $end, $output_filename);
print "Extracted: $output_filename\n";
$file_count++;
# Update the position for the next marker search
seek($input_fh, $end, 0);
}
close $input_fh;
print "Total MP4 files extracted: $file_count\n";
Código en C
Spoiler for Hiden: #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 4096
// Function to find the next occurrence of a marker
long find_marker(FILE *file, const unsigned char *marker, size_t marker_len) {
unsigned char buffer[BUFFER_SIZE];
size_t bytes_read;
long pos = ftell(file);
// Seek to the start of the file (position is already at the right place)
fseek(file, pos, SEEK_SET);
while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, file)) > 0) {
for (size_t i = 0; i <= bytes_read - marker_len; i++) {
if (memcmp(buffer + i, marker, marker_len) == 0) {
return ftell(file) - bytes_read + i;
}
}
}
return -1;
}
// Function to extract the MP4 segment
void extract_mp4(const char *input_filename, long start, long end, const char *output_filename) {
FILE *input_fh = fopen(input_filename, "rb");
if (!input_fh) {
perror("Cannot open input file");
exit(EXIT_FAILURE);
}
FILE *output_fh = fopen(output_filename, "wb");
if (!output_fh) {
perror("Cannot open output file");
fclose(input_fh);
exit(EXIT_FAILURE);
}
fseek(input_fh, start, SEEK_SET);
long length = end - start;
unsigned char buffer[BUFFER_SIZE];
while (length > 0) {
size_t bytes_to_read = (length < BUFFER_SIZE) ? length : BUFFER_SIZE;
size_t bytes_read = fread(buffer, 1, bytes_to_read, input_fh);
if (bytes_read > 0) {
fwrite(buffer, 1, bytes_read, output_fh);
length -= bytes_read;
}
}
fclose(input_fh);
fclose(output_fh);
}
// Function to get the basename without the extension
void get_basename_without_extension(const char *input_filename, char *basename) {
const char *dot_pos = strrchr(input_filename, '.');
if (dot_pos) {
size_t len = dot_pos - input_filename;
strncpy(basename, input_filename, len);
basename[len] = '\0';
} else {
strcpy(basename, input_filename);
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <input_filename>\n", argv[0]);
return EXIT_FAILURE;
}
const char *input_filename = argv[1];
unsigned char start_marker[] = { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79 }; // 'ftyp'
unsigned char end_marker[] = { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79 }; // 'Xtra'
int file_count = 0;
long current_pos = 0;
FILE *input_fh = fopen(input_filename, "rb");
if (!input_fh) {
perror("Cannot open input file");
return EXIT_FAILURE;
}
char basename[256];
get_basename_without_extension(input_filename, basename);
while (1) {
// Find the start marker (e.g., 'ftyp')
long start = find_marker(input_fh, start_marker, sizeof(start_marker));
if (start == -1) {
break;
}
// Find the end marker ('Xtra')
long end = find_marker(input_fh, end_marker, sizeof(end_marker));
if (end == -1) {
// If the end marker is not found, use the end of the file
fseek(input_fh, 0, SEEK_END);
end = ftell(input_fh);
}
// Calculate the size of the segment to extract
long segment_size = end - start;
// Create an output filename with the start position and segment size in hexadecimal
char output_filename[512];
snprintf(output_filename, sizeof(output_filename), "%s_%.8lx_%.8lx.mp4", basename, start, segment_size);
// Extract the MP4 segment
extract_mp4(input_filename, start, end, output_filename);
printf("Extracted: %s\n", output_filename);
file_count++;
// Update the position for the next marker search
fseek(input_fh, end, SEEK_SET);
}
fclose(input_fh);
printf("Total MP4 files extracted: %d\n", file_count);
return EXIT_SUCCESS;
}
Fl0ppy:
Añadid adjunto en el post principal con binario de Windows (32 bits) creado
Fl0ppy:
Creada versión mejorada
Spoiler for Hiden:
--- Quote (selected) ---#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 4096
// Function to find the next occurrence of a marker
long find_marker(FILE *file, const unsigned char *marker, size_t marker_len) {
unsigned char buffer[BUFFER_SIZE];
size_t bytes_read;
long start_pos = ftell(file);
fseek(file, start_pos, SEEK_SET);
while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, file)) > 0) {
for (size_t i = 0; i <= bytes_read - marker_len; i++) {
if (memcmp(buffer + i, marker, marker_len) == 0) {
return ftell(file) - bytes_read + i;
}
}
}
return -1;
}
// Function to extract the MP4 segment
void extract_mp4(const char *input_filename, long start, long end, const char *output_filename) {
FILE *input_fh = fopen(input_filename, "rb");
if (!input_fh) {
perror("Cannot open input file");
exit(EXIT_FAILURE);
}
FILE *output_fh = fopen(output_filename, "wb");
if (!output_fh) {
perror("Cannot open output file");
fclose(input_fh);
exit(EXIT_FAILURE);
}
fseek(input_fh, start, SEEK_SET);
long length = end - start;
unsigned char buffer[BUFFER_SIZE];
while (length > 0) {
size_t bytes_to_read = (length < BUFFER_SIZE) ? length : BUFFER_SIZE;
size_t bytes_read = fread(buffer, 1, bytes_to_read, input_fh);
if (bytes_read > 0) {
fwrite(buffer, 1, bytes_read, output_fh);
length -= bytes_read;
} else {
break;
}
}
fclose(input_fh);
fclose(output_fh);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <input_filename>\n", argv[0]);
return EXIT_FAILURE;
}
const char *input_filename = argv[1];
// Define start and end markers
unsigned char start_marker[] = { 0x66, 0x74, 0x79, 0x70 }; // 'ftyp'
unsigned char end_marker[] = { 0x58, 0x74, 0x72, 0x61 }; // 'Xtra'
FILE *input_fh = fopen(input_filename, "rb");
if (!input_fh) {
perror("Cannot open input file");
return EXIT_FAILURE;
}
int file_count = 0;
while (1) {
long ftyp_pos = find_marker(input_fh, start_marker, sizeof(start_marker));
if (ftyp_pos == -1) break;
// Move 4 bytes before the marker to include MP4 box size
long start = ftyp_pos - 4;
if (start < 0) start = 0;
// Move file pointer just after 'ftyp' to find 'Xtra'
fseek(input_fh, ftyp_pos + sizeof(start_marker), SEEK_SET);
long end = find_marker(input_fh, end_marker, sizeof(end_marker));
if (end == -1) {
fseek(input_fh, 0, SEEK_END);
end = ftell(input_fh);
}
long segment_size = end - start;
if (segment_size <= 0) {
fprintf(stderr, "Invalid segment size detected. Skipping.\n");
break;
}
char output_filename[512];
snprintf(output_filename, sizeof(output_filename), "%s_%.8lx_%.8lx.mp4", input_filename, start, segment_size);
extract_mp4(input_filename, start, end, output_filename);
printf("Extracted: %s\n", output_filename);
file_count++;
fseek(input_fh, end, SEEK_SET);
}
fclose(input_fh);
printf("Total MP4 files extracted: %d\n", file_count);
return EXIT_SUCCESS;
}
--- Fin de la cita ---
Navegación
Ir a la versión completa