Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.03.2013, 23:10   #1
RibGeDx
Пользователь
 
Аватар для RibGeDx
 
Регистрация: 10.05.2012
Сообщений: 16
По умолчанию File Ripper

Всем привет. Заинтересовала тема для поиска файлов внутри файла. В данном случае интересует поиск только MPEG Layer 3 (т.е. mp3). Как его искать - без понятия. Нужна программа типа HyperRipper или MultiExtractor.

Вообще не понимаю, как детектить mp3. По чем? Есть ли какая то последовательность байт, чтобы можно было понять, что это именно mp3, а не какая то ерунда? Как это делается вообще?
RibGeDx вне форума Ответить с цитированием
Старый 09.03.2013, 23:35   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Ну да, берутся уникальные подписи файлов. Для типизированных файлов достаточно найти его "шапку", а в шапке обычно прописана длинна в байтах. Читаем длину - прочитанная шапка = сколько надо ещё прочитать чтобы получился MP3 фай, читаем, склеиваем с шапкой и кидаем в папку. Все.
Поиск по HEX сигнатурам я поднимал(гуглим по форуму). Алсо смотрте исходники Dragon's Unpacker'а. Там есть HyperRipper.
Человек_Борща вне форума Ответить с цитированием
Старый 09.03.2013, 23:38   #3
RibGeDx
Пользователь
 
Аватар для RibGeDx
 
Регистрация: 10.05.2012
Сообщений: 16
По умолчанию

Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
Ну да, берутся уникальные подписи файлов. Для типизированных файлов достаточно найти его "шапку", а в шапке обычно прописана длинна в байтах. Читаем длину - прочитанная шапка = сколько надо ещё прочитать чтобы получился MP3 фай, читаем, склеиваем с шапкой и кидаем в папку. Все.
Поиск по HEX сигнатурам я поднимал(гуглим по форуму). Алсо смотрте исходники Dragon's Unpacker'а. Там есть HyperRipper.
Спасибо, посмотрю. А насчет HyperRipper'a, он очень медленно детектит mp3. Да и я слизал весь код с него, но он все равно не работал...

Человек_Борща
Как я понял:
1. Открываем файл
2. Ищем шапку
3. Узнаем всю инфу с шапки (layer, pad etc.)
4. Узнаем длину mp3 ((72000 * битрейт) / rate + pad)
5. Меняем позицию в файле на размер mp3 + 1, чтобы искать дальше.

Но, собственно ступорюсь на втором пункте. По каким параметрам искать начало фрейма? Что его выделяет среди остальных байт?

Последний раз редактировалось Stilet; 10.03.2013 в 00:16.
RibGeDx вне форума Ответить с цитированием
Старый 10.03.2013, 00:17   #4
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

Цитата:
Но, собственно ступорюсь на втором пункте. По каким параметрам искать начало фрейма? Что его выделяет среди остальных байт?
А зачем? Обычно в файловых шапках пишут размер тела файла в байтах.
Итого, высасываем тело пришиваем "голову" и получаем файл.
Человек_Борща вне форума Ответить с цитированием
Старый 10.03.2013, 00:43   #5
RibGeDx
Пользователь
 
Аватар для RibGeDx
 
Регистрация: 10.05.2012
Сообщений: 16
По умолчанию

В мп3 нет заголовка, только фреймы и теги. В этом весь прикол, что я понятия не имею, по чем искать мп3.
RibGeDx вне форума Ответить с цитированием
Старый 10.03.2013, 01:07   #6
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,430
По умолчанию

хм,
Ищем признак фрейма.
Если позади не фрейм, а впереди фрейм, то начинаем читать фреймы пока следующий прочитанный фрейм является правильным фреймом.
Если вдруг фрейм стал не правильным, то бросаем цикл а все прочитанное сбрасываем в файл.
Цикл While true do.
Человек_Борща вне форума Ответить с цитированием
Старый 10.03.2013, 01:13   #7
RibGeDx
Пользователь
 
Аватар для RibGeDx
 
Регистрация: 10.05.2012
Сообщений: 16
По умолчанию

Это я знаю. Но вот как проверять фрейм это или нет?
RibGeDx вне форума Ответить с цитированием
Старый 10.03.2013, 11:31   #8
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Вообще-то внутри файла не может быть другого файла.
По определению.
Если бы это было не так, никакой задачи поиска не стояло бы - можно было бы извлечь файл стандартными средствами файловой системы.
Внутри файла можеьт быть лишь фрагмент, повторяющий содержимое файла (ФПСФ).

Мне представляется более рациональным другой путь.
Просто сливать несколько файлов в один без возможности извлечь их обратно вряд ли кто будет.
Поэтому информация, позволяющая извлечь все ФПСФ из файла должна храниться где-то поблизости. Вероятнее всего, в самом файле. Вот ее и нужно найти.
ФПСФ в исполняемом файле могут быть упакованы как ресурсы. В этом случае их (ресурсы) можно извлечь, ничего не зная об их (ресурсов) внутренней структуре.
ФПСФ могут быть объединены в архив, в таком случае где-то должен храниться каталог архива - обычно в конце файла, в его начале или в "парном" файле (парный - обычно имеющий то же название, но другое расширение).
s-andriano вне форума Ответить с цитированием
Старый 10.03.2013, 12:18   #9
RibGeDx
Пользователь
 
Аватар для RibGeDx
 
Регистрация: 10.05.2012
Сообщений: 16
По умолчанию

