[Android] Fwd: [UPX] android shared objects without UPX
Rafaël Carré
funman at videolan.org
Fri Jul 20 12:39:07 CEST 2012
Hi guys, still working on compressing the .so :
12277208 libvlcjni.so
6336200 libvlcjni.so.gz # gzip -9
6277310 libvlcjni.so.bz2 # bzip2
5034493 libvlcjni.so.7z # 7z
5026124 libvlcjni.so.xz # xz
4954633 libvlcjni.so.paq8 # zpaq : 43 seconds to decompress on Core2Duo
2.26Ghz
I didn't test yet but I expect the size of the decompressor to be well
below 100K.
http://www.7-zip.org/sdk.html has public domain 7z decompressor in Java,
C, asm etc...
We could either use /data/data/something as temporary storage and delete
the decompressed .so on exit, or leave it there permanently (and just
decrease the size of download without effect on internal storage).
I expect /tmp to be noexec like /sdcard but I didn't try yet.
Using RAM storage would be perfect to decompress libvlcjni.so
-------- Message original --------
Date: Thu, 19 Jul 2012 15:24:21 -0700
From: John Reiser <jreiser at bitwagon.com>
Hi Rafaël,
So, taking a more global view than just how to involve UPX:
You should consider this strategy, too, for constructing
compressed shared objects for android (or any other environment
which has dlopen):
1. Build the usual.so in the normal way.
2. Build an impostor .so using some compression of the whole
usual.so file, then arrange supply the uncompressed usual.so
by "whole file" decompression and dlopen() at runtime.
I will use gzip/zlib fpr an example because it has a
subroutine API zlib.h. Other compression will work as long
as there is a subroutine API to compress and uncompress arrays
(instead of files.)
Compress the input file usual.so, which generates the
output file usual.so.gz: gzip usual.so
Compile the usual.so.gz file into a data array:
----- cpr_usual.S
cpr_usual_begin: .global cpr_usual_begin
.incbin "usual.so.gz"
cpr_usual_end: .globl cpr_usual_end
-----
Build another shared library "impostor.so" with an
empty main() function: "main() {}"
and an initializer function (DT_INIT function)
which uses the zlib subroutine API
to decompress the cpr_usual_begin[] array, and write the
de-compressed usual.so into a file such as /tmp/usual.so.
Then the initializer function calls dlopen("/tmp/usual.so", ...);
(A more refined initializer function can check for /tmp/usual.so
existing already, etc.)
3. Link client programs with usual.so first, to be sure that
there are no undefined external symbols.
4. In the runtime environment, replace /usr/lib/usual.so
with impostor.so .
In most cases the client won't care about the "middle man"
impostor.so, as long as the symbols get resolved by the
dlopen()ed /tmp/usual.so. This ignores runtime name conflicts
(two different definitions of the same symbol name, with the
result depending on the search order). This also does not work
if the client cares too much about which library satisfies the
request for an external symbol. (There are some tricks to play
with DT_SONAME, but an overly-paranoid client might be unhappy.)
There is some messiness with the file /tmp/usual.so.
There is some messiness with multiple simultaneous clients.
But this gives you a different approach which you can try now,
instead of waiting for UPX. You can also try compressors that
UPX does not offer, such as xz (although "upx --lzma" ought to be
very close to xz).
--
John Reiser
More information about the Android
mailing list