Autor Tema: Programa para extraer los videos (MP4) de los ficheros .resource (motor Unity)  (Leído 687 veces)

Fl0ppy

  • Administrador
  • Usuario Héroe
  • *****
  • Mensajes: 10009
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;
}
Siempre que pasa igual sucede lo mismo



Fl0ppy

  • Administrador
  • Usuario Héroe
  • *****
  • Mensajes: 10009
Re:Programa para extraer los videos (MP4) de los ficheros .resource (motor Unity)
« Respuesta #1 en: 12 de Abril de 2025, 09:08:58 pm »
Añadid adjunto en el post principal con binario de Windows (32 bits) creado
Siempre que pasa igual sucede lo mismo