IPB

Добро пожаловать, гость ( Вход | Регистрация )

 
Reply to this topicStart new topic
> InstallShield CAB View
Axsis
Dec 13 2010, 00:58
Сообщение #1


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



В InstallShield'е 2011 изменили формат cab/hdr файлов (навскидку увидел что имена файлов теперь хранятся в unicode, возможно есть и другие изменения), соответственно старые распаковщики не у дел.
Слил с оффсайта триал самого InstallShield'а 2011 и достал оттуда ISCabView последней версии, который с новыми файлами умеет работать. Штука весьма неудобная, но до обновления неофициальных утилит думаю может пригодиться: http://ifolder.ru/20772418

PS: да, он распаковывает новый 3DMark11 wink.gif


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Dec 13 2010, 13:26
Сообщение #2


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



О! Спасибо большое!
А можно узнать как он распаковывает?
Потому что из Temp я могу перехватить только data1.cab и data1.hdr, но они очень маленькие и при попытке распаковать из них .DAT файлы программа падает с ошибкой. Мне нужно как-то data2.cab достать из .EXE файла установщика.
У меня есть программа IsXunpack.exe которая может разбивать .EXE файлы InstallShield на .HDR и .CAB, но она за 06.04.2004 и с новыми не работает...

[OffTopic]

P.S. С этим CabView, кстати, вообще смешно:

1) InstallShield CAB File Viewer version 12.0 (v12.00.0499) // © Copyright 1990-2006 Macrovision Software Corporation. All rights raped.
Сначал им пофиг на копирайты.

2) InstallShield Cabinet File Viewer version 15.0 // © Copyright 2008 Acresso Software, Inc. and/or InstallShield Software Co. All Rights Reserved.
Потом они переименовались.

3) InstallShield Cabinet And Log File Viewer // © Copyright 1990-2010 Flexera Software, Inc. and/or InstallShield Software Co. All Rights Reserved.
И ещё раз переименовались.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Dec 13 2010, 21:08
Сообщение #3


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



Оооо... Версий инсталлшилда великое множество, но глобально их можно поделить на 2 типа. Но раз уж затронули эту тему, то обо всём по порядку:
Во-первых как получить сам оверлей для ковыряния оного? Программ довольно много, но наиболее правильно это делает ВНЕЗАПНО 7zip (у меня версия 9.20, за более ранние не ручаюсь, но вроде он давно уже умеет разбирать exe на секции). Правда, он привередлив и распаковывает далеко не все exe, а по-моему только те у которых есть цифровая подпись. Но учитывая что IS платный и пользуются им только крупные разработчики и издатели, то подпись есть на большинстве инсталляторов. Итак, среди распакованных файлов находим файл с загадочным именем "[0]" - это и есть оверлей, он то нам и нужен. Плюс 7zip'а в том, что он, в отличие от других подобных прог, извлекает только то что нам нужно - без отладочной информации, которая в новых инсталляторах идёт после последней секции файла и перед оверлеем, и без самой цифровой подписи, которая идёт после оверлея. (Точнее, всё это сохраняется в отдельных файлах).

Оверлеи, как я уже писал, бывают двух типов - с заголовком "InstallShield" и без заголовка вообще. Файлы с заголовком опишу чуть позже, там тоже несколько разновидностей, шифрование, сжатие и т.д и т.п. В 3DMark'ах (не только в 11, но и в предыдущих) используется второй тип - раньше его брала IsXunpack.exe, но теперь имена файлов и здесь в юникоде, так что облом.
Я эти файлы распаковываю с помощью скриптов для QuickBMS. Для новой версии понадобилась лишь лёгкая модификация скрипта smile.gif

Для старых версий (без юникода; действие аналогично IsXunpack):
CODE
# is_type2.bms
get END ASIZE
math END -= 8
do
  get NAME string
  get FULLNAME string
  get VERSION string
  get SIZE string
  savepos OFFSET
  log FULLNAME OFFSET SIZE
  math OFFSET += SIZE
  goto OFFSET
while OFFSET < END


Для новых версий (с именами в юникоде):
CODE
# is_type2u.bms
get FILES long # Догадались добавить количество файлов...
for I = 0 < FILES
  get NAME unicode
  get FULLNAME unicode
  get VERSION unicode
  get SIZE unicode
  savepos OFFSET
  log FULLNAME OFFSET SIZE
  math OFFSET += SIZE
  goto OFFSET
