Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; ==============================================================================
- ; Версия AutoIt: 3.3.14.5
- ; Язык: Russian
- ; Платформа: Windows NT
- ; Автор: Bannan (http://forum.ru-board.com)
- ; Версия сценария: 0.1 (alpha)
- ;
- ; Назначение сценария:
- ; - извлечение строк интерфейса IDA 7.0 для последующего перевода;
- ; - запись переведенных строк и замена таблицы смещений.
- ;
- ; Сценарий проверен на бинарном файле ida.hlp для IDA 7.0
- ;===============================================================================
- ; ~~~~~~~~ ОПИСАНИЕ РАБОТЫ ~~~~~~~~~
- ; Исходными данными для обработки является файл ida.hlp.
- ;
- ; Поместите этот файл в отдельную папку и создайте его резервную копию.
- ;
- ; [[ Извлечь ]]
- ; Выберите исходный файл ресурса ida.hlp и нажмите "Открыть". По окончании
- ; процесса обработки, если не было никаких ошибок, в папке с файлом ida.hlp
- ; будет создан текстовый файл с именем ida.hlp и расширением ТХТ. Кодировка
- ; документа UTF-8 (with BOM). При переводе строк кодировку не меняйте. Также
- ; не изменяйте форматирование строк. В них обильно присутствуют различные
- ; метки, указатели, спецификаторы, теги и прочие. Работайте только с текстом.
- ;
- ; Полученный файл при работе со сценарием:
- ; - ida.hlp.txt
- ;
- ; [[ Заменить ]]
- ; Для замены в одной папке должны находиться исходный файл ida.hlp и его
- ; одноименный текстовый документ с переведенными строками - ida.hlp.txt.
- ; Выберите исходный файл ресурса ida.hlp и нажмите "Открыть". По окончании
- ; процесса обработки, если не было никаких ошибок, исходный файл ida.hlp
- ; будет перезаписан.
- ;
- ;
- ; ~~~~~~~ СТРУКТУРА ФАЙЛА ~~~~~~~~
- ; Ресурс состоит из 3-х блоков:
- ; I | Header | - ID файла ida.hlp и характеристики массивов
- ; II | Array OffsetStr | - массив ссылок на строки
- ; III | Array Strings | - массив строк с их размерами
- ;
- ; Блок I имеет размер - 13 байт. Он содержит идентификатор ресурса ida.hlp
- ; с начальными двумя байтами 4846, которые используются еще раз между
- ; II и III блоками. Третий байт от начала (02) возможно определяет число
- ; блоков. Последние два байта заголовка определяют количество ссылок.
- ;
- ; Блок II содержит ссылки на строки. Размер ссылки - 4 байта. Порядок байт -
- ; обратный. Ссылка по сути является прямым смещением, по которому строка
- ; находится в файле ida.hlp.
- ;
- ; -- ПРИМЕР:
- ; Имеем в блоке II ссылку вида ......... - 9F1F0000.
- ; Переворачиваем последовательность байт - 00001F9F
- ;
- ; В блоке III строка находится по смещению 00001F9F.
- ; --
- ;
- ; Блок III содержит следующие данные:
- ; - размер (длина) строки
- ; - нуль-терминированная строка (с завершающим нулем - 00)
- ;
- ; Длина строки определяется двумя байтами, порядок байт - обратный.
- ;
- ; -- ПРИМЕР:
- ; Имеем в блоке II ссылку вида ......... - 9F1F0000.
- ; Переворачиваем последовательность байт - 00001F9F
- ; Байты по смещению 00001F9F ........... - 09004E6F204572726F7200
- ; Первые два байта ..................... - 0900
- ; Переворачиваем последовательность байт - 0009
- ; Байты строки ......................... - 4E6F204572726F7200
- ;
- ; Итак, в блоке III по смещению 00001F9F находится строка "No Error",
- ; длина которой - 9(9) байт/символов вместе с завершающим нулем.
- ;
- ;===============================================================================
- ; [BEGIN SCRIPT]
- #NoTrayIcon
- #include <ButtonConstants.au3>
- #include <GUIConstantsEx.au3>
- #include <StaticConstants.au3>
- #include <WindowsConstants.au3>
- #include <ProgressConstants.au3>
- ; Элементы GUI
- Local $hGUI = GUICreate("IDA 7.0 (ida.hlp)", 277, 69)
- Local $iButton1 = GUICtrlCreateButton("Заменить", 4, 14, 70, 25)
- Local $iButton2 = GUICtrlCreateButton("Извлечь", 202, 14, 70, 25)
- $sLabel = GUICtrlCreateLabel("Обработка данных ida.hlp.", 1, 46, 276, 16, $SS_CENTER)
- Local $sLabel1 = GUICtrlCreateLabel("Bannan©2019", 80, 20, 116, 14, $SS_CENTER)
- $hProgress = GUICtrlCreateProgress(7, 50, 262, 10)
- GUICtrlSetState(-1, $GUI_HIDE)
- GUISetState(@SW_SHOW, $hGUI)
- ; Обработка оконных событий
- Local $iMsg
- While 1
- $iMsg = GUIGetMsg()
- Switch $iMsg
- Case $GUI_EVENT_CLOSE
- ExitLoop
- Case $iButton2
- _extract()
- Case $iButton1
- _inject()
- EndSwitch
- WEnd
- GUIDelete($hGUI)
- ; Функция извлечения строк в текстовый документ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- Func _extract()
- ; Установка начальных значений для свойств элементов управления GUI
- GUICtrlSetColor($sLabel, 0x000000)
- GUICtrlSetData($sLabel, "")
- ;--- Диалог выбора исходных файлов ресурсов (HLP) ---
- $sResRawFile = FileOpenDialog("Открыть файл", @ScriptDir, "Строковый ресурс (*.hlp)", 1)
- ; Проверка сделанного выбора (есть строка пути или нет)
- If $sResRawFile = "" Then
- ; Информируем пользователя
- GUICtrlSetColor($sLabel, 0x8b0000)
- GUICtrlSetData($sLabel, "Файл не выбран.")
- ; Выход из функции, если файл не выбран
- Return
- EndIf
- ; Получаем дескриптор полного пути для выбранного файла
- $hResRawFileInit = FileFindFirstFile($sResRawFile)
- ; Получаем имя выбранного файла, включая расширение
- $sResRawFileName = FileFindNextFile($hResRawFileInit)
- ; Проверка имени файла заданным условиям
- If $sResRawFileName <> 'ida.hlp' Then
- ; Информируем пользователя
- GUICtrlSetColor($sLabel, 0xff0000)
- GUICtrlSetData($sLabel, "Выбранный файл не является ресурсным.")
- ; Выход из функции, если имя файла не соответствует условиям
- Return
- EndIf
- ; Формируем имя файла для записи извлеченных строк
- $sResTxtFileName = $sResRawFileName & ".txt"
- ; Проверка наличия файла (есть/нет)
- If FileExists($sResTxtFileName) Then
- ; Информируем пользователя
- If MsgBox(4 + 48, "Предупреждение", "Файл " & $sResTxtFileName & _
- " уже существует." & @CRLF & @CRLF & _
- "Хотите его перезаписать?") = 7 Then
- GUICtrlSetData($sLabel, "Обработка данных ida.hlp.")
- ; Выход из функции, если нажата кнопка "Нет"
- Return
- EndIf
- EndIf
- ; Открываем файл для записи строк
- $hResTxtFile = FileOpen($sResTxtFileName, 2 + 128) ; + 128 (UTF-8 with BOM)
- ;--- Определение характеристик ресурсного файла ---
- ; Открываем файл в двоичном режиме для чтения
- $hResRawFile = FileOpen($sResRawFileName, 16)
- ; Считываем файл в буфер
- $vResRawData = FileRead($hResRawFile)
- ; Определяем количество ссылок в таблице смещений на строки
- $iCountLinks = BitRotate((BinaryMid($vResRawData, 12 , 2)),0)
- ; Устанавливаем адрес начала таблицы смещений на строки (14 позиция от начала файла)
- $iBeginOffsetLinksTable = 14
- ; Объявляем переменную для записи ссылок и присваиваем ей начальное значение
- $iNextOffsetLinksTable = $iBeginOffsetLinksTable
- ; Отключаем отображенине текстовой метки
- GUICtrlSetState($sLabel, $GUI_HIDE)
- ; Включаем отображенине прогресс бара
- GUICtrlSetState($hProgress, $GUI_SHOW)
- ; Устанавливаем начальную позицию прогресс бара
- GUICtrlSetData($hProgress, 0)
- ;--- Извлечение строк из ресурсного файла (HLP) и запись в новый файл ---
- For $i = 1 To $iCountLinks
- ; Определяем позицию строки в массиве строк
- $iOffsetString = BitRotate((BinaryMid ($vResRawData , $iNextOffsetLinksTable , 4)),0)
- ; Проверяем не нулевое значение адреса.
- If $iOffsetString <> 0 Then ; Если адрес не пустой, то...
- ; Определяем размер строки для извлечения
- $iSizeString = BitRotate((BinaryMid($vResRawData , $iOffsetString + 1 , 2)),0)
- ; Получаем бинарный формат строки (без последнего нулевого байта)
- $sStringLine = BinaryMid($vResRawData , $iOffsetString + 3 , $iSizeString - 1 )
- ;//--------------------------------------------------------------------
- ; Замена символов в диапазоне 7F - FF.
- ; Большинство строк содержат служебные коды в диапазоне 7F - FF.
- ; При конвертации переведенных строк в UTF-8 эти служебные символы
- ; будут также преобразованы и в результате утрачены. Чтобы этого
- ; не произошло, все коды заменяем их символьным эквивалентом.
- $sStringLine = StringReplace($sStringLine, 'DC0A', '5C307844430A') ; \0xDC
- $sStringLine = StringReplace($sStringLine, 'DF', '5C30784446') ; \0xDF
- $sStringLine = StringReplace($sStringLine, '0A03', '0A5C30783033') ; \0x03
- $sStringLine = StringReplace($sStringLine, '034361', '5C307830334361')
- $sStringLine = StringReplace($sStringLine, '20DA', '205C30784441') ; \0xDA
- $sStringLine = StringReplace($sStringLine, '0ADA', '0A5C30784441')
- $sStringLine = StringReplace($sStringLine, '20A9', '205C30784139') ; \0xA9
- $sStringLine = StringReplace($sStringLine, '20BF', '205C30784246') ; \0xBF
- $sStringLine = StringReplace($sStringLine, 'BF20', '5C3078424620')
- $sStringLine = StringReplace($sStringLine, 'BF0A', '5C307842460A')
- $sStringLine = StringReplace($sStringLine, 'B320', '5C3078423020') ; \0xB3
- $sStringLine = StringReplace($sStringLine, 'B30A', '5C307842300A')
- $sStringLine = StringReplace($sStringLine, 'D90A', '5C307844390A') ; \0xD9
- $sStringLine = StringReplace($sStringLine, 'D920', '5C3078443920')
- $sStringLine = StringReplace($sStringLine, 'D93C', '5C307844393C')
- ;$sStringLine = StringReplace($sStringLine, 'DBDB', '5C307844425C30784442') ; \0xDB
- $sStringLine = StringReplace($sStringLine, 'C0C4C4', '5C307843305C307843345C30784334') ; \0xC0
- $sStringLine = StringReplace($sStringLine, 'C0C2C4', '5C307843305C307843325C30784334') ; \0xC2
- $sStringLine = StringReplace($sStringLine, 'C4C1C4', '5C307843345C307843315C30784334') ; \0xC1
- $sStringLine = StringReplace($sStringLine, 'C1C4C4', '5C307843315C307843345C30784334')
- $sStringLine = StringReplace($sStringLine, '4441C1C4', '44415C307843315C30784334')
- $sStringLine = StringReplace($sStringLine, 'C4C4C4', '5C307843345C307843345C30784334') ; \0xC4
- $sStringLine = StringReplace($sStringLine, 'C4C45C30', '5C307843345C307843345C30')
- $sStringLine = StringReplace($sStringLine, '4334C4', '43345C30784334')
- ;//--------------------------------------------------------------------
- ; Преобразуем бинарные данные в строку
- $sStringLine = BinaryToString($sStringLine, 1)
- ; Выполняем замену внутристроковых переносов на символьный эквивалент
- $sStringLine = StringRegExpReplace($sStringLine, '(\n)', '\\r\\n') ; 0x0D0A @CRLF \r\n
- Else ; если адрес пустой (0)
- ; Записываем строку с признаком "пустая"
- $sStringLine = '-null-'
- EndIf
- ; Записываем строку в новый текстовый документ
- FileWrite ($hResTxtFile, $sStringLine & @CRLF) ; @CRLF "0D0A"
- ; Переходим к следующему адресу в таблице смещений
- $iNextOffsetLinksTable += 4
- ; Устанавливаем позицию прогресс бара
- GUICtrlSetData($hProgress, $i / $iCountLinks * 100)
- Next
- ;--- Закрываем открытые файлы ---
- FileClose($hResRawFile) ; Исходный файл ресурса
- FileClose($hResTxtFile) ; Текстовый файл со строками
- ;--- Информируем пользователя ---
- GUICtrlSetColor($sLabel, 0x006400)
- GUICtrlSetData($sLabel, "Все строки записаны в " & $sResTxtFileName & "!")
- ; Отключаем отображенине прогресс бара
- GUICtrlSetState($hProgress, $GUI_HIDE)
- ; Включаем отображенине текстовой метки
- GUICtrlSetState($sLabel, $GUI_SHOW)
- EndFunc ;==>_extract
- ; Функция перепаковки строковых ресурсов <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- Func _inject()
- ; Установка начальных значений для свойств элементов управления GUI
- GUICtrlSetColor($sLabel, 0x000000) ;
- GUICtrlSetData($sLabel, "")
- ;--- Диалог выбора исходных файлов ресурсов (HLP) ---
- $sResRawFile = FileOpenDialog( "Открыть файл", @ScriptDir, "Строковый ресурс (*.hlp)", 1)
- ; Проверка сделанного выбора (есть строка пути или нет)
- If $sResRawFile = "" Then
- ; Информируем пользователя
- GUICtrlSetColor($sLabel, 0x8b0000)
- GUICtrlSetData($sLabel, "Файл не выбран.")
- ; Выход из функции, если файл не выбран
- Return
- EndIf
- ; Получаем дескриптор полного пути для выбранного файла
- $hResRawFileInit = FileFindFirstFile($sResRawFile)
- ; Получаем имя выбранного файла, включая расширение
- $sResRawFileName = FileFindNextFile($hResRawFileInit)
- ; Проверка имени файла заданным условиям
- If $sResRawFileName <> 'ida.hlp' Then
- ; Информируем пользователя
- GUICtrlSetColor($sLabel, 0xff0000)
- GUICtrlSetData($sLabel, "Выбранный файл не является ida.hlp.")
- ; Выход из функции, если файла не существует
- Return
- EndIf
- ; Формируем имя файла, в котором находятся строки
- $sResTxtFileName = $sResRawFileName & ".txt"
- ; Формируем полный путь к файлу со строками
- $sPathResTxtFile = GetDir($sResRawFile) & "\" & $sResTxtFileName
- ; Проверка наличия файла (есть/нет)
- If FileExists($sPathResTxtFile) = 0 Then
- ; Информируем пользователя
- GUICtrlSetColor($sLabel, 0xff0000)
- GUICtrlSetData($sLabel, "Файл " & $sResTxtFileName & " не найден.")
- ; Выход из функции, если файла не существует
- Return
- EndIf
- ;--- Определение характеристик ресурсного файла ---
- ; Открываем файл в двоичном режиме для чтения
- $hResRawFile = FileOpen($sResRawFileName, 16)
- ; Считываем файл в буфер
- $vResRawData = FileRead($hResRawFile)
- ; Определяем количество ссылок в таблице ссылок на строки
- $iCountLinks = BitRotate((BinaryMid($vResRawData, 12 , 2)),0)
- ; Устанавливаем адрес начала таблицы ссылок на строки (15 позиция от начала файла)
- $iBeginOffsetLinksTable = 14
- ; Определяем размер таблицы ссылок на строки
- $iSizeLinksTable = $iCountLinks * 4
- ; Определяем адрес начала массива строк
- $iBeginStringsTable = $iBeginOffsetLinksTable + $iSizeLinksTable + 1
- ; Закрываем исходный файл ресурсов
- FileClose($hResRawFile)
- ;--- Модификация ресурсного файла ---
- ; Открываем файл со строками в текстовом режиме только для чтения
- $hResTxtFile = FileOpen($sPathResTxtFile, 0 + 128) ; + 128 (UTF-8 with BOM)
- ; Открываем исходный файл в бинарном режиме для записи
- $hResRawFile = FileOpen($sResRawFile, 16 + 1)
- ; Объявляем переменную для записи новой таблицы ссылок для строк
- $aTempOffsetString = ""
- ; Объявляем переменную для записи позиций и присваиваем ей начальное значение
- $iPosFileNextString = $iBeginStringsTable
- ; Устанавливаем в ресурсном файле позицию на начало массива со строками
- FileSetPos($hResRawFile, $iBeginStringsTable, 0)
- ; Отключаем отображенине текстовой метки
- GUICtrlSetState($sLabel, $GUI_HIDE)
- ; Включаем отображенине прогресс бара
- GUICtrlSetState($hProgress, $GUI_SHOW)
- ; Устанавливаем начальную позицию прогресс бара
- GUICtrlSetData($hProgress, 0)
- ; Объявляем переменную счетчика обработки для прогресс бара
- Local $i = 0
- ;--- Чтение и запись строк, создание таблицы смещений ---
- While 1
- $i += 1
- ; Считываем строку из текстового файла со строками (ТХТ)
- $sStringLineN = FileReadLine($hResTxtFile)
- If @error = -1 Then ExitLoop ; если ошибка чтения, то выход из цикла
- ; Проверяем, является ли строка '-null-'
- $iResult = StringCompare($sStringLineN, '-null-', 1)
- ; Если строка не "пустая", то...
- If $iResult <> 0 Then
- ; Выполняем в строке замену символьных эквивалентов переноса
- $sStringLineN = StringRegExpReplace($sStringLineN, '(\\r\\n)', @LF)
- ; Если в строке есть символы кириллицы, то...
- If StringRegExp($sStringLineN , '[А-Яа-яЁё]+?') Then
- ; Конвертируем в UTF-8, затем в НЕХ и дополняем нулевым байтом (конец строки)
- $sHexStringLineN = StringTrimLeft(StringToBinary($sStringLineN, 4), 2) & "00"
- Else
- ; Конвертируем в UTF-8, затем в НЕХ и дополняем нулевым байтом (конец строки)
- $sHexStringLineN = StringTrimLeft(StringToBinary($sStringLineN), 2) & "00"
- EndIf
- ;//--------------------------------------------------------------------
- ; Восстанавливаем оригинальные символы в диапазоне 7F - FF
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784443', 'DC') ; \0xDC
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784446', 'DF') ; \0xDF
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30783033', '03') ; \0x03
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784441', 'DA') ; \0xDA
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784139', 'A9') ; \0xA9
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784246', 'BF') ; \0xBF
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784230', 'B3') ; \0xB3
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784439', 'D9') ; \0xD9
- ;$sHexStringLineN = StringReplace($sHexStringLineN, '5C30784442', 'DB') ; \0xDB
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784330', 'C0') ; \0xC0
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784331', 'C1') ; \0xC1
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784332', 'C2') ; \0xC2
- $sHexStringLineN = StringReplace($sHexStringLineN, '5C30784334', 'C4') ; \0xC4
- ;//--------------------------------------------------------------------
- ; Определяем размер строки
- $iSizeStringN = BinaryLen(Binary("0x" & $sHexStringLineN))
- ; Получаем байты размера строки в перевернутом виде
- $iHexSizeStringN = Hex(BitShift(BitRotate(Binary("0x" & Hex($iSizeStringN)),0),16), 4)
- ; Дополняем НЕХ данные строки её размером
- $sHexStringLineN = $iHexSizeStringN & $sHexStringLineN
- ; Переворачиваем байты смещения
- $iReversNewOffsetStringShiftN = Hex(BitRotate(Binary("0x" & Hex($iPosFileNextString, 8)),0))
- ; Записываем новое смещение строки в таблицу смещений
- $aTempOffsetString = $aTempOffsetString & $iReversNewOffsetStringShiftN
- ; Записываем новую строку в ресурсный файл
- FileWrite($hResRawFile, Binary("0x" & $sHexStringLineN))
- ; Получаем текущую позицию в ресурсном файле
- $iPosFileNextString = FileGetPos($hResRawFile)
- Else ; если же строка "пустая", то...
- ; Присваиваем нулевое значение адреса
- $iReversNewOffsetStringShiftN = '00000000'
- ; Записываем новое смещение строки в таблицу смещений
- $aTempOffsetString = $aTempOffsetString & $iReversNewOffsetStringShiftN
- EndIf
- ; Устанавливаем позицию прогресс бара
- GUICtrlSetData($hProgress, $i / $iCountLinks * 100)
- WEnd
- ;--- Запись таблицы смещений для строк ---
- FileSetPos($hResRawFile, $iBeginOffsetLinksTable - 1, 0)
- FileWrite($hResRawFile, Binary("0x" & $aTempOffsetString))
- ;--- Закрытие открытых файлов ---
- FileClose($hResRawFile) ; Исходный файл ресурса
- FileClose($hResTxtFile) ; Текстовый файл со строками
- ;--- Информируем пользователя ---
- GUICtrlSetColor($sLabel, 0x006400)
- GUICtrlSetData($sLabel, "Файл " & $sResRawFileName & " изменён!")
- ; Отключаем отображенине прогресс бара
- GUICtrlSetState($hProgress, $GUI_HIDE)
- ; Включаем отображенине текстовой метки
- GUICtrlSetState($sLabel, $GUI_SHOW)
- EndFunc ;==>_inject
- ; Функция получения папки для выбранного файла <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- Func GetDir($sFilePath)
- ;--- Объявление переменных ---
- Local $aFolders = StringSplit($sFilePath, "\")
- Local $iArrayFoldersSize = UBound($aFolders)
- Local $FileDir = ""
- ;--- Проверка наличия пути ---
- If (Not IsString($sFilePath)) Then
- Return SetError(1, 0, -1)
- EndIf
- ;--- Разделение строки пути на подстроки ---
- $aFolders = StringSplit($sFilePath, "\")
- ;--- Получение размера массива с подстроками ---
- $iArrayFoldersSize = UBound($aFolders)
- ;--- Формирование пути к папке ---
- For $i = 1 To ($iArrayFoldersSize - 2)
- $FileDir &= $aFolders[$i] & "\"
- Next
- Return $FileDir
- EndFunc ;==>GetDir
- ; [END SCRIPT]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement