loader.txt updated
This commit is contained in:
+26
-65
@@ -2,16 +2,8 @@ This documentation is written for those brave souls who want to
|
|||||||
understand and/or modify the UPX assembly stubs - the small snippets
|
understand and/or modify the UPX assembly stubs - the small snippets
|
||||||
that do the runtime decompression when a compressed program is started.
|
that do the runtime decompression when a compressed program is started.
|
||||||
|
|
||||||
So, how the runtime stub/loader generation works?
|
If you look at the C++ source files, you can find code fragments like
|
||||||
|
this:
|
||||||
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:
|
|
||||||
|
|
||||||
addLoader("PEMAIN20",
|
addLoader("PEMAIN20",
|
||||||
ih.entry ? "PEDOJUMP" : "PERETURN",
|
ih.entry ? "PEDOJUMP" : "PERETURN",
|
||||||
@@ -19,71 +11,40 @@ in the following way:
|
|||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
Basically that's all you have to know: when you want to add a section
|
linker->defineSymbol("original_entry", ih.entry);
|
||||||
of assembly code to the runtime loader, you just write
|
|
||||||
|
|
||||||
l_foo.asm
|
and in the assembly files fragments like this:
|
||||||
---------
|
|
||||||
;__FOOBAR00__
|
|
||||||
|
|
||||||
xor eax, eax
|
section PEISDLL1
|
||||||
label1:
|
cmpb [esp + 8], 1
|
||||||
jmps label1
|
jnz reloc_end_jmp
|
||||||
|
|
||||||
;__FOOBARZZ__
|
section PEMAIN21
|
||||||
|
reloc_end_jmp:
|
||||||
|
|
||||||
p_foo.cpp
|
section PERETURN
|
||||||
---------
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
ret 0x0C
|
||||||
|
section PEDOJUMP
|
||||||
|
jmp original_entry
|
||||||
|
|
||||||
addLoader("FOOBAR00", NULL);
|
Everything works as you would expect. If you want to add the code
|
||||||
|
fragment which is in `section PERETURN' to the runtime stub, then
|
||||||
This will add the assembly section starting from __FOOBAR00__ and ending
|
simply use `addLoader("PERETURN")' in the C++ source.
|
||||||
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
|
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
|
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
|
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
|
loader using `addLoader()' and the rest is done by upx. It will resolve
|
||||||
every conditional or unconditional jumps or subrutine calls for you.
|
every conditional or unconditional jumps or subroutine calls for you.
|
||||||
|
|
||||||
This functionality (we could say it's a simple linker) is achived by the
|
You can also use (undefined) symbols in the assembly for values that
|
||||||
assembly preprocessor (src/stub/scripts/app.pl) and a little C++ module
|
can only be computed during compression time (like `original_entry').
|
||||||
(src/linker.cpp). And of course NASM - the Netwide Assembler. You can
|
These symbols can be defined later in C++ using
|
||||||
see what's going on behind the scenes - just do:
|
|
||||||
|
|
||||||
cd src/stubs
|
linker->defineSymbol("xx", yy)
|
||||||
make maintainer-clean
|
|
||||||
make all
|
|
||||||
|
|
||||||
This will rebuild all the loaders - and keep the temporary files (*.as[xy])
|
This functionality (we could say it's a simple linker) is achived by
|
||||||
which are seen by the assembler.
|
compiling the assembly into an ELF object file which a little C++
|
||||||
|
module (src/linker.cpp) can interpret and work with.
|
||||||
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.
|
|
||||||
|
|||||||
+1
-1
@@ -116,7 +116,7 @@ void PackCom::patchLoader(OutputFile *fo,
|
|||||||
linker->defineSymbol("bytes_to_copy", ph.c_len + lsize);
|
linker->defineSymbol("bytes_to_copy", ph.c_len + lsize);
|
||||||
linker->defineSymbol("copy_source", ph.c_len + lsize + 0x100);
|
linker->defineSymbol("copy_source", ph.c_len + lsize + 0x100);
|
||||||
linker->defineSymbol("copy_destination", upper_end);
|
linker->defineSymbol("copy_destination", upper_end);
|
||||||
linker->defineSymbol("NRV2B160", ph.u_len + ph.overlap_overhead);
|
linker->defineSymbol("COMCUTPO", ph.u_len + ph.overlap_overhead);
|
||||||
|
|
||||||
linker->relocate();
|
linker->relocate();
|
||||||
loader = getLoader();
|
loader = getLoader();
|
||||||
|
|||||||
Reference in New Issue
Block a user