mirror of
https://github.com/upx/upx.git
synced 2024-11-30 08:00:39 +00:00
90 lines
3.3 KiB
Plaintext
90 lines
3.3 KiB
Plaintext
This documentation was written for those brave souls who want to
|
|
understand and/or modify the UPX assembly stubs - the small snippets
|
|
that do the runtime decompression when a compressed program is started.
|
|
|
|
So, how the runtime stub/loader generation works?
|
|
|
|
You might have already noticed that for some file formats the loaders
|
|
are quite simple (linux/i386 & tos) while in the other cases the
|
|
loaders look very suspicious: they're full of `%ifdef's and contain
|
|
loads of cryptic comments like `__PERELOC2__'.
|
|
|
|
If you look at the C++ source files, however you can notice that these
|
|
comment strings (without the leading and trailing underscores) are used
|
|
in the following way (they are all 8 character length strings):
|
|
|
|
addLoader("PEMAIN20",
|
|
ih.entry ? "PEDOJUMP" : "PERETURN",
|
|
"IDENTSTR""UPX1HEAD",
|
|
NULL
|
|
);
|
|
|
|
Basically that's all you have to know: when you want to add a section
|
|
of assembly code to the runtime loader, you just write
|
|
|
|
l_foo.asm
|
|
---------
|
|
;__FOOBAR00__
|
|
|
|
xor eax, eax
|
|
label1:
|
|
jmps label1
|
|
|
|
;__FOOBARZZ__
|
|
|
|
p_foo.cpp
|
|
---------
|
|
|
|
addLoader("FOOBAR00", NULL);
|
|
|
|
This will add the assembly section starting from __FOOBAR00__ and ending
|
|
before __FOOBARZZ__ to the loader. You can add an %ifdef - %endif pair
|
|
before these comments if you wish - but these conditionals will NOT be
|
|
seen by the assembler, they are just syntactic sugar to make the code a
|
|
little bit more readable and understandable. (Note however, that only
|
|
%ifdefs which are started on the 1st column are removed by the upx
|
|
assembly preprocessor program, so you can still use preprocessor
|
|
conditionals if you wish - just write them starting from the 2nd
|
|
column.)
|
|
|
|
That's nice, you could say, but how cross section jumps and calls are
|
|
handled? Well, that is the nicest part of this stuff - they are handled
|
|
automatically. All you have to do is to add the required sections to the
|
|
loader using `addLoader()' and the rest is done by upx. It will resolve
|
|
every conditional or unconditional jumps or subrutine calls for you.
|
|
|
|
This functionality (we could say it's a simple linker) is achived by the
|
|
assembly preprocessor (src/stub/scripts/app.pl) and a little C++ module
|
|
(src/linker.cpp). And of course NASM - the Netwide Assembler. You can
|
|
see what's going on behind the scenes - just do:
|
|
|
|
cd src/stubs
|
|
make maintainer-clean
|
|
make all
|
|
|
|
This will rebuild all the loaders - and keep the temporary files (*.as[xy])
|
|
which are seen by the assembler.
|
|
|
|
Currently this loader/stub building method only works with ix86
|
|
assembly - both app.pl and linker.cpp heavily rely on this when dealing
|
|
with cross section references.
|
|
|
|
And finally some important features/requirements you should be aware of:
|
|
|
|
- as previously stated - preprocessor conditionals starting on the 1st
|
|
column are removed by app.pl
|
|
- sections are separated by comments in the form `;__X1234567__'
|
|
- jumps are recognized by searching for a word which starts with `j'
|
|
and followed by a label - this also means that `jmp short label1'
|
|
will NOT be recognized (but you can use a macro called `jmps' for it
|
|
by adding `%define jmps jmp short' to the beginning of the file)
|
|
- at the end of the file you need something like this
|
|
|
|
eof:
|
|
; __XTHEENDX__
|
|
section .data
|
|
dd -1
|
|
dw eof
|
|
|
|
That's all for now.
|