Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/1: Рейтинг темы: голосов - 1, средняя оценка - 5.00
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786

Как распаковать файл ZIP функциями из Cabinet.dll или чем отличается ZIP от MSZIP

05.03.2025, 23:14. Показов 3697. Ответов 38

Всем привет!

Я тут решил поэкспериментировать и узнать чем же отличается ZIP от MSZIP. Моя идея заключалась в том, чтобы распаковывать простые ZIP-файлы кодом функций из Cabinet.dll, распаковывая буфер MSZIP. Идея была до ужаса проста: взять буфер ZIP и перенести в CAB и приклеить его в буфер MSZIP для того чтобы попробовать распаковать файл таким образом. Как вы думаете, получилось у меня это или нет? Получилось! Но только наполовину. Не всегда буфер MSZIP совпадает с буфером обычного ZIP.

Я решил для этого освоить новые функции Windows 8 из Cabinet.dll и попробовать ими распаковывать буфер обычного ZIP. Мои эксперименты длились несколько дней и всё чего я смог достичь это то что половина файлов у меня всё-таки распаковывается таким образом.

Я поэтому даже немного переделал версию своего класса для распаковки ZIP файлов, пытаясь достичь распаковки буфера ZIP, но правильным образом мне всё-таки этого достичь не удалось... Итак, представляю вам версию своего творчества, но только для ознакомления, а не для постоянного использования, так как мне не удалось на 100% разобраться с Cabinet.dll и сделать так чтобы распаковывались все файлы. Сейчас половину файлов не распаковывается у меня этим кодом...

Буду признателен и благодарен если кто-нибудь мне когда-нибудь подскажет, что же можно изменить в этом коде, для того чтобы распаковывались все файлы, и возможно ли это вообще (это тоже вопрос!).
1
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.03.2025, 23:14
Ответы с готовыми решениями:

Zip в zip. Как распаковать одним махом?
Я изучаю Zip бомбы. И я решил создать прямо атомную. Но вопрос в том, что мне надо распаковать зип сразу. Пример 1.zip>2.zip>3.zip......

Как распаковать ZIP-файл в 7z?
'При помощи VBA WinRAR распаковывает архив в папку … q = Адрес_сохранения_файла 'путь к каталогу, то есть к папке, в конце пути для...

Как программно распаковать Zip файл
Возможно ли штатными средствами .net или на край виндовыми библиотеками стандаратными распаковать архив?

38
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
09.03.2025, 02:03  [ТС]
Я нашёл все необходимые структуры для создания CAB-файла с нуля! Все эти необходимые структуры есть в открытом исходном коде ReactOS за что им большое спасибо конечно, очень помогает, такого больше в интернете нигде не найдёшь уже в MSDN давно нет полного описания CAB файлов...

Добавлено через 5 минут
Итак сначала CAB файла идёт структура CFHEADER, потом идёт CFFOLDER, CFFILE и потом в самом конце уже идёт структура CFDATA, а потом уже сразу следуя за структурой CFDATA сразу уже идёт буфер начинающий с двух байтов 43 4B.

Добавлено через 37 секунд
То есть минимальный CAB-файл состоит из 4 структур.

Добавлено через 48 секунд
В структуре CFDATA правда есть заковырка, её не так просто будет собрать так как там есть контрольная сумма...

Добавлено через 1 минуту
Зато все эти структуры, хотябы, описаны! В ReactOS по крайней мере и мы будем точно знать куда что записывать, а не тыкаться наугад, как я это делал с буфером восьмёрышных функций до этого...

Добавлено через 1 час 2 минуты
Цитата Сообщение от HackerVlad Посмотреть сообщение
Сейчас половину файлов не распаковывается у меня этим кодом...
Я только что выяснил, что этот код, распаковывает только файлы в пределах одного блока до 32 Кб если файлы, а я не мог понять главное и думал почему у меня половину файлов не распаковывается...

Добавлено через 1 минуту
Фактически теперь мне стало понятно уже точно что ZIP и MSZIP это по сути одно и тоже... Там буфер одинаковый вообще...
1
1401 / 860 / 92
Регистрация: 08.02.2017
Сообщений: 3,663
Записей в блоге: 2
09.03.2025, 03:22
Решил поискать, что за CFDATA и поиск выдал мне спецификацию cab-формата - небольшой файл ворд. Там, кстати приводится код вычисления контрольной суммы и такая аннотация (перевод)
Вычисление и проверка контрольных сумм, найденных в записях CFDATA cabinet-файлов, выполняется с помощью функции с именем CSUMCompute. Ее фактический исходный код предоставляется для справки. Если контрольные суммы не предоставлены приложением, создающим cabinet-файл, поле контрольной суммы устанавливается равным нулю. Приложения для извлечения cabinet-файлов не вычисляют и не проверяют контрольную сумму, если поле установлено равным нулю.
Т.е. если чек-суммы нет, то распаковщик не обязан ее проверять.
Кликните здесь для просмотра всего текста
4.1 Checksum Method
The computation and verification of checksums found in CFDATA entries cabinet files is done using a function named CSUMCompute. Its actual source code is provided for reference. When checksums are not supplied by the cabinet file creating application, the checksum field is set to zero. Cabinet extracting applications do not compute or verify the checksum if the field is set to zero.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
CHECKSUM CSUMCompute(void *pv, UINT cb, CHECKSUM seed)
{
    int         cUlong;                 // Number of ULONGs in block
    CHECKSUM    csum;                   // Checksum accumulator
    BYTE       *pb;
    ULONG       ul;
 
    cUlong = cb / 4;                    // Number of ULONGs
    csum = seed;                        // Init checksum
    pb = pv;                            // Start at front of data block
 
    //** Checksum integral multiple of ULONGs
    while (cUlong-- > 0) {
        //** NOTE: Build ULONG in big/little-endian independent manner
        ul = *pb++;                     // Get low-order byte
        ul |= (((ULONG)(*pb++)) <<  8); // Add 2nd byte
        ul |= (((ULONG)(*pb++)) << 16); // Add 3nd byte
        ul |= (((ULONG)(*pb++)) << 24); // Add 4th byte
 
        csum ^= ul;                     // Update checksum
    }
 
    //** Checksum remainder bytes
    ul = 0;
    switch (cb % 4) {
        case 3:
            ul |= (((ULONG)(*pb++)) << 16); // Add 3nd byte
        case 2:
            ul |= (((ULONG)(*pb++)) <<  8); // Add 2nd byte
        case 1:
            ul |= *pb++;                    // Get low-order byte
        default:
            break;
    }
    csum ^= ul;                         // Update checksum
 
    //** Return computed checksum
    return csum;
}
The checksums for non-split CFDATA blocks are computed first on the compressed data bytes, then on the CFDATA header area, starting at the CFDATA.cbData field:

C
1
2
3
4
5
CFDATA.cbData = cbCompressed;
CFDATA.cbUncomp = cbUncompressed;
csumPartial = CSUMCompute(&CFDATA.ab[0],CFDATA.cbData,0);
CFDATA.csum = CSUMCompute(&CFDATA.cbData,sizeof(CFDATA)sizeof(CFDATA.csum),csumPartial);
When blocks are split across cabinet file boundaries, the checksum for the partial block at the end of a cabinet file is computed first on the partial field of compressed data bytes, then on the header:

C
1
2
3
4
5
CFDATA.cbData = cbPartialData;
CFDATA.cbUncomp = 0;
csumPartial = CSUMCompute(&CFDATA.ab[0],cbPartialData,0);
CFDATA.csum = CSUMCompute(&CFDATA.cbData,sizeof(CFDATA)sizeof(CFDATA.csum),csumPartial);
The checksum for the residual block in the next cabinet file is computed first on the remainder of the field of compressed data bytes, then on the header:

C
1
2
3
4
5
CFDATA.cbData = cbResidualData;
CFDATA.cbUncomp = cbUncompressed;
csumPartial = CSUMCompute(&CFDATA.ab[cbPartialData],cbResidualData,0);
CFDATA.csum = CSUMCompute(&CFDATA.cbData,sizeof(CFDATA)sizeof(CFDATA.csum),csumPartial);
Вложения
Тип файла: zip CABFMT.DOC.zip (39.9 Кб, 2 просмотров)
1
1401 / 860 / 92
Регистрация: 08.02.2017
Сообщений: 3,663
Записей в блоге: 2
09.03.2025, 05:23
Я вот, если честно, сам не очень люблю тему ИИ, но к сожалению он работает(наверное, я еще не проверял). Grock 3 beta:
Кликните здесь для просмотра всего текста
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Public Function CSUMCompute(ByRef pv() As Byte, ByVal cb As Long, ByVal seed As Long) As Long
    Dim cUlong As Long      ' Количество полных 32-битных блоков
    Dim csum As Long        ' Накопитель контрольной суммы
    Dim pbIndex As Long     ' Индекс для доступа к массиву байтов
    Dim ul As Long          ' Временная переменная для сборки 32-битного значения
    
    ' Инициализация
    cUlong = cb \ 4         ' Целочисленное деление для получения количества полных блоков
    csum = seed             ' Начальное значение контрольной суммы
    pbIndex = LBound(pv)    ' Начинаем с нижней границы массива
 
    ' Обработка полных 32-битных блоков
    While cUlong > 0
        ' Сборка 32-битного значения независимо от порядка байтов
        ul = pv(pbIndex)                        ' Младший байт
        pbIndex = pbIndex + 1
        ul = ul Or (CLng(pv(pbIndex)) * 256)    ' Второй байт (<< 8)
        pbIndex = pbIndex + 1
        ul = ul Or (CLng(pv(pbIndex)) * 65536)  ' Третий байт (<< 16)
        pbIndex = pbIndex + 1
        ul = ul Or (CLng(pv(pbIndex)) * 16777216) ' Четвертый байт (<< 24)
        pbIndex = pbIndex + 1
        
        csum = csum Xor ul                      ' Обновление контрольной суммы
        cUlong = cUlong - 1
    Wend
 
    ' Обработка оставшихся байтов
    ul = 0
    Select Case cb Mod 4
        Case 3
            ul = ul Or (CLng(pv(pbIndex)) * 65536)  ' Третий байт
            pbIndex = pbIndex + 1
            ' Fall through
        Case 2
            ul = ul Or (CLng(pv(pbIndex)) * 256)    ' Второй байт
            pbIndex = pbIndex + 1
            ' Fall through
        Case 1
            ul = ul Or pv(pbIndex)                  ' Младший байт
            ' pbIndex увеличивать не нужно, это последний байт
        Case Else
            ' Ничего не делаем для case 0
    End Select
    csum = csum Xor ul                          ' Финальное обновление контрольной суммы
 
    ' Возвращаем результат
    CSUMCompute = csum
End Function
Пример использования:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Sub TestChecksum()
    Dim data() As Byte
    ReDim data(4)
    data(0) = 1
    data(1) = 2
    data(2) = 3
    data(3) = 4
    data(4) = 5
    
    Dim result As Long
    result = CSUMCompute(data(0), 5, 0)
    Debug.Print "Checksum: " & result
End Sub
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
09.03.2025, 12:27  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
поле контрольной суммы устанавливается равным нулю
Да, это прокатывает только внутри файла CAB, но не в буфере который создаёт восьмёрышные функции

Добавлено через 6 минут
Цитата Сообщение от testuser2 Посмотреть сообщение
Я вот, если честно, сам не очень люблю тему ИИ, но к сожалению он работает
Надо ещё проверять, я вообще думал что там должно быть CRC32 простая, но тема контрольной суммы мне сейчас не сильно интересна, так как в CAB можно обходится и без неё затирая всё нулями. За документ DOCX спасибо, думаю что это ценный недостающий материал как раз.

Добавлено через 2 минуты
Что касательно структур и создания CAB-файла с нуля, то я ещё вчера это успешно сделал, правда только опять-таки в пределах одного 32-килобайтного блока. Самое сложное сейчас будет разбираться с деление на 32 килобайтные блоки, когда их несколько...
Вот структуры, я переписывал вчера из ReactOS:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Private Type CFHEADER
    Signature     As Long        ' MSCF (cabinet file signature )
    Res1          As Long        ' CRC 32 of the cab header
    cbCabinet     As Long        ' size of this cabinet file in bytes
    Res2          As Long        ' CRC 32 of the folder header
    coffFiles     As Long        ' offset of the first CFFILE entry
    Res3          As Long        ' CRC 32 of the Files header
    VerMinor      As Byte        ' cabinet file format version, minor
    VerMajor      As Byte        ' cabinet file format version, major
    cFolders      As Integer     ' number of CFFOLDER entries in this cabinet
    cFiles        As Integer     ' number of CFFILE entries in this cabinet
    flags         As Integer     ' cabinet file option indicators ' 1- has prev. cab. 2 - has next cab. 3 - has reserved area.
    setID         As Integer     ' must be the same for all cabinets in a set
    iCabinet      As Integer     ' number of this cabinet file in a set
End Type
 
Private Type CFFOLDER
    coffCabStart As Long
    cCFData As Integer
    typeCompress As Integer
End Type
 
Private Type CFFILE
    FileSize As Long
    FileOffset As Long
    FolderIndex As Integer
    FileDate As Integer
    FileTime As Integer
    Attributes As Integer
    FileName As Currency
    Padding As Byte
End Type
 
Private Type CFDATA
    CheckSum As Long
    CompSize As Integer
    UncompSize As Integer
End Type
Добавлено через 5 минут
Теперь мне нужно изучать как заканчиваются 32 килобайтные блоки и начинаются новые в форматах ZIP и CAB
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.03.2025, 01:11  [ТС]
Короче фокус не получился с тем чтобы взять буфер ZIP и разъединить его на несколько 32-килобайтных чанок и перегнать это всё в CAB.
Получается такая штука, что если размер распакованных данных превышает 32 КБ то мой код распаковки уже работать не будет через CAB или через новые восьмёрышные функции. Но если размер несжатого файла до 32 Кб то всё ок, всё работает, только до 32 Кб...

Добавлено через 5 часов 25 минут
В формате файлов ZIP используются блоки произвольного размера, который кстати может превышать 32 Кб, хотя обычно не превышает 32 Кб, но может, по описанию в документации. Мало того каждый блок начинается не с байта, а с бита! Заголовок ZIP буфера представляет собой 3 первых бита из первого байта блока... Но определить размер одного блока в ZIP, как я понял, не представляется возможным не распаковав его... Мало того в формате файлов CAB размер одного блока ограничен 32 Кб, хоть об этом нигде и не сказано почему, и снять это ограничение вряд ли возможно...

Поэтому я делаю выводы хоть ZIP и MSZIP и используют один и тот же алгоритм распаковки RFC1951, тем ни менее они не совместимы получается, что возможно распаковать только ZIP через MSZIP если размер распакованных данных не будет превышать 32 Кб, что очень мало для нас конечно и мало что нам даёт вообще такая возможность распаковки ZIP файлов до 32 Кб...

Добавлено через 22 минуты
Но зато этот код отлично подойдёт, если вам нужно распаковать много маленьких файлов до 32 Кб, из ZIP-архива, с молниеносной скоростью. То есть сам файл ZIP может занимать и больше 32 Кб, хоть несколько мегабайт, главное чтобы сами файлы внутри ZIP, не превышали 32 Кб.
0
1401 / 860 / 92
Регистрация: 08.02.2017
Сообщений: 3,663
Записей в блоге: 2
10.03.2025, 01:45
Вот есть объяснение поблочной упаковки/распаковки, приводится код, там кстати есть тоже момент получения размеров блока из его заголовка https://learn.microsoft.com/en... block-mode
C
1
2
3
4
5
        //  Read block information.
        CompressedBlockSize = *((ULONG UNALIGNED *)(InputData + ProcessedSoFar));
        ProcessedSoFar += sizeof(ULONG);
        UncompressedBlockSize = *((ULONG UNALIGNED *)(InputData + ProcessedSoFar));
        ProcessedSoFar += sizeof(ULONG);
Но это для кабинета, как это в стандартном зипе х.з.
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.03.2025, 02:33  [ТС]
testuser2, я кстати кажется нашёл документ почти такой же как ты мне скидывал: https://learn.microsoft.com/ru... v=msdn.10)

Добавлено через 25 минут
testuser2, кстати! в самом конце этого документа как раз есть описание Формат сжатия данных Microsoft MSZIP
Сжатие MSZIP имеет лишь незначительные отличия от метода 'deflate' Фила Каца. Вместо того, чтобы заново документировать этот метод, этот документ объяснит эти отличия и отошлет читателя к общедоступным документам 'deflate'.

Добавлено через 1 минуту
Как раз в тему! Чем отличается ZIP от MSZIP кажется нашёл нужную документация наконец-то!

Добавлено через 10 минут
Там даже в документации написано что максимальный размер несжатого блока (то есть распакованных данных) не может превышать 32 Кб...
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.03.2025, 13:42  [ТС]
testuser2, ты был прав! сжатие в блочном режиме (COMPRESS_RAW) создаёт ровно такой буфер какой мне надо, без всяких прибамбас, без заголовков, просто начинается сразу с 43 4B а потом сразу ZIP-буфер и всё.
Там тот магический байт значит вообще можно было даже и не разгадывать...

Добавлено через 39 минут
testuser2, но всё равно, даже таким кодом, распаковать можно максимум 32768 байт.
0
1401 / 860 / 92
Регистрация: 08.02.2017
Сообщений: 3,663
Записей в блоге: 2
10.03.2025, 14:32
Цитата Сообщение от HackerVlad Посмотреть сообщение
но всё равно, даже таким кодом, распаковать можно максимум 32768 байт.
Но это уже классно, уже что-то новое, прям глоток свежего воздуха! Как ты ранее говорил, что любой зип дробится на чанки по 32 кб, это значит осталось только выяснить как разделяются эти чанки в обычном зипе и.. дело в шляпе!.. ?

Добавлено через 16 минут
Цитата Сообщение от HackerVlad Посмотреть сообщение
Мало того каждый блок начинается не с байта, а с бита! Заголовок ZIP буфера представляет собой 3 первых бита из первого байта блока... Но определить размер одного блока в ZIP, как я понял, не представляется возможным не распаковав его...
А понял понял, все так..
3.2.3. Детали формата блока

Каждый блок сжатых данных начинается с 3 битового заголовка, содержащего
следующие данные:

первый бит BFINAL
следующие 2 бита BTYPE



Отметим что биты заголовка не обязательно начинаются на границе байта,
так как блок не обязательно занимает целое число байтов.
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.03.2025, 14:44  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
Но это уже классно, уже что-то новое, прям глоток свежего воздуха!
Спасибо за поддержку))) Написал новый примерчик)))

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
Option Explicit
'////////////////////////////////////////////
'// Класс для чтения ZIP-файлов            //
'// Copyright (c) 10.03.2025 by HackerVlad //
'// e-mail: vladislavpeshkov@ya.ru         //
'// Версия 1.32.8                          //
'// Распаковывает файлы до 32768 байт      //
'////////////////////////////////////////////
 
' Декларации API ...
Private Declare Function CreateFileW Lib "kernel32" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CreateFileA Lib "kernel32" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cbMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetMem2 Lib "msvbvm60" (src As Any, dst As Any) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (src As Any, dst As Any) As Long
Private Declare Function CreateDecompressor Lib "cabinet" (ByVal Algorithm As COMPRESS_ALGORITHMS, ByVal AllocationRoutines As Long, hDecompressor As Long) As Long
Private Declare Function Decompress Lib "cabinet" (ByVal hCompressor As Long, CompressedData As Any, ByVal CompressedDataSize As Long, UncompressedBuffer As Any, ByVal UncompressedBufferSize As Long, bytesOut As Long) As Long
Private Declare Function CloseDecompressor Lib "cabinet" (ByVal hDecompressor As Long) As Long
 
' Константы ...
Private Const OPEN_EXISTING As Long = 3
Private Const FILE_SHARE_READ = &H1
Private Const GENERIC_READ As Long = &H80000000
Private Const CREATE_ALWAYS = 2
Private Const EndOFCentralDirSignature As Long = &H6054B50
Private Const CentralFileHeaderSigniature As Long = &H2014B50
Private Const LocalFileHeaderSignature As Long = &H4034B50
Private Const MSZIPSignature As Integer = &H4B43
Private Const CP_UTF8 As Long = 65001
Private Const CP_OEMCP = 1 ' default to OEM code page
Private Const MB64 As Long = 67108864
 
' Структуры ...
Private Type zipLocalFileHeader
    LocalFileHeaderSignature As Long
    VersionNeededToExtract As Integer
    GeneralPurposeBitFlag As Integer
    CompressionMethod As Integer
    LastModFileTime As Integer
    LastModFileDate As Integer
    ' hidden padding 2 bytes As Integer
    CRC32 As Long
    CompressedSize As Long
    UnCompressedSize As Long
    FileNameLength As Integer
    ExtraFieldLength As Integer
End Type
 
Public Enum AttributesInZip
    zipFileAttr
    zipFileDate
    zipFileTime
    zipFileDateAndTime
End Enum
 
Public Enum FileNameCodePageInZip
    zipCodePageAutoDetect
    zipCodePageCP866
    zipCodePageUTF8
End Enum
 
Private Enum COMPRESS_ALGORITHMS
    COMPRESS_ALGORITHM_MSZIP = 2
    COMPRESS_RAW = &H20000000
End Enum
 
' Переменные для хранения внутри экземпляра класса
Dim EntriesInTheCentralDir As Integer
Dim zipCountFiles As Integer
Dim zipCountDirs As Integer
Dim zipListFiles As New Collection
Dim zipListFilesCP866 As New Collection
Dim zipListFilesUTF8 As New Collection
Dim zipFileAttributes As New Collection
Dim zipFileDosDate As New Collection
Dim zipFileDosTime As New Collection
Dim zipFileSize As New Collection
Dim zipFileSizeCompressed As New Collection
Dim zipFileOffSet As New Collection
Dim OpenedZIPFileName As String
 
