Skip to content

Commit 8f3601e

Browse files
armijnhemelfolkertdev
authored andcommitted
add test case for files with extra data in between the last local file
header and the first central directory header
1 parent c4a7bef commit 8f3601e

3 files changed

Lines changed: 337 additions & 0 deletions

File tree

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
Section 4.3.6 specifies the layout of a ZIP file:
2+
3+
```
4+
4.3.6 Overall .ZIP file format:
5+
6+
[local file header 1]
7+
[encryption header 1]
8+
[file data 1]
9+
[data descriptor 1]
10+
.
11+
.
12+
.
13+
[local file header n]
14+
[encryption header n]
15+
[file data n]
16+
[data descriptor n]
17+
[archive decryption header]
18+
[archive extra data record]
19+
[central directory header 1]
20+
.
21+
.
22+
.
23+
[central directory header n]
24+
[zip64 end of central directory record]
25+
[zip64 end of central directory locator]
26+
[end of central directory record]
27+
```
28+
29+
According to this layout there can be no layout between the last local file
30+
header and the first central directory header, yet there are many files in
31+
which this happens. As an example, Android packages store a signing block right
32+
after the last local file header:
33+
34+
<https://source.android.com/docs/security/features/apksigning/v2>
35+
36+
Although this is not allowed APK files can still be unpacked, as programs use
37+
the central directory to find the offsets to each individual file and
38+
effectively skip the extra data. None of the regular ZIP programs seem to be
39+
able to extract this extra data.
40+
41+
To create a file with extra data only one field needs to be adapted (not
42+
tested for ZIP64 files) in the "end of central directory" (section 4.3.16),
43+
namely:
44+
45+
```
46+
offset of start of central directory with respect to the starting disk number
47+
```
48+
49+
The file `test_with_extra_data_before_central_directory.zip` is a modified
50+
version of `test.zip` with an addition 1024 bytes added in between the last
51+
local file header and the first central directory header. This means that the
52+
central directory is moved an additional 1024 bytes. This can be shown by
53+
comparing the output of `hexdump -C` for both files:
54+
55+
The position of the central directory in the original file is `ba 03`:
56+
57+
```
58+
00000470 00 00 ba 03 00 00 1a 00 54 68 69 73 20 69 73 20 |........This is |
59+
```
60+
61+
In the new file the central directory has been moved 1024 bytes and is now
62+
`ba 07`:
63+
64+
```
65+
00000870 00 00 ba 07 00 00 1a 00 54 68 69 73 20 69 73 20 |........This is |
66+
```
2.14 KB
Binary file not shown.
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
---
2+
source: ziplinter/src/lib.rs
3+
expression: result
4+
---
5+
{
6+
"comment": "This is a zipfile comment.",
7+
"contents": [
8+
{
9+
"central": {
10+
"comment": "",
11+
"compressed_size": 25,
12+
"crc32": 3287144384,
13+
"creator_version": {
14+
"host_system": "Unix",
15+
"version": 30
16+
},
17+
"disk_nbr_start": 0,
18+
"external_attrs": 2175008768,
19+
"extra": [
20+
85,
21+
84,
22+
5,
23+
0,
24+
3,
25+
113,
26+
252,
27+
130,
28+
76,
29+
117,
30+
120,
31+
11,
32+
0,
33+
1,
34+
4,
35+
245,
36+
1,
37+
0,
38+
0,
39+
4,
40+
20,
41+
0,
42+
0,
43+
0
44+
],
45+
"flags": 0,
46+
"header_offset": 0,
47+
"internal_attrs": 1,
48+
"method": "Deflate",
49+
"mode": 420,
50+
"modified": "2010-09-05T02:12:01Z",
51+
"name": "test.txt",
52+
"reader_version": {
53+
"host_system": "MsDos",
54+
"version": 20
55+
},
56+
"uncompressed_size": 26
57+
},
58+
"local": {
59+
"accessed": null,
60+
"compressed_size": 25,
61+
"crc32": 3287144384,
62+
"created": null,
63+
"extra": [
64+
85,
65+
84,
66+
9,
67+
0,
68+
3,
69+
113,
70+
252,
71+
130,
72+
76,
73+
118,
74+
252,
75+
130,
76+
76,
77+
117,
78+
120,
79+
11,
80+
0,
81+
1,
82+
4,
83+
245,
84+
1,
85+
0,
86+
0,
87+
4,
88+
20,
89+
0,
90+
0,
91+
0
92+
],
93+
"flags": 0,
94+
"gid": 501,
95+
"header_offset": 0,
96+
"method": "Deflate",
97+
"method_specific": "None",
98+
"mode": 0,
99+
"modified": "2010-09-05T02:12:01Z",
100+
"name": "test.txt",
101+
"reader_version": {
102+
"host_system": "MsDos",
103+
"version": 20
104+
},
105+
"uid": 501,
106+
"uncompressed_size": 26
107+
}
108+
},
109+
{
110+
"central": {
111+
"comment": "",
112+
"compressed_size": 785,
113+
"crc32": 1423258110,
114+
"creator_version": {
115+
"host_system": "Unix",
116+
"version": 30
117+
},
118+
"disk_nbr_start": 0,
119+
"external_attrs": 2175008768,
120+
"extra": [
121+
85,
122+
84,
123+
5,
124+
0,
125+
3,
126+
58,
127+
48,
128+
131,
129+
76,
130+
117,
131+
120,
132+
11,
133+
0,
134+
1,
135+
4,
136+
245,
137+
1,
138+
0,
139+
0,
140+
4,
141+
20,
142+
0,
143+
0,
144+
0
145+
],
146+
"flags": 0,
147+
"header_offset": 91,
148+
"internal_attrs": 0,
149+
"method": "Store",
150+
"mode": 420,
151+
"modified": "2010-09-05T05:52:58Z",
152+
"name": "gophercolor16x16.png",
153+
"reader_version": {
154+
"host_system": "MsDos",
155+
"version": 10
156+
},
157+
"uncompressed_size": 785
158+
},
159+
"local": {
160+
"accessed": null,
161+
"compressed_size": 785,
162+
"crc32": 1423258110,
163+
"created": null,
164+
"extra": [
165+
85,
166+
84,
167+
9,
168+
0,
169+
3,
170+
58,
171+
48,
172+
131,
173+
76,
174+
59,
175+
48,
176+
131,
177+
76,
178+
117,
179+
120,
180+
11,
181+
0,
182+
1,
183+
4,
184+
245,
185+
1,
186+
0,
187+
0,
188+
4,
189+
20,
190+
0,
191+
0,
192+
0
193+
],
194+
"flags": 0,
195+
"gid": 501,
196+
"header_offset": 0,
197+
"method": "Store",
198+
"method_specific": "None",
199+
"mode": 0,
200+
"modified": "2010-09-05T05:52:58Z",
201+
"name": "gophercolor16x16.png",
202+
"reader_version": {
203+
"host_system": "MsDos",
204+
"version": 10
205+
},
206+
"uid": 501,
207+
"uncompressed_size": 785
208+
}
209+
}
210+
],
211+
"encoding": "Utf8",
212+
"eocd": {
213+
"dir": {
214+
"inner": {
215+
"dir_disk_nbr": 0,
216+
"dir_records_this_disk": 2,
217+
"directory_offset": 1978,
218+
"directory_records": 2,
219+
"directory_size": 168,
220+
"disk_nbr": 0
221+
},
222+
"offset": 2146
223+
},
224+
"dir64": null,
225+
"global_offset": 0
226+
},
227+
"parsed_ranges": [
228+
{
229+
"contains": "end of central directory record",
230+
"end": 2194,
231+
"start": 2146
232+
},
233+
{
234+
"contains": "central directory header",
235+
"end": 2056,
236+
"filename": "test.txt",
237+
"start": 1978
238+
},
239+
{
240+
"contains": "central directory header",
241+
"end": 2146,
242+
"filename": "gophercolor16x16.png",
243+
"start": 2056
244+
},
245+
{
246+
"contains": "local file header",
247+
"end": 66,
248+
"filename": "test.txt",
249+
"start": 0
250+
},
251+
{
252+
"contains": "file data",
253+
"end": 91,
254+
"filename": "test.txt",
255+
"start": 66
256+
},
257+
{
258+
"contains": "local file header",
259+
"end": 169,
260+
"filename": "gophercolor16x16.png",
261+
"start": 91
262+
},
263+
{
264+
"contains": "file data",
265+
"end": 954,
266+
"filename": "gophercolor16x16.png",
267+
"start": 169
268+
}
269+
],
270+
"size": 2194
271+
}

0 commit comments

Comments
 (0)