next I


В принципе ничего сложного, файлы с заголовком опишу чуть позже, там всё несколько хитрее. Но и для них тоже есть скрипт wink.gif
А то тягать инсталляторы из темпа как-то не по-нашенски biggrin.gif

[OffTopic]

Скорее всего, не переименовались, а продались wink.gif
Подозреваю, что "All rights raped." - результат деятельности некоего прыщавого юноши в каком-нибудь рестораторе biggrin.gif
Тот ISCabView, что я выложил, выдернут из InstallShield'а лично мной, так что тут 100% оригинальные файлы.
Если интересует сам IS: http://saturn.installshield.com/product/is...2011premier.exe


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Dec 13 2010, 21:38
Сообщение #4


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Спасибо большое!
Всё распаковал (разве что выяснилось, что чистый (консольный) 7za.exe не умеет распаковывать - надо было именно GUI версию брать). Однако:
1) Запускаю выложенный тобой IsCabView.exe
2) File -> Open, выбираю data1.hdr
3) В панели-дереве слева: Components -> data -> Files
4) В правой панели выбираю любой файл - data0001.dat или data0002.dat
5) Tools -> Extract File
6) Жму "Сохранить" и программа падает с фатальной ошибкой (два окна с руганью подряд)
Для работы IsCabView.exe нужно что-то ещё?

Второй файл уже не нужен - на форуме Extractor.ru его выложили, но мне хотелось бы до конца с IS разобраться, чтобы в будущем не париться...
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Dec 13 2010, 23:59
Сообщение #5


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



QUOTE
Для работы IsCabView.exe нужно что-то ещё?

Та нет вроде. Только что распаковал у себя оба dat файла. Учитывая что она написана на С, то могут понадобиться только библиотеки из vc_redist, скорее всего 2008 версии. (в импорте присутствуют mfc90u.dll, msvcr90.dll, но если бы у тебя их не было, она бы не загрузилась mellow.gif )
Обнови, может поможет. http://www.microsoft.com/downloads/en/deta...&displaylang=en


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Dec 14 2010, 12:54
Сообщение #6


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Не помогло.
Ещё проверил на другой машине (там тоже Windows XP SP3 + все обновления) - тоже самое.
Может надо какую-нибудь примочку IS в систему ставить? Типа ядра установщика? Сдаётся мне, что из-за этого установщик-то и не работает.
Ошибка лезет в mfc90u.dll внутри какой-то функции вызванной по ординалу (адрес .419224 в программе).
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Dec 14 2010, 16:41
Сообщение #7


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



Мда, странно, тоже проверил на XP SP3 - падает. Проверил версии библиотек - у меня на компе версия mfc90u.dll 9.00.30729.4974, самое свежее что смог найти на сайте microsoft - 9.00.30729.4148 - Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package ATL Security Update Но даже с ней на XP падает. Откуда у меня взялась версия 9.00.30729.4974 - хз.
Файлы находятся не в windows\system32\ a в windows\winsxs\..., взял оттуда эту новую версию, положил в папку с IsCabView. Не помогло - программа грузит ту что установлена в системе в winsxs. mad.gif
Запустил под олькой, падает на адресе 78A608EB, из-за того что EAX=0.
CODE
CPU Disasm
Address   Hex dump          Command                                            Comments
78A608E4  |.  53            PUSH EBX                                         ; /lParam
78A608E5  |.  57            PUSH EDI                                         ; |wParam
78A608E6  |.  68 66040000   PUSH 466                                         ; |Msg = WM_USER+102.
78A608EB  |.  FF70 20       PUSH DWORD PTR DS:[EAX+20]                    ; |hWnd
78A608EE  |.  FF15 601A9E78 CALL DWORD PTR DS:[<&USER32.SendMessageW>]    ; \USER32.SendMessageW

Отправил в стек 0, пропустил эту инструкцию, и программа продолжила работать и распаковала выбранный файл. Найти бы способ заставить IsCabView грузить dll, лежащую рядом с ней - можно было б подсунуть ей пропатченную версию, а то патчить системную в winsxs как-то не хочется. unsure.gif


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Dec 14 2010, 17:02
Сообщение #8


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Самый простой способ:

Меняем имя mfc90u.dll на xfc90u.dll в:
- имени этого .DLL файла
- внутри этого .DLL файла
- в импорте .EXE программы

Должно, по идее, заработать.

Выложи, кстати, куда-нибудь свою версию этой библиотеки (с которой работает).

Добавлено:
Засада. У меня другой адрес (версия 9.0.21022.8), но я нашёл этот код и заменил на xor eax, eax / push eax - программа вообще перестала окно обновлять, а после закрытия зависла в процессах... Оставил библиотеку нетронутой, только переименовал, программа всё равно висит - то ли сам IsCabView.exe проверяет свою целостность, то ли ещё что...
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Dec 14 2010, 21:51
Сообщение #9


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



Та похоже, что версия всё-таки не причём - глянул у себя на компе в отладчике - этот код в mfc90u вообще не выполняется, так как срабатывает условный переход чуть выше в этой функции.
Даже не знаю, неужели XP уже не поддерживается? Думаю ещё попробовать всё-таки установить InstallShield на XP и проверить. Но на своём-то компе я его не ставил, а ISCabView работает... unsure.gif
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Dec 16 2010, 02:18
Сообщение #10


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Есть такая утилита как InstallShield 5.x/6.x Cabinet Compression & Maintenance Util (i5comp.exe / i6comp.exe). У меня к ней даже где-то исходные коды на сях валяются, попробую поковырять...

Добавлено:

Ha-ha! I tricked you!
© Laura, Silent Hill 2

Распаковщик: i6compx.zip

Unicode, правда, не поддерживается (тупо переводится в ANSI с заменой на "_" левых символов), но главное, что оно всё правильно распаковывает. Флаг 0x04000000 я поставил от балды, т.к. не знаю какой там должен быть правильный, чтобы по нему определить наличие отсутствия Unicode.
Кстати, это новая версия (у меня её не было) и там нет необходимости в ZD*.DLL файлах для распаковки - соответствующая библиотека статически слинкована с программой, что очень удобно.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Jan 26 2011, 12:17
Сообщение #11


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



Итак, возвращаясь к теме распаковки InstallShield'а с заголовком, а то моё "чуть позже" и так затянулось... rolleyes.gif
Давным-давно были версии IS, в которых файлы в оверлее лежали в открытом виде.
Потом разработчики сделали шифрование каждого файла в псевдоархиве. Потом они сделали шифрование не целиком всего файла, а блоками по 1024 байта, видимо, чтоб не грузить файл в память целиком.
И последнее нововведение - файлы теперь ещё и сжаты перед шифрованием (zlib).
Скрипт поддерживает все (вроде) данные типы. Однако, когда я реализовал расшифровку средствами самого BMS, то работало оно жутко медленно - у меня скорость была порядка 1 Мб в секунду, и ждать, например, по полторы-две минуты на расшифровке 100 мегабайтного файла быстро надоело. Поэтому, почитав в очередной раз справку по QuickBMS, я решил переписать функцию расшифровки на асме и вызывать её из скрипта. Быстрее стало в буквальном смысле на порядок, тот же файл распаковался примерно за 10 сек.
Собственно рабочая версия скрипта:
CODE
IDString "InstallShield\x00"
#Get ASZ ASize
Set MEMORY_FILE2 binary "\x55\x89\xE5\x8B\x75\x08\x8B\x7D\x10\x8B\x4D\x14\xC1\xE9\x02\x36\x81\x34\x8F\xEC\xCA\x79\xF8\x85\xC9\x74\x03\x49\xEB\xF1\x31\xD2\x31\xDB\x8A\x04\x31\xC0\xC0\x04\x32\x04\x3A\x42\x3B\x55\x14\x75\x02\x31\xD2\x43\x3B\x5D\x18\x75\x04\x31\xDB\x31\xD2\x88\x04\x31\x41\x3B\x4D\x0C\x75\xDC\x5D\xC3"
Get FILES Long
GoTo 0x1C 0 SEEK_CUR
For i = 0 < FILES
GetDString NAME 0x100
Get DUMMY Long
Get TYPE Long
Get DUMMY Long
Get SIZE Long
Get DUMMY Long
Get DUMMY Long
Get COMPRESSED Long
GetDString DUMMY2 0x1C
SavePos OFFSET
If TYPE == 0
Log NAME OFFSET SIZE
ElseIf TYPE == 2
Set CHUNKSZ Short 0
CallFunction DecryptFile
ElseIf TYPE == 6
Set CHUNKSZ Short 1024
CallFunction DecryptFile
Else
Print "Unsupported type (%TYPE%) of file %NAME%"
EndIf
Math OFFSET += SIZE
GoTo OFFSET
Next i

StartFunction DecryptFile
Set KEY NAME
StrLen KEYSZ NAME
Log MEMORY_FILE OFFSET SIZE

###################################################################
# IShield.DeCrypt (&Buffer, BufferSize, &Key, KeySize, ChunkSize) #
###################################################################
CallDll MEMORY_FILE2 0 cdecl "" MEMORY_FILE SIZE &KEY KEYSZ CHUNKSZ

If COMPRESSED == 0
Log NAME 0 SIZE MEMORY_FILE
Else
ComType zlib
CLog NAME 0 SIZE 0x10000000 MEMORY_FILE
EndIf
EndFunction

При расшифровке QuickBMS спросит можно ли вызвать функцию из MEMORY_FILE2 - нужно ему разрешить wink.gif

Ну и тестовая версия с расшифровкой на самом BMS:
CODE
IDString "InstallShield\x00"
#Get ASZ ASize
Get FILES Long
GoTo 0x1C 0 SEEK_CUR
For i = 0 < FILES
GetDString NAME 0x100
Get DUMMY Long
Get TYPE Long
Get DUMMY Long
Get SIZE Long
Get DUMMY Long
Get DUMMY Long
Get COMPRESSED Long
GetDString DUMMY2 0x1C
SavePos OFFSET
If TYPE == 0
Log NAME OFFSET SIZE
ElseIf TYPE == 2
Set CHUNKSZ Short 0
CallFunction DecryptFile
ElseIf TYPE == 6
Set CHUNKSZ Short 1024
CallFunction DecryptFile
Else
Print "Unsupported type (%TYPE%) of file %NAME%"
EndIf
Math OFFSET += SIZE
GoTo OFFSET
Next i

StartFunction DecryptFile
Set KEY1 NAME
Set KEY2 Binary \xEC\xCA\x79\xF8
StrLen KEYSZ NAME
Set CO 0 # CHUNK_OFFSET
Set KO 0 # KEY_OFFSET
String KEY1 ^ KEY2
# Print "New KEY1 is %KEY1%"
Log MEMORY_FILE OFFSET SIZE
For j = 0 < SIZE
GetVarChr TMP1 MEMORY_FILE j

# Decrypt stage 1 #
Set TMP2 Byte TMP1
Math TMP1 r 4
Math TMP2 l 4
Math TMP1 | TMP2

# Decrypt stage 2 #
GetVarChr TMP2 KEY1 KO
Math TMP1 ^ TMP2
Math KO += 1
If KO == KEYSZ
Math KO = 0
EndIf
Math CO += 1
If CO == CHUNKSZ
Math CO = 0
Math KO = 0
EndIf
PutVarChr MEMORY_FILE j TMP1
Next j
If COMPRESSED == 0
Log NAME 0 SIZE MEMORY_FILE
Else
ComType zlib
CLog NAME 0 SIZE 0x10000000 MEMORY_FILE
EndIf
EndFunction

Повторюсь, эта версия довольно медленная и никак не сообщает работает она или же висит. Я пробовал добавить вывод некоего "прогресс-бара", но тогда скрипт работает ещё медленнее. sad.gif Так что запускайте его на небольших файлах или наберитесь терпения.

PS: И сам алгоритм шифрования: DecodedData = ByteSwap(EncodedData) XOR (FileName.ext XOR 0xECCA79F8).
ByteSwap - обмен местами младших и старших 4 бит в байте, как в 3Дмарках. FileName.ext - имя сохраняемого файла, используется как ключ, поэтому регистр важен. В EncodedData либо весь файл сразу, либо блоками по 1024 байта - в зависимости от версии IS.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Jan 26 2011, 22:43
Сообщение #12


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Спасибо большое!
Убрал твой код в codebox, а то он сильно страницу форума раздувал.

QUOTE(Axsis @ Jan 26 2011, 12:17) *
Однако, когда я реализовал расшифровку средствами самого BMS, то работало оно жутко медленно - у меня скорость была порядка 1 Мб в секунду, и ждать, например, по полторы-две минуты на расшифровке 100 мегабайтного файла быстро надоело.
Хех, поэтому я до сих пор предпочитаю классические языки программирования. У меня для каждого типа распаковщика есть шаблон (по сути уже написанная когда-то программа). В 5 минут из неё выкидывается лишнее и добавляется что надо. Все дела.

QUOTE(Axsis @ Jan 26 2011, 12:17) *
Поэтому, почитав в очередной раз справку по QuickBMS, я решил переписать функцию расшифровки на асме и вызывать её из скрипта.
Ты бы код своей функции (я так понимаю это .DLL файл?) выложил тоже чтобы не писать если понадобится.

Кстати, вопрос:
FileName.ext XOR 0xECCA79F8
FileName.ext же может быть сколь угодно длинным - как его на DWORD-то XOR'ить?.. Что-то я не понял этот момент совсем.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Jan 27 2011, 02:15
Сообщение #13


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



QUOTE(-=CHE@TER=- @ Jan 27 2011, 01:43) *

Кстати, вопрос:
FileName.ext XOR 0xECCA79F8
FileName.ext же может быть сколь угодно длинным - как его на DWORD-то XOR'ить?.. Что-то я не понял этот момент совсем.

Немного некорректно выразился, там не 0xECCA79F8 а массив байт 0xEC, 0xCA, 0x79, 0xF8. Длина имени любая, 5-ый символ в строке xor'ится опять первым байтом массива, 6-й - вторым, и т.д.

Если вставить байтики из "Set MEMORY_FILE2 binary "\x55\x89\xE5\x8B\x75\x08..." в ольку, то можно получить примерно следующее:
CODE
CPU Disasm
Address Hex dump Command Comments
00401000 /. 55 PUSH EBP
00401001 |. 89E5 MOV EBP,ESP
00401003 |. 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
00401006 |. 8B7D 10 MOV EDI,DWORD PTR SS:[EBP+10]
00401009 |. 8B4D 14 MOV ECX,DWORD PTR SS:[EBP+14]
0040100C |. C1E9 02 SHR ECX,2
0040100F |> 36:81348F ECCA79F8 /XOR DWORD PTR SS:[ECX*4+EDI],F879CAEC
00401017 |. 85C9 |TEST ECX,ECX
00401019 |. 74 03 |JE SHORT 0040101E
0040101B |. 49 |DEC ECX
0040101C |.^ EB F1 \JMP SHORT 0040100F
0040101E |> 31D2 XOR EDX,EDX
00401020 |. 31DB XOR EBX,EBX
00401022 |> 8A0431 /MOV AL,BYTE PTR DS:[ESI+ECX]
00401025 |. C0C0 04 |ROL AL,4
00401028 |. 32043A |XOR AL,BYTE PTR DS:[EDI+EDX]
0040102B |. 42 |INC EDX
0040102C |. 3B55 14 |CMP EDX,DWORD PTR SS:[EBP+14]
0040102F |. 75 02 |JNE SHORT 00401033
00401031 |. 31D2 |XOR EDX,EDX
00401033 |> 43 |INC EBX
00401034 |. 3B5D 18 |CMP EBX,DWORD PTR SS:[EBP+18]
00401037 |. 75 04 |JNE SHORT 0040103D
00401039 |. 31DB |XOR EBX,EBX
0040103B |. 31D2 |XOR EDX,EDX
0040103D |> 880431 |MOV BYTE PTR DS:[ESI+ECX],AL
00401040 |. 41 |INC ECX
00401041 |. 3B4D 0C |CMP ECX,DWORD PTR SS:[EBP+0C]
00401044 |.^ 75 DC \JNE SHORT 00401022
00401046 |. 5D POP EBP
00401047 \. C3 RETN

Нормального исходника нет, так как писал и сразу отлаживал непосредственно в ольке. smile.gif


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Mar 16 2013, 12:17
Сообщение #14


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



QUOTE(-=CHE@TER=- @ Dec 16 2010, 06:18) *

Есть такая утилита как InstallShield 5.x/6.x Cabinet Compression & Maintenance Util (i5comp.exe / i6comp.exe). У меня к ней даже где-то исходные коды на сях валяются, попробую поковырять...

Добавлено:

Распаковщик: i6compx.zip

Unicode, правда, не поддерживается (тупо переводится в ANSI с заменой на "_" левых символов), но главное, что оно всё правильно распаковывает. Флаг 0x04000000 я поставил от балды, т.к. не знаю какой там должен быть правильный, чтобы по нему определить наличие отсутствия Unicode.
Кстати, это новая версия (у меня её не было) и там нет необходимости в ZD*.DLL файлах для распаковки - соответствующая библиотека статически слинкована с программой, что очень удобно.

Недавно понадобилось распаковать одну прогу, обнаружил что имена директорий в CAB'ах там обрабатываются отдельно - при распаковке каталога от его имени остаётся только первый символ (т.к. тот же юникод, и второй байт, равный 0, считается как конец строки).
Глянул исходник, вроде нашел где надо поправить, только вот в Visual Studio 2010 проект не захотел импортироваться sad.gif Я так понимаю ты в более старой компилировал его? Может поправишь?
Похоже, обработка имён каталогов идёт тут (i6comp.c):
CODE
LPDIRARRAY DirsArrayBuild(DFTABLE DFT)
{
    LPDIRARRAY pDs;
    DWORD i;

    pDs = Alloc(sizeof(DIRARRAY) + pCabDesc->cDirs * sizeof(LPSTR));
    for (i = 0; i < pCabDesc->cDirs; i++)
        pDs->Dirs[i] = strdup(GetString(DFT, DFT[i]));
    pDs->Count = pCabDesc->cDirs;

    return pDs;
}


По аналогии с твоим фиксом для имён файлов, здесь должно быть что-то вроде
CODE
LPDIRARRAY DirsArrayBuild(DFTABLE DFT)
{
    LPDIRARRAY pDs;
    DWORD i;
    char stmp[MAX_PATH]; // CXTP

    pDs = Alloc(sizeof(DIRARRAY) + pCabDesc->cDirs * sizeof(LPSTR));
    for (i = 0; i < pCabDesc->cDirs; i++)
        // CXTP/
        if(CabHdr.Version & 0x04000000){
            stmp[0] = '\0';
            WideCharToMultiByte(CP_ACP, 0, GetString(DFT, DFT[i]), -1, stmp, MAX_PATH, "_", NULL);
            pDs->Dirs[i] = strdup(stmp);
        }else{
            pDs->Dirs[i] = strdup(GetString(DFT, DFT[i]));
        }
        // /CXTP
    pDs->Count = pCabDesc->cDirs;

    return pDs;
}


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Mar 17 2013, 21:47
Сообщение #15


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Ага, спасибо, исправил и пересобрал - лежит там же. Пробуй. Мне, увы, проверить не на чем.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Mar 18 2013, 11:59
Сообщение #16


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



Фокус не удался. sad.gif
Там походу имена каталогов привязаны к именам так называемых файловых групп.
Чтоб всё работало, там надо либо патчить GetString() либо править все её вызовы.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Mar 18 2013, 20:31
Сообщение #17


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Это макрос из "is6cab.h":
CODE
#define GetString(ptr, ofs) ( (LPSTR) (((BYTE*)ptr) + ((DWORD)ofs)) )

Я вот, подумал, может тупо UNICODE версию собрать?
Кстати, почему у тебя в 2010 не собирается? Что за ошибка-то?
Попробуй вот эту версию заимпортить - я вручную пересобрал проект:
i6comp2x.zip
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Axsis
Mar 18 2013, 23:30
Сообщение #18


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



Ну в смысле переделать его в функцию с проверкой if(CabHdr.Version & 0x04000000), и либо возвращать указатель на строку (как сейчас и есть), либо конвертировать исходную строку из юникода в ascii в память и возвращать указатель на неё.
Ну или правда сделать юникодную версию i17comp smile.gif (6 в названии i6comp - это версия инсталлшилда с которой не было глобальных изменений аж до 16-той и распаковщик прекрасно работал, а в 17 перешли на юникод)

