1 /* packer.h --
2 
3    This file is part of the UPX executable compressor.
4 
5    Copyright (C) 1996-2020 Markus Franz Xaver Johannes Oberhumer
6    Copyright (C) 1996-2020 Laszlo Molnar
7    All Rights Reserved.
8 
9    UPX and the UCL library are free software; you can redistribute them
10    and/or modify them under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2 of
12    the License, or (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; see the file COPYING.
21    If not, write to the Free Software Foundation, Inc.,
22    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24    Markus F.X.J. Oberhumer              Laszlo Molnar
25    <markus@oberhumer.com>               <ezerotven+github@gmail.com>
26  */
27 
28 
29 #ifndef __UPX_PACKER_H
30 #define __UPX_PACKER_H 1
31 
32 #include "mem.h"
33 
34 class InputFile;
35 class OutputFile;
36 class Packer;
37 class PackMaster;
38 class UiPacker;
39 class Filter;
40 
41 
42 /*************************************************************************
43 //
44 **************************************************************************/
45 
46 // see stub/src/include/header.S
47 class PackHeader
48 {
49     friend class Packer;
50 
51 private:
52     // these are strictly private to Packer and not accessible in subclasses:
53     PackHeader();
54 
55     void putPackHeader(upx_bytep p);
56     bool fillPackHeader(const upx_bytep b, int blen);
57 
58 public:
59     int getPackHeaderSize() const;
60 
61 public:
62     // fields stored in compressed file
63     //enum { magic = UPX_MAGIC_LE32 };
64     int version;
65     int format;                 // executable format
66     int method;                 // compresison method
67     int level;                  // compresison level 1..10
68     unsigned u_len;
69     unsigned c_len;
70     unsigned u_adler;
71     unsigned c_adler;
72     off_t u_file_size;
73     int filter;
74     int filter_cto;
75     int n_mru;                  // FIXME: rename to filter_misc
76     int header_checksum;
77 
78     // support fields for verifying decompression
79     unsigned saved_u_adler;
80     unsigned saved_c_adler;
81 
82     // info fields set by fillPackHeader()
83     unsigned buf_offset;
84 
85     // info fields set by Packer::compress()
86     upx_compress_result_t compress_result;
87     //unsigned min_offset_found;
88     unsigned max_offset_found;
89     //unsigned min_match_found;
90     unsigned max_match_found;
91     //unsigned min_run_found;
92     unsigned max_run_found;
93     unsigned first_offset_found;
94     //unsigned same_match_offsets_found;
95 
96     // info fields set by Packer::compressWithFilters()
97     unsigned overlap_overhead;
98 };
99 
100 
101 bool ph_skipVerify(const PackHeader &ph);
102 void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out,
103                    bool verify_checksum, Filter *ft);
104 bool ph_testOverlappingDecompression(const PackHeader &ph, const upx_bytep buf,
105                                      unsigned overlap_overhead);
106 
107 
108 /*************************************************************************
109 // abstract base class for packers
110 //
111 // FIXME: this class is way too fat and badly needs a decomposition
112 **************************************************************************/
113 
114 class Packer
115 {
116     //friend class PackMaster;
117     friend class UiPacker;
118 protected:
119     Packer(InputFile *f);
120 public:
121     virtual ~Packer();
122     virtual void assertPacker() const;
123 
124     virtual int getVersion() const = 0;
125     // A unique integer ID for this executable format. See conf.h.
126     virtual int getFormat() const = 0;
127     virtual const char *getName() const = 0;
128     virtual const char *getFullName(const options_t *) const = 0;
129     virtual const int *getCompressionMethods(int method, int level) const = 0;
130     virtual const int *getFilters() const = 0;
131 
132     // PackMaster entries
133     void initPackHeader();
134     void updatePackHeader();
135     void doPack(OutputFile *fo);
136     void doUnpack(OutputFile *fo);
137     void doTest();
138     void doList();
139     void doFileInfo();
140 
141     // unpacker capabilities
canUnpackVersion(int version)142     virtual bool canUnpackVersion(int version) const
143         { return (version >= 8); }
canUnpackFormat(int format)144     virtual bool canUnpackFormat(int format) const
145         { return (format == getFormat()); }
146 
147 protected:
148     // unpacker tests - these may throw exceptions
149     virtual bool testUnpackVersion(int version) const;
150     virtual bool testUnpackFormat(int format) const;
151 
152 protected:
153     // implementation
154     virtual void pack(OutputFile *fo) = 0;
155     virtual void unpack(OutputFile *fo) = 0;
156     virtual void test();
157     virtual void list();
158     virtual void fileInfo();
159 
160 public:
161     // canPack() should throw a cantPackException eplaining why it
162     // cannot pack a recognized format.
163     // canUnpack() can return -1 meaning "format recognized, but file
164     // is definitely not packed" (see packmast.cpp).
165     virtual bool canPack() = 0;
166     virtual int canUnpack() = 0;
canTest()167     virtual int canTest() { return canUnpack(); }
canList()168     virtual int canList() { return canUnpack(); }
169 
170 protected:
171     // main compression drivers
172     virtual bool compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
173                           const upx_compress_config_t *cconf = NULL);
174     virtual void decompress(const upx_bytep in, upx_bytep out,
175                             bool verify_checksum = true, Filter *ft = NULL);
176     virtual bool checkDefaultCompressionRatio(unsigned u_len, unsigned c_len) const;
177     virtual bool checkCompressionRatio(unsigned u_len, unsigned c_len) const;
178     virtual bool checkFinalCompressionRatio(const OutputFile *fo) const;
179 
180     // high-level compression drivers
181     void compressWithFilters(Filter *ft,
182                              const unsigned overlap_range,
183                              const upx_compress_config_t *cconf,
184                              int filter_strategy = 0,
185                              bool inhibit_compression_check = false);
186     void compressWithFilters(Filter *ft,
187                              const unsigned overlap_range,
188                              const upx_compress_config_t *cconf,
189                              int filter_strategy,
190                              unsigned filter_buf_off,
191                              unsigned compress_ibuf_off,
192                              unsigned compress_obuf_off,
193                              const upx_bytep hdr_ptr, unsigned hdr_len,
194                              bool inhibit_compression_check = false);
195     // real compression driver
196     void compressWithFilters(upx_bytep i_ptr, unsigned i_len,
197                              upx_bytep o_ptr,
198                              upx_bytep f_ptr, unsigned f_len,
199                              const upx_bytep hdr_ptr, unsigned hdr_len,
200                              Filter *ft,
201                              const unsigned overlap_range,
202                              const upx_compress_config_t *cconf,
203                              int filter_strategy,
204                              bool inhibit_compression_check = false);
205 
206     // util for verifying overlapping decompresion
207     //   non-destructive test
208     virtual bool testOverlappingDecompression(const upx_bytep buf,
209                                               const upx_bytep tbuf,
210                                               unsigned overlap_overhead) const;
211     //   non-destructive find
212     virtual unsigned findOverlapOverhead(const upx_bytep buf,
213                                          const upx_bytep tbuf,
214                                          unsigned range = 0,
215                                          unsigned upper_limit = ~0u) const;
216     //   destructive decompress + verify
217     void verifyOverlappingDecompression(Filter *ft = NULL);
218     void verifyOverlappingDecompression(upx_bytep o_ptr, unsigned o_size, Filter *ft = NULL);
219 
220     // packheader handling
221     virtual int patchPackHeader(void *b, int blen);
222     virtual bool getPackHeader(void *b, int blen, bool allow_incompressible=false);
223     virtual bool readPackHeader(int len, bool allow_incompressible=false);
224     virtual void checkAlreadyPacked(const void *b, int blen);
225 
226     // loader core
227     virtual void buildLoader(const Filter *ft) = 0;
228     virtual Linker* newLinker() const = 0;
229     virtual void relocateLoader();
230     // loader util for linker
231     virtual upx_byte *getLoader() const;
232     virtual int getLoaderSize() const;
233     virtual void initLoader(const void *pdata, int plen, int small=-1);
234 #define C const char *
235     void addLoader(C); void addLoader(C,C); void addLoader(C,C,C);
236     void addLoader(C,C,C,C); void addLoader(C,C,C,C,C);
237     void addLoader(C,C,C,C,C,C); void addLoader(C,C,C,C,C,C,C);
238     void addLoader(C,C,C,C,C,C,C,C); void addLoader(C,C,C,C,C,C,C,C,C);
239     void addLoader(C,C,C,C,C,C,C,C,C,C);
240 #undef C
241 #if 0 && (ACC_CC_CLANG || (ACC_CC_GNUC >= 0x040100))
242     void __acc_cdecl_va addLoaderVA(const char *s, ...) __attribute__((__sentinel__));
243 #else
244     void __acc_cdecl_va addLoaderVA(const char *s, ...);
245 #endif
246     virtual bool hasLoaderSection(const char *name) const;
247     virtual int getLoaderSection(const char *name, int *slen=NULL) const;
248     virtual int getLoaderSectionStart(const char *name, int *slen=NULL) const;
249 
250     // compression handling [see packer_c.cpp]
251 public:
252     static bool isValidCompressionMethod(int method);
253 protected:
254     const int *getDefaultCompressionMethods_8(int method, int level, int small=-1) const;
255     const int *getDefaultCompressionMethods_le32(int method, int level, int small=-1) const;
256     virtual const char *getDecompressorSections() const;
257     virtual unsigned getDecompressorWrkmemSize() const;
258     virtual void defineDecompressorSymbols();
259 
260     // filter handling [see packer_f.cpp]
261     virtual bool isValidFilter(int filter_id) const;
optimizeFilter(Filter *,const upx_byte *,unsigned)262     virtual void optimizeFilter(Filter *, const upx_byte *, unsigned) const { }
263     virtual void addFilter32(int filter_id);
264     virtual void defineFilterSymbols(const Filter *ft);
265 
266     // stub and overlay util
267     static void handleStub(InputFile *fi, OutputFile *fo, unsigned size);
268     virtual void checkOverlay(unsigned overlay);
269     virtual void copyOverlay(OutputFile *fo, unsigned overlay,
270                              MemBuffer *buf, bool do_seek=true);
271 
272     // misc util
273     virtual unsigned getRandomId() const;
274 
275     // patch util
276     int patch_be16(void *b, int blen, unsigned old, unsigned new_);
277     int patch_be16(void *b, int blen, const void * old, unsigned new_);
278     int patch_be32(void *b, int blen, unsigned old, unsigned new_);
279     int patch_be32(void *b, int blen, const void * old, unsigned new_);
280     int patch_le16(void *b, int blen, unsigned old, unsigned new_);
281     int patch_le16(void *b, int blen, const void * old, unsigned new_);
282     int patch_le32(void *b, int blen, unsigned old, unsigned new_);
283     int patch_le32(void *b, int blen, const void * old, unsigned new_);
284     void checkPatch(void *b, int blen, int boff, int size);
285 
286     // relocation util
287     static upx_byte *optimizeReloc(upx_byte *in,unsigned relocnum,upx_byte *out,upx_byte *image,int bs,int *big, int bits);
288     static unsigned unoptimizeReloc(upx_byte **in,upx_byte *image,MemBuffer *out,int bs, int bits);
289     static upx_byte *optimizeReloc32(upx_byte *in,unsigned relocnum,upx_byte *out,upx_byte *image,int bs,int *big);
290     static unsigned unoptimizeReloc32(upx_byte **in,upx_byte *image,MemBuffer *out,int bs);
291     static upx_byte *optimizeReloc64(upx_byte *in,unsigned relocnum,upx_byte *out,upx_byte *image,int bs,int *big);
292     static unsigned unoptimizeReloc64(upx_byte **in,upx_byte *image,MemBuffer *out,int bs);
293 
294     // target endianness abstraction
get_te16(const void * p)295     unsigned get_te16(const void *p)       const { return bele->get16(p); }
get_te32(const void * p)296     unsigned get_te32(const void *p)       const { return bele->get32(p); }
get_te64(const void * p)297     upx_uint64_t get_te64(const void *p)   const { return bele->get64(p); }
set_te16(void * p,unsigned v)298     void set_te16(void *p, unsigned v)     const { bele->set16(p, v); }
set_te32(void * p,unsigned v)299     void set_te32(void *p, unsigned v)     const { bele->set32(p, v); }
set_te64(void * p,upx_uint64_t v)300     void set_te64(void *p, upx_uint64_t v) const { bele->set64(p, v); }
301 
302 protected:
303     const N_BELE_RTP::AbstractPolicy *bele; // target endianness
304     InputFile *fi;
305     off_t file_size;        // will get set by constructor
306     PackHeader ph;          // must be filled by canUnpack()
307     int ph_format;
308     int ph_version;
309 
310     // compression buffers
311     MemBuffer ibuf;         // input
312     MemBuffer obuf;         // output
313 
314     // UI handler
315     UiPacker *uip;
316 
317     // linker
318     Linker *linker;
319 
320 private:
321     // private to checkPatch()
322     void *last_patch;
323     int last_patch_len;
324     int last_patch_off;
325 
326 private:
327     // disable copy and assignment
328     Packer(const Packer &); // {}
329     Packer& operator= (const Packer &); // { return *this; }
330 };
331 
332 
333 #endif /* already included */
334 
335 /* vim:set ts=4 sw=4 et: */
336