Что нового

Автоматизация Замена части HEX в одном файле на полное содержимое из другого

Tosyk

Новичок
Приветствую!

Версия AutoIt: 3.5.4

Описание: есть бинарный файл vehicles.bin (далее мастер-файл). он состоит из 89 одинаковых по структуре и длине (4396 байт), но разных по содержанию блоков.
в начале мастер-файла есть заголовок:
  • первые 4 байта отвечают за версию файла - 1
  • следующие 4 байта - это количество блоков - 89
далее начинается блок:
  • сначала 4 байта с числом 73 - я не зачем оно, но оно у каждого блока одинаковое, возможно разделитель
  • затем 29 байт, в которых содержится имя блока - оно может быть любым
  • далее идут 4396 байта - это сам блок
так же есть файл MOD.RCAR (далее сурс-файл). он состоит из заголовка (9 байт. всегда одинаковые) и самого блока - 4396 байта!

Помогите пожалуйста сделать EXE, который при запуске будет показывать выпадающий список и кнопку под списком. В списке будут 89 записей-блоков на выбор. когда я выберу из списка название и нажму на кнопку должно происходить следующее: выбранный блок из мастер-файла (только 4396 байта) заменится на блок из сурс-файла (теми же 4396 байтами)

Примечания: я прикладываю файлы примеры к этому сообщению. замечу, что есть редактор для мастер-файла, его можно скачать отсюда — он как раз и может создавать сурс-файлы (RCAR). приложил так же скрин программы и вероятного списка "красивых" записей (слева который).

Буду признателен за помощь :smile:
 

Вложения

Последнее редактирование:

Medic84

Омега
Команда форума
Администратор
1573823642741.png

Что то Ваше описание немного не сходится с началом файла.
Для чтения файла по структуре Вам поможет функция
Код:
_WinAPI_ReadFile()

Там и примерчик есть.
 
Автор
Tosyk

Tosyk

Новичок
Посмотреть вложение 3655

Что то Ваше описание немного не сходится с началом файла.
а в чём не сходится?

Для чтения файла по структуре Вам поможет функция
Код:
_WinAPI_ReadFile()

Там и примерчик есть.
я к сожалению горазд только на простые скрипты по перемещениям и копированию, поэтому и пришёл за помощью
я представляю в голове как оно должно работать, но вот в коде не представляю :/
 

joiner

Модератор
Локальный модератор
Tosyk
В предыдущем посте указано на фото, что нет таких символов в файле - версия, количество блоков и так далее.
по задания я понял так, что у мастер-файла ВСЕГДА вот такая структура
первые 8 байт-личная информация мастер-файла
далее идут 89 блоков
у каждого блока первые 33 байта это инфа, и ее не нужно перезаписывать
а только остальные 4396 байта.

в принципе, задача не сложна. достаточно и
Код:
FileRead
FileSetPos
FileGetPos


насчет выпадающего списка выбора. Программа должна сама читать имена блоков?
 
Последнее редактирование:
Автор
Tosyk

Tosyk

Новичок
у каждого блока первые 33 байта это инфа, и ее не нужно перезаписывать
а только остальные 4396 байта.
верно

насчет выпадающего списка выбора. Программа должна сама читать имена блоков?
да, хотелось бы такое, а если можно привязать (захардкодить) красивые имена то это было бы ещё лучше: типа как Caesar 8C Mostro (alfa8c)

Tosyk
В предыдущем посте указано на фото, что нет таких символов в файле - версия, количество блоков и так далее.
по задания я понял так, что у мастер-файла ВСЕГДА вот такая структура
первые 8 байт-личная информация мастер-файла
далее идут 89 блоков
я немного увлекаюсь реверсивным инженирингом, поэтому могу визуально "парсить" бинарные файлы

первые 4 байта в HEX это:
Код:
01 00 00 00
я не уверен, но обычно в начале пишут версию файла, так удобнее определять и читать файл. в десятичной системе счисления эти байты равны 1

далее 4 байта в HEX это:
Код:
59 00 00 00
вот тут я уже уверен, что это количество блоков. в десятичной системе счисления эти байты равны как раз 89, можно в калькуляторе проверить :smile:
 

joiner