Что прошлые версии, что эта - открываю в VS2010 проект, предлагает сконвертировать из старого в свой формат, соглашаюсь, и всё - пустое окно студии ни ошибок не пишет - ничего. Думаю, быть может из-за того что она у меня Express? Если попытаться создать проект из файлов - что-то ругается про .NET 4 blink.gif
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Jul 24 2024, 14:15
Сообщение #19


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,361
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 314 раз(а)



Возвращаясь к этой теме 11 лет спустя.
Мне пришло письмо с просьбой помочь не только с распаковкой, но и запаковкой назад (это нужно, чтобы не переписывать сложную логику установки оригинального пакета) новых InstallShield, которые в Unicode имена файлов хранят.
Кстати, кому интересно только для распаковки есть программа:
https://github.com/lifenjoiner/ISx
И более навороченная версия:
https://github.com/twogood/unshield
В описании к обеим указано, что они основаны на i5comp/i6comp. Но так как там нет упаковки от слова "совсем", а мне браться за исходные коды i6comp очень не хотелось, то, в итоге, сделал другое решение, которое опишу здесь, возможно, кому-нибудь ещё пригодится.

1. Есть штатная утилита "ISCAB.exe" для запаковки, распаковки, удаления и добавления файлов в .CAB архивы, но последняя версия InstallShield, где эта утилита была, это InstallShield 2009, которая Unicode не поддерживала. Но мы это поправим, поэтому ищем в Интернете установочный пакет InstallShield 2009 версии Premier Edition или Professional (главное, не Express Edition) и берём оттуда файл "ISCAB.exe".

2. Далее идём вот сюда (ссылка) и берём там архив "ISCABViewer2016" - оттуда нужно два файла: "ISTools.dll" и "MediaBuild40.dll" (возможно, эти файлы можно взять из InstallShield 2016).

3. Кидаем файлы из п.1 и п.2 в один каталог. Далее исправляем в "MediaBuild40.dll" следующие байты любым шестнадцатеричным (hex) редактором (смещение: старый_байт новый_байт):
CODE
InstallShield 2016 / MediaBuild40.dll / 23.0.0.511

; offset:old new
; allow to run under Windows NT 5+ (2000/XP+) instead 6+ (Vista+)
00000170: 06 05
00000178: 06 05
; fix invalid memory operations
00023765: 8B 8D
000239EB: A1 B8
00023A04: A1 B8

Я не знаю почему, но в этой .DLL делаются какие-то странные операции с памятью и я откровенно не понимаю как оно, вообще, могло работать. Ну, да ладно, починили.

4. Теперь нужно распаковать пакет перед изменением. Пусть у нас будет каталог C:\DATA\, тогда размещаем файлы следующим образом:
CODE
C:\DATA\ISCab\
  ISTools.dll
  MediaBuild40.dll
  ISCAB.exe

C:\DATA\files\
  layout.bin
  data2.cab
  data1.cab
  ISSetup.dll
  setup.exe
  data1.hdr
  setup.ini
  0x0409.ini
  setup.inx
  setup.iss

C:\DATA\files2\
  layout.bin
  data2.cab
  data1.cab
  ISSetup.dll
  setup.exe
  data1.hdr
  setup.ini
  0x0409.ini
  setup.inx
  setup.iss

Обращаю ваше внимание, что содержимое каталогов "files" и "files2" должно быть одинаковым перед началом перепаковки! Если список файлов не совпадает с вашими - ничего страшного, просто положите все файлы установщика, какие у вас есть, в каталог "files" и сделайте копию в "files2".

5. Перед распаковкой нужно создать список файлов внутри .CAB архивов вызвав в консоли (как работать с консолью описано здесь) из каталога C:\DATA\ следующую команду:
CODE
ISCab\ISCAB.exe files\data1.cab -lx -ifiles.ini


6. Неочевидный момент - почему-то распаковщик не будет работать, если файлы упакованы в .CAB архивах не просто так, а с путями. Поэтому открываем файл "files.ini" и смотрим, есть ли там пути, и, если есть, то создаём их. Например, если видим такое:
CODE
[ProgramFiles(x86)]
File1="CompanyName\SoftwareName\config.exe"

Это значит, что придётся создавать в каталоге C:\DATA\ путь "CompanyName\SoftwareName" - получится такое:
C:\DATA\CompanyName\SoftwareName\
Иначе распаковка будет останавливаться с ошибкой и вы не распакуете все файлы! Я глубоко вопрос не изучал, возможно, "ISCAB.EXE" просто не был рассчитан на распаковку с путями.

7. Теперь файлы можно распаковывать следующей командой (из того же каталога C:\DATA\):
CODE
ISCab\ISCAB.exe files\data1.cab -x -ifiles.ini


8. Всё готово - можно заменять нужные файлы.

9. Перед упаковкой назад делаем копию файла "files.ini" в "files2.ini", находим там строчки:
CODE
[<Disk1>Disk1 Files(1)]
File1="layout.bin"
File2="data1.hdr"
File3="data1.cab"

[<Disk1>Disk1 Files(2)]
File1="setup.exe"
File2="ISSetup.dll"
File3="0x0409.ini"

[<Disk1>Disk1 Files(3)]
File1="setup.inx"

[<Disk1>Disk1 Files(4)]
File1="setup.ini"

И все такие строчки (секции [<Disk#>Disk# Files(#)] с именами файлов далее) удаляем, либо комментируем добавляя в начало строки символ ";". Если этого не сделать упаковка будет вылетать с ошибкой!

10. Вот теперь можно упаковывать назад командой (всё из того же каталога C:\DATA\):
CODE
ISCab\ISCAB.exe files2\data1.cab -a -ifiles2.ini

Обратите внимание, что вместо "files" в обоих случаях стоит "files2" - во-первых, мы не трогаем оригинальный архив, на случай если что-то пойдёт не так, чтобы можно было снова распаковать оригинал, а, во-вторых, в качестве листинга файлов используется "files2.ini", где мы убрали секции Disk# мешающие запаковке.

В общем-то, это всё, можно тестировать результат из каталога "files2".
Обратите внимание, чтобы при распаковке/упаковке в консоль не выводились ошибки - это будет означать что операция была аварийно прервана и не дошла до конца!

Теоретически можно сократить файл "files2.ini" только до одной записи - секции и файла, который нужен, распаковать (опция "-x"), удалить (опция "-r"), затем добавить новый (опция "-a"), а не перепаковывать весь архив. Но я такое не пробовал, возможно, там есть какие-то подводные камни - если кто захочет, то может поэкспериментировать.

Для автоматизации п.6 (создание каталогов) и п.9 (удаление лишнего) можно воспользоваться вот таким скриптом:

iconvert.vbs:
CODE
Option Explicit

Dim objFS, objFile, objTempFile, objRE, objDir, objMatches
Dim isCopy, strLine, strPath, I, S

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile = objFS.OpenTextFile("files.ini")
Set objTempFile = objFS.CreateTextFile("files2.ini", True)

' http://www.script-coding.com/WSH/RegExp.html
Set objRE = CreateObject("VBScript.RegExp")
objRE.IgnoreCase = False
isCopy = False
Set objDir = CreateObject("Scripting.FileSystemObject")

Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
' not empty line
If (Len(Trim(strLine)) > 0) Then
' section?
objRE.Pattern = "^\s*\[.*\]\s*$"
If (objRE.Test(strLine)) Then
' section name
objRE.Pattern = "<Disk\d+>Disk\d+\s+Files\(\d+\)"
' do not copy reserved section
isCopy = Not objRE.Test(strLine)
Else
' line value
objRE.Pattern = "^\s*File\d+\s*=\s*""(.+)""\s*$"
If (objRE.Test(strLine)) Then
' create folders
Set objMatches = objRE.Execute(strLine)
strPath = objMatches.Item(0).SubMatches(0)
For I = 1 To Len(strPath)
If (Mid(strPath, I, 1) = "\") Then
S = Mid(strPath, 1, I - 1)
' folder do not exists
If (Not objDir.FolderExists(S)) Then
objDir.CreateFolder S
End If
End If
Next
End If
End If
End If
' Write the modified line to the temporary file
If (isCopy = True) Then
objTempFile.WriteLine(strLine)
End If
Loop

' Close both files
objFile.Close
objTempFile.Close
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0 -

 



Упрощённая версия Сейчас: 1st November 2024 - 05:34