Сейчас подробно объясню задачу. Есть архив (не сжатый, т.е. заголовки и пр. сохраняются), в нем много разных файлов, в том числе и mp3. Вот их нужно отделить от остальных и правильно распаковать. Как я думаю это реализовать. В заголовке первого фрейма храниться вся информация (lbitrate, layer and etc.) и с него можно достать полный размер mp3 в байтах. Размер заголовка фрейма составляет 4-и байта. Т.е. нужно сканировать каждые 4-и байта в файле и смотреть, фрейм это или нет. Если фрейм - достаем с него всю инфу и получаем размер mp3, потом перемещаем позицию в файле на (текущая позиция + размер mp3 + 1) чтобы искать дальше. Я прав? Можно ли такое провернуть?

P.S. Вот код, который я смог написать (пока просто получение layer'a):

Код:
program test;

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils, Classes;

type
  TBuffer = array [0..3] of Byte;

var
  DestFile: TFileStream;
  Buffer: TBuffer;
  PosBuf, FoundSize: Int64;
  i: Integer;
  MP3Ver: byte;
  MP3Layer: byte;
  MP3Padding: byte;
  MP3Rate: longword;
  MP3BitRate: longword;
  MP3FrameLen: longword;
  MP3Frames: longword;
  VBRFlags: longword;
  VBRNumFrames: longword;
  VBRFileSize: longword;

begin
  DestFile:= TFileStream.Create('data.pak', fmOpenReadWrite and fmShareExclusive);

  PosBuf:= 0;
  FoundSize := 0;
  MP3FrameLen := 0;
  MP3Frames := 0;
  MP3Layer := 0;

  repeat
    DestFile.Read(Buffer, 4);
      if (Buffer[0] = 255) and ((Buffer[1] and 224) = 224) then begin
        MP3Ver := Buffer[1] And 24;
        case MP3Ver of
          24: MP3Ver := 10;
          16: MP3Ver := 20;
          8: Break;
        else
          MP3Ver := 25;
        end;

        MP3Layer := Buffer[1] and 6;
        case MP3Layer of
          6: MP3Layer := 1;
          4: MP3Layer := 2;
          2: MP3Layer := 3;
        end;

        MP3Padding := Buffer[2] and 2;
        if MP3Padding = 2 then
            MP3Padding := 1;

        MP3BitRate := Buffer[2] And 240;
        MP3Rate := Buffer[2] And 12;

        Writeln(MP3Layer);
      end;
    Inc(PosBuf, 4);
  until DestFile.Position >= DestFile.Size;

  DestFile.Free;
end.
В файле data.pak всего лишь один mp3. Т.е. layer должен быть только один, равен 3-м. Да, такой есть, но помимо его еще два layer'a 1. Что не так?

Последний раз редактировалось RibGeDx; 10.03.2013 в 12:37.
RibGeDx вне форума Ответить с цитированием
Старый 10.03.2013, 14:31   #10
RibGeDx
Пользователь
 
Аватар для RibGeDx
 
Регистрация: 10.05.2012
Сообщений: 16
По умолчанию

Ну что же, вроде я понял, как получать Offset. Но.. как дальше получить размер mp3 в байтах? Вот код:

Код:
program test;

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils, Classes;

type
  TBuffer = array [0..3] of Byte;

var
  DestFile: TFileStream;
  Buffer: TBuffer;
  PosBuf, FoundSize: Int64;
  MP3Ver: byte;
  MP3Layer: byte;
  MP3Padding: byte;
  MP3Rate: longword;
  MP3BitRate: longword;
  MP3FrameLen: longword;
  MP3Frames: longword;
  buf3: array[1..3] of char;
  B: Byte;

const
  BIT_RATE_TABLE: array [0..15] of Integer =
    (0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0);

var
  firstOffset: Int64;

begin
  DestFile:= TFileStream.Create('data.mp3', fmOpenReadWrite and fmShareExclusive);
  
  repeat
    DestFile.Read(B, 1);
  until B = 255;
  
  DestFile.Seek((DestFile.Position-1), 0);
  firstOffset:= DestFile.Position;
  DestFile.Read(Buffer, 4);

  if (Buffer[0] = 255) and ((Buffer[1] and 224) = 224) then begin
    MP3Ver := Buffer[1] And 24;
    case MP3Ver of
       24: MP3Ver := 10;
       16: MP3Ver := 20;
       8: exit;
    else
       MP3Ver := 25;
    end;
    
    MP3Layer:= (4 - (Buffer [1] shr 1) and 3) and 3;
    MP3Padding:= ((Buffer [2] shr 1) and 1);

    MP3BitRate := BIT_RATE_TABLE[(Buffer[2] And 240) shr 4];
    MP3Rate := Buffer[2] And 12;

    if MP3Rate = 0 then MP3Rate := 44100;
    if MP3Rate = 4 then MP3Rate := 48000;
    if MP3Rate = 8 then MP3Rate := 32000;

    Writeln(MP3Rate);
    Writeln(Mp3layer);
  end;
  
  DestFile.Free;
end.
что нужно сделать, чтобы получить размер mp3?
RibGeDx вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
В чём разница между unit, header file, cpp file? TwiX Общие вопросы C/C++ 6 29.04.2012 19:49
Почему FILE*, а не FILE Asker13 Общие вопросы C/C++ 2 30.03.2011 23:20
File Чуччи Паскаль, Turbo Pascal, PascalABC.NET 3 10.03.2011 20:00
Error 1 fatal error C1083: Cannot open include file: 'iostream.h': No such file or directory s20 Общие вопросы C/C++ 2 26.09.2009 23:28