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