' Открыть файл ZIP на чтение
Public Function OpenZip(ByVal ZipFileName As String) As Boolean
    Dim hFile As Long
    Dim dwBytesReaded As Long
    Dim nFileSize As Long
    Dim bArray() As Byte
    Dim i As Long
    Dim Signature As Long
    Dim FileName As String
    Dim FileNameCP866 As String
    Dim FileNameUTF8 As String
    Dim OffSet As Long
    Dim FileNameLength As Integer
    Dim LastModFileTime As Integer
    Dim LastModFileDate As Integer
    Dim CompressedSize As Long
    Dim UnCompressedSize As Long
    Dim ExtraFieldLength As Integer
    Dim FileCommentLength As Integer
    Dim ExternalFileAttributes As Long
    Dim nOutputCharLen As Long
    Dim numread As Long
    Dim SetNewPosition As Long
    Dim MajorWindowsVersion As Long
    Dim RelativeOffsetOfLocalHeader As Long
    
    hFile = CreateFileW(StrPtr(ZipFileName), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
    If hFile = 0 Then hFile = CreateFileA(ZipFileName, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
    
    If hFile <> -1 And hFile <> 0 Then
        nFileSize = GetFileSize(hFile, ByVal 0&)
        
        If nFileSize <> -1 Then
            If nFileSize <= MB64 Then ' Если размер файла меньше 64 МБ то читать весь файл
                ReDim bArray(nFileSize - 1)
                ReadFile hFile, VarPtr(bArray(0)), nFileSize, dwBytesReaded, ByVal 0&
            Else ' Размер файла больше 64 МБ
                ReDim bArray(MB64 - 1)
                
                ' Прочитать только последние 64 МБ
                SetNewPosition = nFileSize - MB64
                SetFilePointer hFile, SetNewPosition, ByVal 0&, 1
                ReadFile hFile, VarPtr(bArray(0)), MB64, dwBytesReaded, ByVal 0&
            End If
            
            If dwBytesReaded > 0 Then
                For i = UBound(bArray) - 3 To LBound(bArray) Step -1
                    GetMem4 bArray(i), Signature
                    
                    If Signature = EndOFCentralDirSignature Then
                        Exit For
                    End If
                Next
                
                If i > 0 Then
                    ' Загрузить в переменные данные из файла (я решил не использовать структуры)
                    GetMem2 bArray(i + 10), EntriesInTheCentralDir
                    GetMem4 bArray(i + 16), OffSet
                    
                    If SetNewPosition > 0 Then
                        OffSet = OffSet - SetNewPosition
                    End If
                    
                    GetMem4 ByVal &H7FFE026C, MajorWindowsVersion
                    
                    If zipListFiles.Count > 0 Then Set zipListFiles = Nothing
                    If zipListFilesCP866.Count > 0 Then Set zipListFilesCP866 = Nothing
                    If zipListFilesUTF8.Count > 0 Then Set zipListFilesUTF8 = Nothing
                    If zipFileAttributes.Count > 0 Then Set zipFileAttributes = Nothing
                    If zipFileDosDate.Count > 0 Then Set zipFileDosDate = Nothing
                    If zipFileDosTime.Count > 0 Then Set zipFileDosTime = Nothing
                    If zipFileSize.Count > 0 Then Set zipFileSize = Nothing
                    If zipFileSizeCompressed.Count > 0 Then Set zipFileSizeCompressed = Nothing
                    If zipFileOffSet.Count > 0 Then Set zipFileOffSet = Nothing
                    
                    zipCountFiles = 0
                    zipCountDirs = 0
                    
                    For i = 1 To EntriesInTheCentralDir
                        GetMem4 bArray(OffSet), Signature
                        
                        If Signature = CentralFileHeaderSigniature Then
                            ' Получить всю необходимую информацию о файле
                            GetMem2 bArray(OffSet + 12), LastModFileTime
                            GetMem2 bArray(OffSet + 14), LastModFileDate
                            GetMem4 bArray(OffSet + 20), CompressedSize
                            GetMem4 bArray(OffSet + 24), UnCompressedSize
                            GetMem2 bArray(OffSet + 28), FileNameLength
                            GetMem2 bArray(OffSet + 30), ExtraFieldLength
                            GetMem2 bArray(OffSet + 32), FileCommentLength
                            GetMem4 bArray(OffSet + 38), ExternalFileAttributes
                            GetMem4 bArray(OffSet + 42), RelativeOffsetOfLocalHeader
                            
                            OffSet = OffSet + 46
                            
                            FileName = String$(FileNameLength, vbNullChar)
                            CopyMemory ByVal StrPtr(FileName), bArray(OffSet), FileNameLength
                            
                            OffSet = OffSet + FileNameLength + ExtraFieldLength + FileCommentLength
                            
                            FileNameCP866 = Space$(FileNameLength)
                            FileNameUTF8 = Space$(FileNameLength)
                            
                            nOutputCharLen = MultiByteToWideChar(CP_OEMCP, 0&, StrPtr(FileName), -1, 0&, 0&) ' Получить размер буфера в символах для кодировки DOS
                            MultiByteToWideChar CP_OEMCP, 0&, StrPtr(FileName), -1, StrPtr(FileNameCP866), nOutputCharLen ' Преобразовать кодировки
                            nOutputCharLen = 0
                            nOutputCharLen = MultiByteToWideChar(CP_UTF8, 0&, StrPtr(FileName), -1, 0&, 0&) ' Получить размер буфера в символах для кодировки UTF8
                            MultiByteToWideChar CP_UTF8, 0&, StrPtr(FileName), -1, StrPtr(FileNameUTF8), nOutputCharLen ' Преобразовать кодировки
                            
                            FileNameUTF8 = Left$(FileNameUTF8, nOutputCharLen - 1)
                            FileNameCP866 = Replace$(FileNameCP866, "/", "\")
                            FileNameUTF8 = Replace$(FileNameUTF8, "/", "\")
                            
                            If (ExternalFileAttributes And vbDirectory) <> 0 Then
                                zipCountDirs = zipCountDirs + 1
                            Else
                                zipCountFiles = zipCountFiles + 1
                            End If
                            
                            If MajorWindowsVersion >= 6 And MajorWindowsVersion < 600 Then
                                If FileNameUTF8 Like "*[" & ChrW(-3) & "]*" Then ' Авто-определение кодировок
                                    zipListFiles.Add FileNameCP866 ' Кодировка DOS
                                Else
                                    zipListFiles.Add FileNameUTF8 ' Кодировка UTF8
                                End If
                            Else ' Windows версии меньше чем Vista
                                zipListFiles.Add FileNameCP866 ' Кодировка DOS
                            End If
                            
                            zipListFilesCP866.Add FileNameCP866
                            zipListFilesUTF8.Add FileNameUTF8
                            zipFileAttributes.Add ExternalFileAttributes
                            zipFileDosDate.Add LastModFileDate
                            zipFileDosTime.Add LastModFileTime
                            zipFileSize.Add UnCompressedSize
                            zipFileSizeCompressed.Add CompressedSize
                            zipFileOffSet.Add RelativeOffsetOfLocalHeader
                            
                            If OpenZip = False Then
                                OpenedZIPFileName = ZipFileName
                                OpenZip = True
                            End If
                        End If
                    Next
                End If
            End If
        End If
        
        CloseHandle hFile
    End If
End Function
 
' Возвращает количество файлов и каталогов внутри ZIP
Public Property Get CountFilesAndDirs() As Long
    CountFilesAndDirs = EntriesInTheCentralDir
End Property
 
' Возвращает количество файлов внутри ZIP
Public Property Get CountFiles() As Long
    CountFiles = zipCountFiles
End Property
 
' Возвращает количество каталогов внутри ZIP
Public Property Get CountDirs() As Long
    CountDirs = zipCountDirs
End Property
 
' Возвращает список файлов внутри ZIP, по индексу
Public Property Get List(ByVal Index As Integer, Optional ByVal CodePage As FileNameCodePageInZip) As String
    If zipListFiles.Count > 0 And Index > 0 Then
        If CodePage = zipCodePageAutoDetect Then
            List = zipListFiles(Index)
        ElseIf CodePage = zipCodePageCP866 Then
            List = zipListFilesCP866(Index)
        ElseIf CodePage = zipCodePageUTF8 Then
            List = zipListFilesUTF8(Index)
        End If
    End If
End Property
 
' Возвращает атрибуты файла внутри ZIP, по индексу
Public Property Get FileAttributes(ByVal Index As Integer) As Long
    If zipFileAttributes.Count > 0 And Index > 0 Then
        FileAttributes = zipFileAttributes(Index)
    End If
End Property
 
' Возвращает дату файла внутри ZIP, по индексу
Public Property Get FileDosDate(ByVal Index As Integer) As Integer
    If zipFileDosDate.Count > 0 And Index > 0 Then
        FileDosDate = zipFileDosDate(Index)
    End If
End Property
 
' Возвращает время создания файла внутри ZIP, по индексу
Public Property Get FileDosTime(ByVal Index As Integer) As Integer
    If zipFileDosTime.Count > 0 And Index > 0 Then
        FileDosTime = zipFileDosTime(Index)
    End If
End Property
 
' Возвращает размер файла внутри ZIP, по индексу
Public Property Get FileSize(ByVal Index As Integer) As Long
    If zipFileSize.Count > 0 And Index > 0 Then
        FileSize = zipFileSize(Index)
    End If
End Property
 
' Возвращает размер сжатого блока файла внутри ZIP, по индексу
Public Property Get FileSizeCompressed(ByVal Index As Integer) As Long
    If zipFileSizeCompressed.Count > 0 And Index > 0 Then
        FileSizeCompressed = zipFileSizeCompressed(Index)
    End If
End Property
 
' Возвращает имя открытого файла ZIP
Public Property Get GetOpenedZIPFileName() As String
    GetOpenedZIPFileName = OpenedZIPFileName
End Property
 
' Записывает в массив список файлов из ZIP
Public Function ListFiles(arrFileNames() As String, Optional ByVal CodePage As FileNameCodePageInZip) As Boolean
    Dim i As Integer
    
    If zipListFiles.Count > 0 Then
        ReDim arrFileNames(zipListFiles.Count - 1)
        
        For i = 1 To zipListFiles.Count
            If CodePage = zipCodePageAutoDetect Then
                arrFileNames(i - 1) = zipListFiles(i)
            ElseIf CodePage = zipCodePageCP866 Then
                arrFileNames(i - 1) = zipListFilesCP866(i)
            ElseIf CodePage = zipCodePageUTF8 Then
                arrFileNames(i - 1) = zipListFilesUTF8(i)
            End If
        Next
        
        ListFiles = True
    End If
End Function
 
' Возвращает атрибуты файла внутри ZIP, а так же дату и время создания файлов
Public Property Get GetFileAttributesInZip(ByVal FileNameInZip As String, Optional ByVal AttrInZip As AttributesInZip) As Long
    Dim i As Integer
    
    If zipListFilesCP866.Count > 0 Then
        For i = 1 To zipListFilesCP866.Count
            If zipListFilesCP866(i) = FileNameInZip Then
                GoTo Subroutine
                Exit For
            End If
        Next
    End If
    If zipListFilesUTF8.Count > 0 Then
        For i = 1 To zipListFilesUTF8.Count
            If zipListFilesUTF8(i) = FileNameInZip Then
                GoTo Subroutine
                Exit For
            End If
        Next
    End If
    Exit Property
Subroutine:
    If AttrInZip = zipFileAttr Then
        GetFileAttributesInZip = zipFileAttributes(i)
    ElseIf AttrInZip = zipFileDate Then
        GetFileAttributesInZip = zipFileDosDate(i)
    ElseIf AttrInZip = zipFileTime Then
        GetFileAttributesInZip = zipFileDosTime(i)
    ElseIf AttrInZip = zipFileDateAndTime Then
        GetFileAttributesInZip = ((zipFileDosTime(i) And &H7FFF&) * &H10000) Or (zipFileDosDate(i) And &HFFFF&) Or (&H80000000 And zipFileDosTime(i) < 0)
    End If
End Property
 
' Извлекает выбранный по индексу файл из архива ZIP в буфер байтового массива
Public Function ExtractToMemory(ByVal Index As Integer, bData() As Byte) As Boolean
    If zipFileOffSet.Count > 0 And Index > 0 Then
        If zipFileSizeCompressed(Index) > 32 Then
            If (zipFileAttributes(Index) And vbDirectory) = 0 Then
                Dim hFile As Long
                Dim dwBytesReaded As Long
                Dim ZipFileHeader As zipLocalFileHeader
                Dim bArray() As Byte
                Dim bArrayNew() As Byte
                Dim bytesOut As Long
                Dim h As Long
                Dim i As Byte
                
                hFile = CreateFileW(StrPtr(OpenedZIPFileName), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
                
                If hFile <> -1 And hFile <> 0 Then
                    ReDim bArray(zipFileSizeCompressed(Index) + 1024)
                    
                    SetFilePointer hFile, zipFileOffSet(Index), ByVal 0&, 1
                    ReadFile hFile, VarPtr(bArray(0)), zipFileSizeCompressed(Index) + 1024, dwBytesReaded, ByVal 0&
                    CloseHandle hFile
                    
                    If dwBytesReaded > 0 Then
                        CopyMemory ZipFileHeader, bArray(0), 14
                        CopyMemory ByVal VarPtr(ZipFileHeader) + 16, bArray(14), 14
                        
                        If ZipFileHeader.LocalFileHeaderSignature = LocalFileHeaderSignature Then
                            If ZipFileHeader.CompressedSize = zipFileSizeCompressed(Index) Then
                                If ZipFileHeader.UnCompressedSize = zipFileSize(Index) Then
                                    ' ZipFileHeader.GeneralPurposeBitFlag = 2050 это кодировка UTF8
                                    
                                    ReDim bArrayNew(ZipFileHeader.CompressedSize + 1)
                                    
                                    CopyMemory bArrayNew(0), MSZIPSignature, 2
                                    CopyMemory bArrayNew(2), bArray(30 + ZipFileHeader.FileNameLength + ZipFileHeader.ExtraFieldLength), ZipFileHeader.CompressedSize
                                    
                                    If CreateDecompressor(COMPRESS_ALGORITHM_MSZIP Or COMPRESS_RAW, 0, h) Then
                                        ReDim bData(ZipFileHeader.UnCompressedSize - 1)
                                        If ZipFileHeader.UnCompressedSize <= 32768 Then
                                            Decompress h, bArrayNew(0), UBound(bArrayNew) + 1, bData(0), ZipFileHeader.UnCompressedSize, bytesOut
                                        End If
                                        
                                        If bytesOut Then ExtractToMemory = True
                                        CloseDecompressor h
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    End If
End Function
Миниатюры
Как распаковать файл ZIP функциями из Cabinet.dll или чем отличается ZIP от MSZIP  
Вложения
Тип файла: zip Чтение картинок из ZIP кодом Cabinet.dll (2).zip (719.2 Кб, 3 просмотров)
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.03.2025, 14:56  [ТС]
Если бы каждый блок в ZIP файле помечался бы его размером, было бы гораздо лучше. А ещё лучше чтобы каждый блок так же выдавал информацию о количестве несжатых и сжатых байт внутри одного блока, лучше всего чтобы такая информация была бы в заголовке ZIP. Но такого нет. Я прочитал документацию, единственный случай когда в заголовке блока ZIP написан размер это когда данные несжаты...

Добавлено через 4 минуты
Но учитывая, что блоки начинаются даже не с байта, а с бита, определить границу где вообще заканчивается один блок внутри ЗИП и начинается другой блок, вообще не представляется возможным. Можно прочитать лишь первый блок, но это мало что нам даст, можно лишь достать информацию например финальный это блок или нет, таким образом определить единственный он или нет и можно прочитать ещё например пометку о том что данные несжаты. Это всё что можно. ЗИП очень старый формат и очень неудобный для чтения и распаковки оказался.

Тут больше ничего не придумаешь толком. Вряд ли ты сможешь распаковать файл, размер распакованных данных которого будет превышать 32768 байт... Я склоняюсь к тому что это невозможно...
0
1401 / 860 / 92
Регистрация: 08.02.2017
Сообщений: 3,663
Записей в блоге: 2
10.03.2025, 17:38
Наверное нужно двигаться в эту сторону https://www.cyberforum.ru/blogs/354370/4075.html
Вот есть inflate на asm https://github.com/keirf/amiga... nflate.asm
Я так просто если что, я вооще не знаю как етим пользоваться )
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.03.2025, 17:59  [ТС]
testuser2, так это уже реализовано в классе wqweto, его превзойти мы вряд ли сможем... Единственный минус его класса это огромные EXE - только по этой единственной причине я и затеял поиск других методов...

Добавлено через 7 минут
testuser2, в классе wqweto сохранён как раз таки ассемблерный код который запускается для распаковки зипов, но его реализация занимает слишком много места из-за того что ещё и ассемблерную подпрограмму приходится хранить прямо в коде класса его

Добавлено через 1 минуту
testuser2, кстати его класс работает в VBA? Не знаешь?
0
1401 / 860 / 92
Регистрация: 08.02.2017
Сообщений: 3,663
Записей в блоге: 2
10.03.2025, 18:27
[HackerVlad, ты хочешь сказать, что у него там нативный код загружается в память.. Я особо не разбирался, как он работает, но на vba 86-ом он действительно работал, как я помню без особых переделок.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.03.2025, 19:44  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
ты хочешь сказать, что у него там нативный код загружается в память
А ты разве не смотрел как работает его класс? Да, он загружает в память код ассемблерной подпрограммы из ассемблерной вставки.

Добавлено через 1 минуту
Цитата Сообщение от testuser2 Посмотреть сообщение
но на vba 86-ом он действительно работал
На 64-битном его класс работать не будет конечно...

Добавлено через 1 минуту
На 64 битах можно распаковать через этот новый код до 32 килобайт, а больше 32 килобайт можно распаковать через SHFileOperation с флагом который гасит диалоговое окно!
0
1401 / 860 / 92
Регистрация: 08.02.2017
Сообщений: 3,663
Записей в блоге: 2
11.03.2025, 02:16
Цитата Сообщение от HackerVlad Посмотреть сообщение
А ты разве не смотрел как работает его класс? Да, он загружает в память код ассемблерной подпрограммы из ассемблерной вставки.
Да вот сейчас глянул, там без 100 гр. не разберешься. Похоже инициализация ассемблерной вставки происходит в этих двух функциях (в основном во второй, в первой получаются адреса функций). И вот это вот не понятно, какой еще GetEnvironmentVariable? Все очень загадочно. Я и в принципе-то ни когда не пользовался ассемблерными вставками, а тут такое, поэтому "разве", да..
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Private Function pvInitRelocTable(uRtbl As ZipRelocTableType) As Long
    Dim lpThunk         As Long
    Dim vSplit          As Variant
    
    lpThunk = pvGetThunkAddress()
    vSplit = Split(STR_THUNK_OFFSETS, "|")
    With uRtbl
        .CompressInit = lpThunk + vSplit(zipRelCompressInit)
        .CompressCleanup = lpThunk + vSplit(zipRelCompressCleanup)
        .CompressBlock = lpThunk + vSplit(zipRelCompressBlock)
        .DecompressInit = lpThunk + vSplit(zipRelDecompressInit)
        .DecompressCleanup = lpThunk + vSplit(zipRelDecompressCleanup)
        .DecompressBlock = lpThunk + vSplit(zipRelDecompressBlock)
        .CalcCrc32 = lpThunk + vSplit(zipRelCalcCrc32)
        .MemNonce = lpThunk + vSplit(zipRelMemNonce)
        .MemXor = lpThunk + vSplit(zipRelMemXor)
        .ZipCrypt = lpThunk + vSplit(zipRelZipCrypt)
        .MallocImpl = GetProcAddress(GetModuleHandle(StrPtr("ole32")), "CoTaskMemAlloc")
        .ReallocImpl = GetProcAddress(GetModuleHandle(StrPtr("ole32")), "CoTaskMemRealloc")
        .FreeImpl = GetProcAddress(GetModuleHandle(StrPtr("ole32")), "CoTaskMemFree")
        .LenCodes = lpThunk + vSplit(zipRelLenCodes)
        .DistCodes = lpThunk + vSplit(zipRelDistCodes)
        .MirrorBytes = lpThunk + vSplit(zipRelMirrorBytes)
        .LenLenMap = lpThunk + vSplit(zipRelLenLenMap)
        .Crc32Table = pvGetCrc32Table()
    End With
End Function
 
Private Function pvGetThunkAddress() As Long
    Static lpThunk      As Long
    Dim baThunk()       As Byte
    Dim sBuffer         As String
    
    If lpThunk = 0 Then
        sBuffer = String$(50, 0)
        Call GetEnvironmentVariable(StrPtr("_ZIP_THUNK_" & GetCurrentProcessId() & "_" & STR_THUNK_BUILDDATE), StrPtr(sBuffer), Len(sBuffer) - 1)
        lpThunk = Val(sBuffer)
        If lpThunk = 0 Then
            pvGetThunkData baThunk
            lpThunk = VirtualAlloc(0, UBound(baThunk) + 1, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
            Call CopyMemory(ByVal lpThunk, baThunk(0), UBound(baThunk) + 1)
            Call SetEnvironmentVariable(StrPtr("_ZIP_THUNK_" & GetCurrentProcessId() & "_" & STR_THUNK_BUILDDATE), StrPtr(lpThunk))
        End If
    End If
    pvGetThunkAddress = lpThunk
End Function
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
11.03.2025, 13:03  [ТС]
Ну да, похоже, что его ассемблерный переходник называется "_ZIP_THUNK_"

Добавлено через 6 минут
Цитата Сообщение от testuser2 Посмотреть сообщение
Наверное нужно двигаться в эту сторону
А я считаю что уже всё написано у wqweto и в единственную сторону в которую теперь можно двигаться, это в сторону урезания его класса, чтобы небыли exe такими огромными...

Добавлено через 5 минут
testuser2, я вот когда занимался специально урезанием его класса, то мне удалось урезать со 150 до 82 Кб. 82 килобайт это мой рекорд по урезанию, но я мечтаю ещё больше урезать его класс (но будет только одна распаковка).
0
1401 / 860 / 92
Регистрация: 08.02.2017
Сообщений: 3,663
Записей в блоге: 2
11.03.2025, 13:14
Да, самое главное не отметил это процедура pvGetThunkData.. Кстати, как я смотрю, довольно просто выглядит использование т.н. "вставки", конечно же при наличии кода для такой вставки и знание в ней смещений - выделяется память с помощью VirtualAlloc, копирование туда байт-кода, а далее просто вызов функций из этой области памяти с помощью CallWindowProc. Вместо CallWindowProc можно наверное использовать "трамплин" или "фукции - пустышки" о которых писал The tric в выше упомянутой статье.

Добавлено через 6 минут
Цитата Сообщение от HackerVlad Посмотреть сообщение
я вот когда занимался специально урезанием его класса, то мне удалось урезать со 150 до 82 Кб. 82 килобайт это мой рекорд по урезанию, но я мечтаю ещё больше урезать его класс (но будет только одна распаковка).
Я уже подумал, что можно его асм-код поместить в хвост программы, и вдобавок еще сжать с помощью Compress_NT
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
11.03.2025, 13:47  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
с помощью CallWindowProc
Да, я это тоже сразу заметил)

Цитата Сообщение от testuser2 Посмотреть сообщение
и вдобавок еще сжать с помощью Compress_NT
Я уже спорил с wqweto по поводу того, почему он не сжал хоть чем-нибудь код своей подпрограммы. Он отказался даже после долгих обсуждений, сказал мол хочешь сам делай...

Добавлено через 59 секунд
Ему видимо точно плевать на огромный размер EXE, в отличии от меня...

Добавлено через 1 минуту
Цитата Сообщение от testuser2 Посмотреть сообщение
его асм-код поместить в хвост программы
Я тоже думал об этом, если поместить в ресурсы или в хвост EXE то конечно же тогда будут значительно меньше EXE

Добавлено через 1 минуту
А плюс если ещё сжать (желательно через дельту) тогда размер его ассемблерной вставки будет почти в два раза меньше... Я ему говорил об этом, но он меня не услышал, не захотел он этим заниматься, опять отмахнулся и сказал хочешь сам попробуй...

Добавлено через 1 минуту
Он аргументировал это тем что класс будет тогда работать начиная от XP... Хотя и до этого у него тоже от XP работало... Но теперь он с умным видом сказал мне что будет, вместо всего этого, работать над тем чтобы его класс работал в системах меньше чем XP...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.03.2025, 13:47

Программно распаковать zip файл
Необходимо распаковать MACHINEDATA.TT.ZIP файл. Использовав пример из https://www.cyberforum.ru/vb-net/thread343195-page3.html получился...

Открыть zip архив и распаковать pdf файл с паролем
из zip архива распаковать pdf файл с паролем

Как распаковать файл из архива внутри архива? Ionic.Zip
Всем привет! Пишу программу для распаковки файла &quot;Main.xml&quot; в ZIP архиве &quot;Test2&quot; в ZIP архиве &quot;Test&quot;. Для лучшего понимание...

Как в Access97 распаковать ZIP
Как в Access97 распаковать ZIP? Где взять библиотеку по распаковке Zip-архивов, с примерами на VBA?

Как распаковать Zip архив?
Привет, как можно легко распаковать Zip архив? У меня программа качает архив, но как то должна распаковать его.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
23. что сделано за последнее время.
anaschu 17.06.2026
• Эталон: Клиника НИИ питания РАМН, Москва — централизованный пищеблок, 225 коек, 180 пациентов • Git: репозиторий med2, ветка абсентеизм. Рабочий файл: СРесурсами1_v4. alp • Смежный проект:. . .
22. Подключение слоя системной динамики (потоковые диффуры): экономические метрики модели
anaschu 17.06.2026
Апдейт модели: финансовый контур, разделение затрат Продолжаю развивать модель рабочего коллектива на AnyLogic. В этот раз работа шла над агентом Экономика — финансовым SD-слоем модели. Задача:. . .
[golang] Insert Delete GetRandom O(1) (Leetcode: 380)
alhaos 16.06.2026
Insert Delete GetRandom O(1) Сложность: Medium Источник: LeetCode 380 Задача Реализовать структуру данных RandomizedSet, которая поддерживает следующие операции за O(1) в среднем:
Свет в конце тоннеля
kumehtar 16.06.2026
Поймал себя на одной мысли. Раньше мне всегда казалось неправильным жить без чёткого понимания, куда всё идёт. Будто я иду по дороге судьбы, но не знаю, куда она ведёт. А раз не знаю — значит,. . .
[golang] Реализация стека с поддержкой получения минимального элемента за O(1)
alhaos 16.06.2026
Min Stack Сложность: Medium Источник: LeetCode 155 Задача: Реализовать стек который поддерживает push, pop, top и получение минимального элемента за O(1). Методы:
[golang] Конкурентный fetcher с ограничением максимального количества одновременных HTTP запросов.
alhaos 10.06.2026
Задача Реализовать конкурентный fetcher с ограничением максимального количества одновременных HTTP запросов. Сигнатура func Fetch(urls string, maxConcurrent int) Result Пример urls :=. . .
[golang] Состояние гонки (race condition)
alhaos 10.06.2026
Состояние гонки (race condition) Состояние гонки (Race Condition) — это ошибка, возникающая при одновременном доступе нескольких горутин к одним и тем же данным без должной синхронизации. При этом. . .
Взрослые отношения, и почему они не получаются
kumehtar 09.06.2026
Когда в детстве ребёнок не получает от родителей чего-то важного, он лишается не просто приятных переживаний, а основы для формирования определённых внутренних качеств и навыков. Если ребёнок не. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru