diff options
Diffstat (limited to 'Build/source/libs/zziplib/docs/sfx-make.htm')
-rw-r--r-- | Build/source/libs/zziplib/docs/sfx-make.htm | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/Build/source/libs/zziplib/docs/sfx-make.htm b/Build/source/libs/zziplib/docs/sfx-make.htm new file mode 100644 index 00000000000..5e092e47a11 --- /dev/null +++ b/Build/source/libs/zziplib/docs/sfx-make.htm @@ -0,0 +1,167 @@ +<section> <date> February 2003 </date> +<h2> SFX-Make </h2> combining an EXE with a ZIP archive + +<!--border--> + +<section> +<h3> How To </h3> +<P> + In this section we walk you through the steps of combining an EXE + with a ZIP archive. The basic scheme goes like this: the final + file will have an EXE starting at offset null, followed by the + data entries of a ZIP archive. The <em>last</em> part of the ZIP + archive is the ZIP central-directory which ends at the end of the file. +</P> +<P> + The basic problem lies in the fact that the zip central-directory + entries reference their data section with an offset from the + start-of-file so that you can not just append a zip archive after + an exe stub. The trick goes like adding the EXE as the first data + part of the ZIP archive - so that the offsets for each entry will + be correct when we are finished with it. +</P> +<P> + Again, one can not just use a zip tool to put the EXE as the first + part - since each data part is preceded with an infoblock of a + few bytes. The data of the first data part will therefore not + start at offset zero. We solve this problem with moving the data + a few bytes later - so that the final file will not start with a + "PK" magic (from the zip info header) but with an "MZ" or "ELF" + magic (from the exe info header). +</P> + +</section><section> +<h3> Step 1: Creating The Zip Combination </h3> +<P> + Choose your exe file (example.exe) and wrap that file into a + zip container - ensure that the zip tool does <em>not</em> + use any compression algorithm on the data. This is usually + done with saying "zero compression level" as an option to + the zip tool. Also note that <em>no other</em> file is + wrapped as some zip tools reorder the entries from the + order on the command line to alphabetic order. Here is an + example with infozip's `zip` (e.g. on linux): + <pre> zip -0 -j example.zip example.exe </pre> +</P> +<P> + There is no zip tool that would reorder the data entries in + an existing zip archive. This mode is used here - the real + compressed data entries can now be added to the existing + zip archive that currently just wraps the exe part. With + specifying maximum compression ("-9" = compression level 9) + and throwing away any subdirectory part ("-j" = junk path) + it might look like + <pre> zip -9 -j example.zip data/* </pre> +</P> +<P> + Now we need to move the exe part by a few bytes to the + real start of the file. This can be done as easily as + writing the exe file again on to the start of the file. + However, one can not just use a shell-direction or + copy-operation since that would truncate (!!) the zip + file to the length of the exe part. The overwrite-operation + must be done without truncation. For maximum OS independence + the zziplib ships with a little tool in "test/zzipsetstub.c" + that you can reuse for this task: + <pre> zzipsetstub example.zip example.exe </pre> +</P> +<P> + This is it - the `unzip` tool can still access all data + entries but the first EXE - the first EXE will be listed + in the central-directory of the ZIP archive but one can + not extract the data since the "PK" magic at offset null + has been overwritten with the EXE magic. The data of all + the other entries can still be extracted with a normal + `unzip` tool - or any tool from the zziplib be used for + the same task. +</P> + +</section><section> +<h3> Step 2: Accessing The Data From The Program </h3> + +<P> + There is an example in test/zzipself.c that show how to do + it. The OS will provide each program with its own name in + argv[0] of the main() routine. This program file (!!) is + also the zip archive that carries the compressed data + entries along. Therefore, we can just issue a zzip_opendir + on argv[0] to access the zip central-directory. +</P> +<P> + Likewise one can open a file within it by just prepending + the string argv[0] to the filename stem, i.e. you could + do like + <pre> ZZIP_FILE* f = zzip_fopen ("example.exe/start.gif", "rbi")</pre> +</P><P> + however you are advised to use the _ext_io cousin to be + platform independet - different Operating Systems use + different file extensions for executables, it's not always + an ".exe". +</P> +<P> + Once the file is opened, the data can be zzip_fread or + passed through an SDL_rwops structure into the inner + parts of your program. +</P> + +</section><section> +<h3> Step 3: Using Obfuscation Along </h3> + +<P> + The next level uses obfuscatation on the data part of the + application. That way there is no visible data to be seen + from outside, it looks like it had been compiled right into + the C source part. One can furthermore confuse a possible + attacker with staticlinking the zziplib into the executable + (this is possible in a limited set of conditions). +</P> +<P> + The first pass is again in creating the zip - here we must + ensure that only the ZIP archive part is obfuscated but + the EXE part must be plain data so that the operationg + system can read and relocate it into main memory. Using + xor-obfuscation this is easy - applying xor twice will + yield the original data. The steps look like this now: + <pre> + zzipxorcopy example.exe example.xor + zip -0 application.zip example.xor + zip -9 application.zip data/* + zzipsetstub application.zip example.xor + zzipxorcopy application.zip application.exe + </pre> +</P> +<P> + In the second step the open-routine in your application + needs to be modified - there are quite some examples in + the zziplib that show you how to add an xor-read routine + and passing it in the "io"-part of an zzip_open_ext_io + routine (see zzipxorcat.c). + <pre> + static int xor_value = 0x55; + + static zzip_ssize_t xor_read (int f, void* p, zzip_size_t l) + { + zzip_ssize_t r = read(f, p, l); + zzip_ssize_t x; char* q; for (x=0, q=p; x < r; x++) q[x] ^= xor_value; + return r; + } + + static struct zzip_plugin_io xor_handlers; + static zzip_strings_t xor_fileext[] = { ".exe", ".EXE", "", 0 }; + + main(...) + { + zzip_init_io (&xor_handlers, 0); xor_handlers.read = &xor_read; + + ZZIP_FILE* fp = zzip_open_ext_io (filename, + O_RDONLY|O_BINARY, ZZIP_CASELESS|ZZIP_ONLYZIP, + xor_fileext, &xor_handlers); + .... + </pre> +</P> +<P> + You may want to pick your own xor-value instead of the default 0x55, + the zziplib-shipped tool `zzipxorcopy` does know an option to just + set the xor-value with which to obfuscate the data. +</P> +</section></section> |