Модератор
Локальный модератор
Код:
#include <Array.au3>
Local $aNamesBlock[0], $bRF, $sName
Local $hFO = FileOpen('vehicles.bin', 16)
FileSetPos($hFO, 12, 1);пропускаем версию файла, количество блоков, первый разделитель
While 1
    $bRF = FileRead($hFO, 29);читаем имя блока
    If @error Then ExitLoop
    FileSetPos($hFO, 4396 + 4, 1); пропускаем весь блок и следующий разделитель
    $sName =  StringStripWS(BinaryToString($bRF), 3)
    If Not($sName = '') Then _ArrayAdd($aNamesBlock, $sName)
WEnd
_ArrayDisplay($aNamesBlock)


34 элемента читаемы, остальное - нет.
может, все-таки, последовательность расположения блоков другая, начиная с определенной части файла. или кодировка текста
Сообщение автоматически объединено:

сделал эксперимент.
разделил мастер файл на отдельные файлы - блоки.
все как в массиве: первые тридцать пять файлов имеют разделить и последующее за ним имя
b.jpg

разделитель разный. сравни первый и второй скрин. разделитель выделен
2.jpg

а вот скрин файла 36, соответственно - блок 36 в мастер файле
v.jpg

и только в конце 36-го блока мы находим новое имя
3.jpg

итог - первые 35 блоков читаются по указанному алгоритму. далее - алгоритм должен меняться. Блок bugatti больше в два раза - занимает 35 и 36 блоки почти полностью
не факт, что остальные блоки одинакового размера
 
Последнее редактирование:
Автор
Tosyk

Tosyk

Новичок
ого, уже выглядит круто! :acute:

прошу прощения, что глубже не покопал в первый раз :/
я разобрал основную структуру файла vehicles.bin более подробно.
проблема в том, что блоки могут состоять из 1 или 2 разделов. поэтому и была ошибка на 34 блоке

vehicles.bin:
Код:
--------------------------------------------------------------------------------------
variable        bytes    description
--------------------------------------------------------------------------------------
fileVersion     4        всегда равно 1 (01 00 00 00)
blockCount      4        количество блоков в файле - 89  (59 00 00 00)

blockLength     4        длина блока
blockName       24       имя блока, постоянная длина, но имя может быть разным
unknown1        4        что то неизвестное, целое число от 0 до 1, может быть = YES/NO?
unknown2        4        неизвестно, чаще всегда = 0, можно пропустить
sectCount       4        количество разделов в блоке
sectLength      4        длина раздела
section         ?        далее идёт раздел, по наблюдениям он всегда длинной 4385 байт
--------------------------------------------------------------------------------------
если разделов 1, то после окончания раздела идёт blockLength и далее
если разделов 2, то после окончания 1 раздела сразу идёт sectLength и за ним следующий блок и далее

так же вот тут более подробно о MOD.RCAR:
Код:
--------------------------------------------------------------------------------------
variable        bytes    description
--------------------------------------------------------------------------------------
fileType        5        тип файла, всегда RHAMl
unknown3        7        непонятная информация
sectCount       4        количество разделов в блоке
sectLength      4        длина раздела
section         ?        далее идёт раздел, по наблюдениям он всегда длинной 4385 байт (до конца файла)
--------------------------------------------------------------------------------------
таким образом нужно взять sectLength и section из MOD.RCAR и заменить на те же самые sectLength и section в vehicles.bin
если в блоке 2 раздела то нужно заменить первый
Сообщение автоматически объединено:

сделал картинку для визуальной понятности
 

Вложения

Последнее редактирование:

joiner

Модератор
Локальный модератор
blockLength 4 длина блока
тут, как я понимаю, размер блока в байтах? даже если он состоит из двух и более разделов. соответственно, если два раздела, то размер блока будет 4385 х 2
точно 4385?
 
Автор
Tosyk

Tosyk

Новичок
тут, как я понимаю, размер блока в байтах? даже если он состоит из двух и более разделов. соответственно, если два раздела, то размер блока будет 4385 х 2
точно 4385?
не совсем. если разделов в блоке 2 то размер блока будет 8814 байтов
вот тут как раз пример 34-го блока: 6E 22 00 00 соответствует 8814 байтам в десятичной системе счисления

1574002121732.png
 
Последнее редактирование:

joiner

Модератор
Локальный модератор
По сути, всегда указывается количество разделов и длина раздела. Так?
Сообщение автоматически объединено:

сразу идёт sectLength и за ним следующий блок и далее
Точнее, следующий раздел, а не блок
 
Автор
Tosyk

Tosyk

Новичок
скорее всегда указывается вот это:
Код:
--------------------------------------------------------------------------------------
variable        bytes    description
--------------------------------------------------------------------------------------
blockLength     4        длина блока
blockName       24       имя блока, постоянная длина, но имя может быть разным
unknown1        4        что то неизвестное, целое число от 0 до 1, может быть = YES/NO?
unknown2        4        неизвестно, чаще всегда = 0, можно пропустить
sectCount       4        количество разделов в блоке
sectLength      4        длина раздела
section         ?        далее идёт раздел, по наблюдениям он всегда длинной 4385 байт
--------------------------------------------------------------------------------------
и судя по тому что я заметил размер двух последних переменных никогда не меняется. вот их то и нужно заменить на новые из файла MOD.RCAR.
в последней переменной я поставил знак вопроса потому, что вроде как размер этого раздела зависит от предыдущего параметра. но я не видел чтобы они менялись.
две неизвестных переменные нужно наверное пропустить. я не смог найти их связи с какими-либо данными

т.е. в MOD.RCAR есть конечно ещё sectCount, который по идее тоже нужно переносить, но его трогать не нужно - он должен остаться неизменным в vehicles.bin!
 
Последнее редактирование:

joiner

Модератор
Локальный модератор
Сравни со списком, который выдает RHAM
Код:
#include <Array.au3>

Local $aNamesBlock[0], $bName, $sName, $nlbl, $nlsl, $blbl, $blsl, $bsc, $ssc
Local $hFO = FileOpen('vehicles.bin', 16)
FileSetPos($hFO, 8, 0);пропускаем версию файла, количество блоков

While 1
    $blbl = FileRead($hFO, 4)
    If @error Then ExitLoop
    $nlbl = BitAND($blbl, 0xFFFF);Длина блока
    $bName = FileRead($hFO, 24)
    $sName = StringStripWS(BinaryToString($bName), 3); Имя блока
    If Not ($sName = '') Then _ArrayAdd($aNamesBlock, $sName)
    FileSetPos($hFO, 8, 1);Пропускаем unknown1 и unknown2
    $bsc = FileRead($hFO, 4)
    $ssc = BitAND($bsc, 0xFFFF); Количество разделов
    $blsl = FileRead($hFO, 4)
    $nlsl = BitAND($blsl, 0xFFFF); Длина раздела
    ConsoleWrite($nlbl & @LF & $sName & @LF & $ssc & @LF & $nlsl & @LF & '===============================' & @LF)
    If $ssc > 1 Then
        For $i = 1 To $ssc
            If $i < $ssc Then
                FileSetPos($hFO, $nlsl + 4, 1); пропускаем раздел
            Else
                FileSetPos($hFO, $nlsl, 1)
            EndIf
        Next
    Else
        FileSetPos($hFO, $nlsl, 1)
    EndIf

WEnd

_ArrayDisplay($aNamesBlock)
 

joiner

Модератор
Локальный модератор
есть момент. размер блока это размер раздела плюс инфо о блоке - длина блока, имя блока и так далее?
сравни цифры
в массиве вторая колонка это позиция начала записи блока в мастер файле. третья колонка это размер раздела. там два блока с двойным разделом: bugatti и chuligani
в консоле пишет размер 8814, но в итоге размер двух разделов 8770 плюс 4 байта на промежуточную запись - длина второго раздела

Код:
#include <Array.au3>

Local $aNamesBlock[1][3] = [['Имя блока', 'Позиция начала записи', 'Размер раздела(ов)']], $bName, $sName, $nlbl, $nlsl, $blbl, $blsl, $bsc, $ssc
Local $hFO = FileOpen('vehicles.bin', 16)
FileSetPos($hFO, 8, 0);пропускаем версию файла, количество блоков

While 1
    $blbl = FileRead($hFO, 4)
    If @error Then ExitLoop
    $nlbl = BitAND($blbl, 0xFFFF);Длина блока
    $bName = FileRead($hFO, 24)
    $sName = StringStripWS(BinaryToString($bName), 3); Имя блока
    FileSetPos($hFO, 8, 1);Пропускаем unknown1 и unknown2
    $bsc = FileRead($hFO, 4)
    $ssc = BitAND($bsc, 0xFFFF); Количество разделов
    $blsl = FileRead($hFO, 4)
    $nlsl = BitAND($blsl, 0xFFFF); Длина раздела
    ConsoleWrite($nlbl & @LF & $sName & @LF & $ssc & @LF & $nlsl & @LF & FileGetPos($hFO) + 1 & @LF & '===============================' & @LF)
    If $ssc > 1 Then
        _ArrayAdd($aNamesBlock, $sName & '|' & FileGetPos($hFO) + 1 & '|' & $ssc * 4385)
        For $i = 1 To $ssc
            If $i < $ssc Then
                FileSetPos($hFO, $nlsl + 4, 1); пропускаем раздел
            Else
                FileSetPos($hFO, $nlsl, 1)
            EndIf
        Next
    Else
        _ArrayAdd($aNamesBlock, $sName & '|' & FileGetPos($hFO) + 1 & '|' & $ssc * 4385)
        FileSetPos($hFO, $nlsl, 1)
    EndIf

WEnd

_ArrayDisplay($aNamesBlock)
Сообщение автоматически объединено:

еще важный момент. ты уверен, что в файле доноре всегда будет одинаковое количество разделов в блоке что и в мастер файле?. то есть, перезапись только раздела, а шапка блока(размер, имя и прочее) не перезаписываем?
Сообщение автоматически объединено:

в файле доноре из архива начало 16 байт это ненужная инфа. но далее идет размер раздела. получается, что в мастер файле нужно начинать запись с позиции размера раздела
 
Последнее редактирование:
Автор
Tosyk

Tosyk

Новичок
посмотрел сейчас размер блока bugatti, там перед именем указан размер блока 8814, если такое количество байтов пропустить то сразу начнётся следующий блок - т.е. его размер потому имя и т.д. — TruckA12. поэтому не очень понимаю откуда вы берёте 8770 :unknown:

в файле доноре всегда 1 блок с 1 разделом. а так же по поводу того, что нужно перезаписывать из донора в мастер файле я написал вот тут: http://autoit-script.ru/threads/zam...lnoe-soderzhimoe-iz-drugogo.27342/post-150565
Сообщение автоматически объединено:

что в мастер файле нужно начинать запись с позиции размера раздела
да, получается что так, нужно подменять только sectLength и section
 

joiner

Модератор
Локальный модератор
8770 это длина двух разделов блока. 4385 х 2
между двумя разделами есть еще 4 байта - это размер второго блока
8814 - это весь блок. вот я и спросил, что возможно в этот размер входит еще и шапка блока с инфой.
насчет донора - в доноре всегда один раздел, даже если в блоке мастер файла их два?

лучше два раза переспросить, чем сто раз переделывать )))
Сообщение автоматически объединено:

точно, размер блока это размер раздела и доп.инфы из шапки
4
24
4
4
4
4
плюс размер двух блоков 8770
получается 8814

только момент такой, что по твоим словам, между разделами большого блока есть 4 байта инфы о размере последующего блока. вот они сюда никак не влезают. хотя судя по коду смещения не происходит, все имена читаются
 
Последнее редактирование:
Автор
Tosyk

Tosyk

Новичок
8770 это длина двух разделов блока. 4385 х 2
математически я вас понимаю, но я вижу цифры в файле и там 8814 :smile:

8814-blockName-unknown1-unknown2-sectCount-sectLength-sectLength = 8770

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

я тут не понятно расписал с переменными?:
Сообщение автоматически объединено:

только момент такой, что по твоим словам, между разделами большого блока есть 4 байта инфы о размере последующего блока. вот они сюда никак не влезают. хотя судя по коду смещения не происходит, все имена читаются
да верно, между двумя разделами в большом блоке есть 4 байта о размере второго раздела. я получил 8770 когда вычитал всю макушку блока из 8814 :smile:
 

joiner

Модератор
Локальный модератор
ладно. в доноре измененная запись для блока alfa8C ?
проверим корректность перезаписи
 
Автор
Tosyk

Tosyk

Новичок
ладно. в доноре измененная запись для блока alfa8C ?
по идее смысл в том чтобы любой раздел в мастер-файле можно было изменить на тот что в доноре.

можно сделать скриншот файла например того же бугатти а потом сравнить
 

joiner

Модератор
Локальный модератор
ясно что нужно любой. на выбор.
для этого и выведена вторая колонка. куда устанавливать указатель в файле для перезаписи участка. я подобный код (идею) уже писал как то
сейчас нужно проверка работоспособности на примерных файлах. далее уже будет через кнопки в окне.
лучше проверять готовый файл в программе, которая их использует. там будет видно, корректно или нет
 
Верх