void Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum) { initFilter(this, buf_, buf_len_); const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id); if (fe == NULL) throwInternalError("unfilter-1"); if (fe->id == 0) return; if (buf_len < fe->min_buf_len) return; if (fe->max_buf_len && buf_len > fe->max_buf_len) return; if (!fe->do_unfilter) throwInternalError("unfilter-2"); //printf("unfilter: %02x %p %d\n", this->id, this->buf, this->buf_len); int r = (*fe->do_unfilter)(this); //printf("unfilter: %02x %d\n", fe->id, r); if (r != 0) throwInternalError("unfilter-3"); //OutputFile::dump("unfilter.dat", buf, buf_len); // verify checksum if (verify_checksum && clevel != 1) { if (this->adler != upx_adler32(this->buf, this->buf_len)) throwInternalError("unfilter-4"); } }
bool Filter::scan(const upx_byte *buf_, unsigned buf_len_) { // Note: must use const_cast here. This is fine as the scan // implementations (fe->do_scan) actually don't change the buffer. upx_byte *b = const_cast<upx_byte *>(buf_); initFilter(this, b, buf_len_); const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id); if (fe == NULL) throwInternalError("scan-1"); if (fe->id == 0) return true; if (buf_len < fe->min_buf_len) return false; if (fe->max_buf_len && buf_len > fe->max_buf_len) return false; if (!fe->do_scan) throwInternalError("scan-2"); //printf("filter: %02x %p %d\n", this->id, this->buf, this->buf_len); int r = (*fe->do_scan)(this); //printf("filter: %02x %d\n", fe->id, r); if (r > 0) throwFilterException(); if (r == 0) return true; return false; }
void setupSkypeFrameWork(JNIEnv *env) { currentEnv = env; if (XInitThreads() == 0) { throwInternalError(env, "Xlib don't support multi-threads."); return; } _display = XOpenDisplay(NULL); if (_display == NULL) { throwInternalError(env, "Opening the diplay failed."); return; } _screen = DefaultScreen(_display); _desktop = XRootWindow(_display, _screen); _dummyWindow = XCreateSimpleWindow(_display, _desktop, 0, 0, 1, 1, 0, BlackPixel(_display, _screen), BlackPixel(_display, _screen)); _skypeInstanceAtom = XInternAtom(_display, "_SKYPE_INSTANCE", False); _skypeControlApiMessageBeginAtom = XInternAtom(_display, "SKYPECONTROLAPI_MESSAGE_BEGIN", False); _skypeControlApiMessageAtom = XInternAtom(_display, "SKYPECONTROLAPI_MESSAGE", False); _stopEventLoopAtom = XInternAtom(_display, "_STOP_EVENT_LOOP", False); _windowNameAtom = XInternAtom(_display, "WM_NAME", True); _dispatching = True; }
bool Filter::filter(upx_byte *buf_, unsigned buf_len_) { initFilter(this, buf_, buf_len_); const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id); if (fe == NULL) throwInternalError("filter-1"); if (fe->id == 0) return true; if (buf_len < fe->min_buf_len) return false; if (fe->max_buf_len && buf_len > fe->max_buf_len) return false; if (!fe->do_filter) throwInternalError("filter-2"); // save checksum this->adler = 0; if (clevel != 1) this->adler = upx_adler32(this->buf, this->buf_len); //printf("filter: %02x %p %d\n", this->id, this->buf, this->buf_len); //OutputFile::dump("filter.dat", buf, buf_len); int r = (*fe->do_filter)(this); //printf("filter: %02x %d\n", fe->id, r); if (r > 0) throwFilterException(); if (r == 0) return true; return false; }
int PackHeader::getPackHeaderSize() const { if (format < 0 || version < 0) throwInternalError("getPackHeaderSize"); int n = 0; if (version <= 3) n = 24; else if (version <= 9) { if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) n = 20; else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) n = 25; else n = 28; } else { if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) n = 22; else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) n = 27; else n = 32; } if (n < 20) throwCantUnpack("unknown header version"); return n; }
int upx_ucl_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb_parm, int method, int level, const upx_compress_config_t *cconf_parm, upx_compress_result_t *cresult ) { int r; assert(level > 0); assert(cresult != NULL); COMPILE_TIME_ASSERT(sizeof(ucl_compress_config_t) == sizeof(REAL_ucl_compress_config_t)) ucl_progress_callback_t cb; cb.callback = 0; cb.user = NULL; if (cb_parm && cb_parm->nprogress) { cb.callback = wrap_nprogress_ucl; cb.user = cb_parm; } ucl_compress_config_t cconf; cconf.reset(); if (cconf_parm) memcpy(&cconf, &cconf_parm->conf_ucl, sizeof(cconf)); // cconf = cconf_parm->conf_ucl; // struct copy ucl_uint *res = cresult->result_ucl.result; // assume no info available - fill in worst case results //res[0] = 1; // min_offset_found - NOT USED res[1] = src_len - 1; // max_offset_found //res[2] = 2; // min_match_found - NOT USED res[3] = src_len - 1; // max_match_found //res[4] = 1; // min_run_found - NOT USED res[5] = src_len; // max_run_found res[6] = 1; // first_offset_found //res[7] = 999999; // same_match_offsets_found - NOT USED // prepare bit-buffer settings cconf.bb_endian = 0; cconf.bb_size = 0; if (method >= M_NRV2B_LE32 && method <= M_NRV2E_LE16) { static const unsigned char sizes[3] = {32, 8, 16}; cconf.bb_size = sizes[(method - M_NRV2B_LE32) % 3]; } else { throwInternalError("unknown compression method"); return UPX_E_ERROR; } // optimize compression parms if (level <= 3 && cconf.max_offset == UCL_UINT_MAX) cconf.max_offset = 8*1024-1; else if (level == 4 && cconf.max_offset == UCL_UINT_MAX) cconf.max_offset = 32*1024-1; if M_IS_NRV2B(method) r = ucl_nrv2b_99_compress(src, src_len, dst, dst_len, &cb, level, &cconf, res); else if M_IS_NRV2D(method)
const wchar* AvmplusHostContext::readFileForEval(const wchar* basename, const wchar* filename, uint32_t* inputlen) { // FIXME: the mismatch between what eval needs and what the core API delivers is just stunning. if (nextstring == sizeof(strings)/sizeof(strings[0])) throwInternalError("includes too deeply nested"); StUTF16String str(core->readFileForEval(core->newStringUTF16(basename), core->newStringUTF16(filename))); // return value is already NUL-terminated wchar *s = new wchar[str.length()]; VMPI_memcpy(s, str.c_str(), str.length()*sizeof(wchar)); *inputlen = str.length(); strings[nextstring++] = s; return s; }
int upx_test_overlap ( const upx_bytep buf, const upx_bytep tbuf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, const upx_compress_result_t *cresult ) { int r = UPX_E_ERROR; if (cresult && cresult->method == 0) cresult = NULL; assert(*dst_len > 0); assert(src_len < *dst_len); // must be compressed unsigned overlap_overhead = src_off + src_len - *dst_len; assert((int)overlap_overhead > 0); if (0) { } #if (WITH_LZMA) else if (M_IS_LZMA(method)) r = upx_lzma_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult); #endif #if (WITH_NRV) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_nrv_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult); #endif #if (WITH_UCL) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_ucl_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult); #endif else { throwInternalError("unknown decompression method"); } return r; }
int upx_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, const upx_compress_result_t *cresult ) { int r = UPX_E_ERROR; assert(*dst_len > 0); assert(src_len < *dst_len); // must be compressed if (cresult && cresult->method == 0) cresult = NULL; if (0) { } #if (WITH_LZMA) else if (M_IS_LZMA(method)) r = upx_lzma_decompress(src, src_len, dst, dst_len, method, cresult); #endif #if (WITH_NRV) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_nrv_decompress(src, src_len, dst, dst_len, method, cresult); #endif #if (WITH_UCL) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_ucl_decompress(src, src_len, dst, dst_len, method, cresult); #endif #if (WITH_ZLIB) else if (M_IS_DEFLATE(method)) r = upx_zlib_decompress(src, src_len, dst, dst_len, method, cresult); #endif else { throwInternalError("unknown decompression method"); } return r; }
void PackHeader::putPackHeader(upx_bytep p) { assert(get_le32(p) == UPX_MAGIC_LE32); if (get_le32(p+4) != UPX_MAGIC2_LE32) { //fprintf(stderr, "MAGIC2_LE32: %x %x\n", get_le32(p+4), UPX_MAGIC2_LE32); throwBadLoader(); } int size = 0; int old_chksum = 0; // the new variable length header if (format < 128) { if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) { size = 22; old_chksum = get_packheader_checksum(p, size - 1); set_le16(p+16,u_len); set_le16(p+18,c_len); p[20] = (unsigned char) filter; } else if (format == UPX_F_DOS_EXE) { size = 27; old_chksum = get_packheader_checksum(p, size - 1); set_le24(p+16,u_len); set_le24(p+19,c_len); set_le24(p+22,u_file_size); p[25] = (unsigned char) filter; } else if (format == UPX_F_DOS_EXEH) { throwInternalError("invalid format"); } else { size = 32; old_chksum = get_packheader_checksum(p, size - 1); set_le32(p+16,u_len); set_le32(p+20,c_len); set_le32(p+24,u_file_size); p[28] = (unsigned char) filter; p[29] = (unsigned char) filter_cto; assert(n_mru == 0 || (n_mru >= 2 && n_mru <= 256)); p[30] = (unsigned char) (n_mru ? n_mru - 1 : 0); } set_le32(p+8,u_adler); set_le32(p+12,c_adler); } else { size = 32; old_chksum = get_packheader_checksum(p, size - 1); set_be32(p+8,u_len); set_be32(p+12,c_len); set_be32(p+16,u_adler); set_be32(p+20,c_adler); set_be32(p+24,u_file_size); p[28] = (unsigned char) filter; p[29] = (unsigned char) filter_cto; assert(n_mru == 0 || (n_mru >= 2 && n_mru <= 256)); p[30] = (unsigned char) (n_mru ? n_mru - 1 : 0); } p[4] = (unsigned char) version; p[5] = (unsigned char) format; p[6] = (unsigned char) method; p[7] = (unsigned char) level; // header_checksum assert(size == getPackHeaderSize()); // check old header_checksum if (p[size - 1] != 0) { if (p[size - 1] != old_chksum) { //printf("old_checksum: %d %d\n", p[size - 1], old_chksum); throwBadLoader(); } } // store new header_checksum p[size - 1] = get_packheader_checksum(p, size - 1); }
void do_one_file(const char *iname, char *oname) { int r; struct stat st; memset(&st, 0, sizeof(st)); #if (HAVE_LSTAT) r = lstat(iname, &st); #else r = stat(iname, &st); #endif if (r != 0) { if (errno == ENOENT) throw FileNotFoundException(iname, errno); else throwIOException(iname, errno); } if (!(S_ISREG(st.st_mode))) throwIOException("not a regular file -- skipped"); #if defined(__unix__) // no special bits may be set if ((st.st_mode & (S_ISUID | S_ISGID | S_ISVTX)) != 0) throwIOException("file has special permissions -- skipped"); #endif if (st.st_size <= 0) throwIOException("empty file -- skipped"); if (st.st_size < 512) throwIOException("file is too small -- skipped"); if (!mem_size_valid_bytes(st.st_size)) throwIOException("file is too large -- skipped"); if ((st.st_mode & S_IWUSR) == 0) { bool skip = true; if (opt->output_name) skip = false; else if (opt->to_stdout) skip = false; else if (opt->backup) skip = false; if (skip) throwIOException("file is write protected -- skipped"); } InputFile fi; fi.st = st; fi.sopen(iname, O_RDONLY | O_BINARY, SH_DENYWR); #if (USE_FTIME) struct ftime fi_ftime; memset(&fi_ftime, 0, sizeof(fi_ftime)); if (opt->preserve_timestamp) { if (getftime(fi.getFd(), &fi_ftime) != 0) throwIOException("cannot determine file timestamp"); } #endif // open output file OutputFile fo; if (opt->cmd == CMD_COMPRESS || opt->cmd == CMD_DECOMPRESS) { if (opt->to_stdout) { if (!fo.openStdout(1, opt->force ? true : false)) throwIOException("data not written to a terminal; Use '-f' to force."); } else { char tname[ACC_FN_PATH_MAX+1]; if (opt->output_name) strcpy(tname,opt->output_name); else { if (!maketempname(tname, sizeof(tname), iname, ".upx")) throwIOException("could not create a temporary file name"); } if (opt->force >= 2) { #if (HAVE_CHMOD) r = chmod(tname, 0777); IGNORE_ERROR(r); #endif r = unlink(tname); IGNORE_ERROR(r); } int flags = O_CREAT | O_WRONLY | O_BINARY; if (opt->force) flags |= O_TRUNC; else flags |= O_EXCL; int shmode = SH_DENYWR; #if defined(__MINT__) flags |= O_TRUNC; shmode = O_DENYRW; #endif // cannot rely on open() because of umask //int omode = st.st_mode | 0600; int omode = 0600; if (!opt->preserve_mode) omode = 0666; fo.sopen(tname,flags,shmode,omode); // open succeeded - now set oname[] strcpy(oname,tname); } } // handle command PackMaster pm(&fi, opt); if (opt->cmd == CMD_COMPRESS) pm.pack(&fo); else if (opt->cmd == CMD_DECOMPRESS) pm.unpack(&fo); else if (opt->cmd == CMD_TEST) pm.test(); else if (opt->cmd == CMD_LIST) pm.list(); else if (opt->cmd == CMD_FILEINFO) pm.fileInfo(); else throwInternalError("invalid command"); // copy time stamp if (opt->preserve_timestamp && oname[0] && fo.isOpen()) { #if (USE_FTIME) r = setftime(fo.getFd(), &fi_ftime); IGNORE_ERROR(r); #elif (USE__FUTIME) struct _utimbuf u; u.actime = st.st_atime; u.modtime = st.st_mtime; r = _futime(fo.getFd(), &u); IGNORE_ERROR(r); #endif } // close files fo.closex(); fi.closex(); // rename or delete files if (oname[0] && !opt->output_name) { // FIXME: .exe or .cof etc. if (!opt->backup) { #if (HAVE_CHMOD) r = chmod(iname, 0777); IGNORE_ERROR(r); #endif File::unlink(iname); } else { // make backup char bakname[ACC_FN_PATH_MAX+1]; if (!makebakname(bakname, sizeof(bakname), iname)) throwIOException("could not create a backup file name"); File::rename(iname,bakname); } File::rename(oname,iname); } // copy file attributes if (oname[0]) { oname[0] = 0; const char *name = opt->output_name ? opt->output_name : iname; UNUSED(name); #if (USE_UTIME) // copy time stamp if (opt->preserve_timestamp) { struct utimbuf u; u.actime = st.st_atime; u.modtime = st.st_mtime; r = utime(name, &u); IGNORE_ERROR(r); } #endif #if (HAVE_CHMOD) // copy permissions if (opt->preserve_mode) { r = chmod(name, st.st_mode); IGNORE_ERROR(r); } #endif #if (HAVE_CHOWN) // copy the ownership if (opt->preserve_ownership) { r = chown(name, st.st_uid, st.st_gid); IGNORE_ERROR(r); } #endif } UiPacker::uiConfirmUpdate(); }
void throwBadLoader() { throwInternalError("bad loader"); }
void PackUnix::packExtent( const Extent &x, unsigned &total_in, unsigned &total_out, Filter *ft, OutputFile *fo, unsigned hdr_u_len ) { unsigned const init_u_adler = ph.u_adler; unsigned const init_c_adler = ph.c_adler; MemBuffer hdr_ibuf; if (hdr_u_len) { hdr_ibuf.alloc(hdr_u_len); fi->seek(0, SEEK_SET); int l = fi->readx(hdr_ibuf, hdr_u_len); (void)l; } fi->seek(x.offset, SEEK_SET); for (off_t rest = x.size; 0 != rest; ) { int const filter_strategy = ft ? getStrategy(*ft) : 0; int l = fi->readx(ibuf, UPX_MIN(rest, (off_t)blocksize)); if (l == 0) { break; } rest -= l; // Note: compression for a block can fail if the // file is e.g. blocksize + 1 bytes long // compress ph.c_len = ph.u_len = l; ph.overlap_overhead = 0; unsigned end_u_adler = 0; if (ft) { // compressWithFilters() updates u_adler _inside_ compress(); // that is, AFTER filtering. We want BEFORE filtering, // so that decompression checks the end-to-end checksum. end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler); ft->buf_len = l; // compressWithFilters() requirements? ph.filter = 0; ph.filter_cto = 0; ft->id = 0; ft->cto = 0; compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy, 0, 0, 0, hdr_ibuf, hdr_u_len); } else { (void) compress(ibuf, ph.u_len, obuf); // ignore return value } if (ph.c_len < ph.u_len) { const upx_bytep tbuf = NULL; if (ft == NULL || ft->id == 0) tbuf = ibuf; ph.overlap_overhead = OVERHEAD; if (!testOverlappingDecompression(obuf, tbuf, ph.overlap_overhead)) { // not in-place compressible ph.c_len = ph.u_len; } } if (ph.c_len >= ph.u_len) { // block is not compressible ph.c_len = ph.u_len; memcpy(obuf, ibuf, ph.c_len); // must update checksum of compressed data ph.c_adler = upx_adler32(ibuf, ph.u_len, ph.saved_c_adler); } // write block sizes b_info tmp; if (hdr_u_len) { unsigned hdr_c_len = 0; MemBuffer hdr_obuf; hdr_obuf.allocForCompression(hdr_u_len); int r = upx_compress(hdr_ibuf, hdr_u_len, hdr_obuf, &hdr_c_len, 0, ph.method, 10, NULL, NULL); if (r != UPX_E_OK) throwInternalError("header compression failed"); if (hdr_c_len >= hdr_u_len) throwInternalError("header compression size increase"); ph.saved_u_adler = upx_adler32(hdr_ibuf, hdr_u_len, init_u_adler); ph.saved_c_adler = upx_adler32(hdr_obuf, hdr_c_len, init_c_adler); ph.u_adler = upx_adler32(ibuf, ph.u_len, ph.saved_u_adler); ph.c_adler = upx_adler32(obuf, ph.c_len, ph.saved_c_adler); end_u_adler = ph.u_adler; memset(&tmp, 0, sizeof(tmp)); set_te32(&tmp.sz_unc, hdr_u_len); set_te32(&tmp.sz_cpr, hdr_c_len); tmp.b_method = (unsigned char) ph.method; fo->write(&tmp, sizeof(tmp)); b_len += sizeof(b_info); fo->write(hdr_obuf, hdr_c_len); total_out += hdr_c_len; total_in += hdr_u_len; hdr_u_len = 0; // compress hdr one time only } memset(&tmp, 0, sizeof(tmp)); set_te32(&tmp.sz_unc, ph.u_len); set_te32(&tmp.sz_cpr, ph.c_len); if (ph.c_len < ph.u_len) { tmp.b_method = (unsigned char) ph.method; if (ft) { tmp.b_ftid = (unsigned char) ft->id; tmp.b_cto8 = ft->cto; } } fo->write(&tmp, sizeof(tmp)); b_len += sizeof(b_info); if (ft) { ph.u_adler = end_u_adler; } // write compressed data if (ph.c_len < ph.u_len) { fo->write(obuf, ph.c_len); // Checks ph.u_adler after decompression, after unfiltering verifyOverlappingDecompression(ft); } else { fo->write(ibuf, ph.u_len); } total_in += ph.u_len; total_out += ph.c_len; } }
static jfieldID getFieldReference (JNIEnv * env, jobject field, const char *type) { jclass classClass; jclass fieldClass; jclass declaringClass; jclass typeClass; jfieldID fid; const char *field_name; const char *type_name; int type_len; jmethodID mid; jstring name; jstring tname; int i; fieldClass = (*env)->GetObjectClass (env, field); mid = (*env)->GetMethodID (env, fieldClass, "getName", "()Ljava/lang/String;"); if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL) { throwInternalError (env); return NULL; } name = (*env)->CallObjectMethod (env, field, mid); field_name = (*env)->GetStringUTFChars (env, name, NULL); mid = (*env)->GetMethodID (env, fieldClass, "getDeclaringClass", "()Ljava/lang/Class;"); if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL) { throwInternalError (env); return NULL; } declaringClass = (*env)->CallObjectMethod (env, field, mid); /* Do we need to find out the exact type descriptor of the field? */ if (type == NULL) { char *the_type; mid = (*env)->GetMethodID (env, fieldClass, "getType", "()Ljava/lang/Class;"); if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL) { throwInternalError (env); return NULL; } typeClass = (*env)->CallObjectMethod (env, field, mid); classClass = (*env)->FindClass (env, "java/lang/Class"); mid = (*env)->GetMethodID (env, classClass, "getName", "()Ljava/lang/String;"); if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL) { throwInternalError (env); return NULL; } tname = (*env)->CallObjectMethod (env, typeClass, mid); type_name = (*env)->GetStringUTFChars (env, tname, NULL); /* * If it isn't an array class then the actual field type descriptor * starts with 'L', ends with ';' and has '/' instead of '.'. */ type_len = strlen (type_name); if (type_name[0] != '[') { /* XXX - FIXME - should not use dynamic allocation in core lib. */ the_type = (char *) malloc (type_len + 3); the_type[0] = 'L'; the_type[type_len + 1] = ';'; the_type[type_len + 2] = '\0'; the_type++; } else { /* XXX - FIXME - should not use dynamic allocation in core lib. */ the_type = (char *) malloc (type_len + 1); the_type[type_len] = '\0'; } for (i = 0; i < type_len; i++) if (type_name[i] == '.') the_type[i] = '/'; else the_type[i] = type_name[i]; if (type_name[0] != '[') the_type--; (*env)->ReleaseStringUTFChars (env, tname, type_name); fid = (*env)->GetFieldID (env, declaringClass, field_name, the_type); free (the_type); } else { type_len = -1; fid = (*env)->GetFieldID (env, declaringClass, field_name, type); } if (fid == NULL) { throwInternalError (env); return NULL; } (*env)->ReleaseStringUTFChars (env, name, field_name); return fid; }
int upx_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb, int method, int level, const upx_compress_config_t *cconf, upx_compress_result_t *cresult ) { int r = UPX_E_ERROR; upx_compress_result_t cresult_buffer; assert(method > 0); assert(level > 0); #if 1 // set available bytes in dst if (*dst_len == 0) *dst_len = MemBuffer::getSizeForCompression(src_len); #else // force users to provide *dst_len assert(*dst_len != 0); #endif // for UPX, we always require a reasonably sized outbut buffer assert(*dst_len >= MemBuffer::getSizeForCompression(src_len)); if (!cresult) cresult = &cresult_buffer; memset(cresult, 0, sizeof(*cresult)); #if 1 // debug cresult->method = method; cresult->level = level; cresult->u_len = src_len; cresult->c_len = 0; #endif if (0) { } #if (WITH_LZMA) else if (M_IS_LZMA(method)) r = upx_lzma_compress(src, src_len, dst, dst_len, cb, method, level, cconf, cresult); #endif #if (WITH_NRV) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_nrv_compress(src, src_len, dst, dst_len, cb, method, level, cconf, cresult); #endif #if (WITH_UCL) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_ucl_compress(src, src_len, dst, dst_len, cb, method, level, cconf, cresult); #endif else { throwInternalError("unknown compression method"); } #if 1 // debug cresult->c_len = *dst_len; #endif return r; }
void PackArmPe::pack(OutputFile *fo) { // FIXME: we need to think about better support for --exact if (opt->exact) throwCantPackExact(); const unsigned objs = ih.objects; isection = new pe_section_t[objs]; fi->seek(pe_offset+sizeof(ih),SEEK_SET); fi->readx(isection,sizeof(pe_section_t)*objs); rvamin = isection[0].vaddr; infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs); // check the PE header // FIXME: add more checks if (!opt->force && ( (ih.cpu != 0x1c0 && ih.cpu != 0x1c2) || (ih.opthdrsize != 0xe0) || ((ih.flags & EXECUTABLE) == 0) || (ih.subsystem != 9) || (ih.entry == 0 /*&& !isdll*/) || (ih.ddirsentries != 16) // || IDSIZE(PEDIR_EXCEPTION) // is this used on arm? // || IDSIZE(PEDIR_COPYRIGHT) )) throwCantPack("unexpected value in PE header (try --force)"); if (IDSIZE(PEDIR_SEC)) IDSIZE(PEDIR_SEC) = IDADDR(PEDIR_SEC) = 0; // throwCantPack("compressing certificate info is not supported"); if (IDSIZE(PEDIR_COMRT)) throwCantPack(".NET files (win32/net) are not yet supported"); if (isdll) opt->win32_pe.strip_relocs = false; else if (opt->win32_pe.strip_relocs < 0) opt->win32_pe.strip_relocs = (ih.imagebase >= 0x10000); if (opt->win32_pe.strip_relocs) { if (ih.imagebase < 0x10000) throwCantPack("--strip-relocs is not allowed when imagebase < 0x10000"); else ih.flags |= RELOCS_STRIPPED; } if (memcmp(isection[0].name,"UPX",3) == 0) throwAlreadyPackedByUPX(); if (!opt->force && IDSIZE(15)) throwCantPack("file is possibly packed/protected (try --force)"); if (ih.entry && ih.entry < rvamin) throwCantPack("run a virus scanner on this file!"); if (!opt->force && ih.subsystem == 1) throwCantPack("subsystem 'native' is not supported (try --force)"); if (ih.filealign < 0x200) throwCantPack("filealign < 0x200 is not yet supported"); handleStub(fi,fo,pe_offset); const unsigned usize = ih.imagesize; const unsigned xtrasize = UPX_MAX(ih.datasize, 65536u) + IDSIZE(PEDIR_IMPORT) + IDSIZE(PEDIR_BOUNDIM) + IDSIZE(PEDIR_IAT) + IDSIZE(PEDIR_DELAYIMP) + IDSIZE(PEDIR_RELOC); ibuf.alloc(usize + xtrasize); // BOUND IMPORT support. FIXME: is this ok? fi->seek(0,SEEK_SET); fi->readx(ibuf,isection[0].rawdataptr); Interval holes(ibuf); unsigned ic,jc,overlaystart = 0; ibuf.clear(0, usize); for (ic = jc = 0; ic < objs; ic++) { if (isection[ic].rawdataptr && overlaystart < isection[ic].rawdataptr + isection[ic].size) overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign); if (isection[ic].vsize == 0) isection[ic].vsize = isection[ic].size; if ((isection[ic].flags & PEFL_BSS) || isection[ic].rawdataptr == 0 || (isection[ic].flags & PEFL_INFO)) { holes.add(isection[ic].vaddr,isection[ic].vsize); continue; } if (isection[ic].vaddr + isection[ic].size > usize) throwCantPack("section size problem"); if (((isection[ic].flags & (PEFL_WRITE|PEFL_SHARED)) == (PEFL_WRITE|PEFL_SHARED))) if (!opt->force) throwCantPack("writable shared sections not supported (try --force)"); if (jc && isection[ic].rawdataptr - jc > ih.filealign) throwCantPack("superfluous data between sections"); fi->seek(isection[ic].rawdataptr,SEEK_SET); jc = isection[ic].size; if (jc > isection[ic].vsize) jc = isection[ic].vsize; if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs? jc = isection[ic].vsize = isection[ic].size; if (isection[ic].vaddr + jc > ibuf.getSize()) throwInternalError("buffer too small 1"); fi->readx(ibuf + isection[ic].vaddr,jc); jc += isection[ic].rawdataptr; } // check for NeoLite if (find(ibuf + ih.entry, 64+7, "NeoLite", 7) >= 0) throwCantPack("file is already compressed with another packer"); unsigned overlay = file_size - stripDebug(overlaystart); if (overlay >= (unsigned) file_size) { #if 0 if (overlay < file_size + ih.filealign) overlay = 0; else if (!opt->force) throwNotCompressible("overlay problem (try --force)"); #endif overlay = 0; } checkOverlay(overlay); Resource res; Interval tlsiv(ibuf); Export xport((char*)(unsigned char*)ibuf); const unsigned dllstrings = processImports(); processTls(&tlsiv); // call before processRelocs!! processResources(&res); processExports(&xport); processRelocs(); //OutputFile::dump("x1", ibuf, usize); // some checks for broken linkers - disable filter if necessary bool allow_filter = true; if (ih.codebase == ih.database || ih.codebase + ih.codesize > ih.imagesize || (isection[virta2objnum(ih.codebase,isection,objs)].flags & PEFL_CODE) == 0) allow_filter = false; const unsigned oam1 = ih.objectalign - 1; // FIXME: disabled: the uncompressor would not allocate enough memory //objs = tryremove(IDADDR(PEDIR_RELOC),objs); // FIXME: if the last object has a bss then this won't work // newvsize = (isection[objs-1].vaddr + isection[objs-1].size + oam1) &~ oam1; // temporary solution: unsigned newvsize = (isection[objs-1].vaddr + isection[objs-1].vsize + oam1) &~ oam1; //fprintf(stderr,"newvsize=%x objs=%d\n",newvsize,objs); if (newvsize + soimport + sorelocs > ibuf.getSize()) throwInternalError("buffer too small 2"); memcpy(ibuf+newvsize,oimport,soimport); memcpy(ibuf+newvsize+soimport,orelocs,sorelocs); cimports = newvsize - rvamin; // rva of preprocessed imports crelocs = cimports + soimport; // rva of preprocessed fixups ph.u_len = newvsize + soimport + sorelocs; // some extra data for uncompression support unsigned s = 0; upx_byte * const p1 = ibuf + ph.u_len; memcpy(p1 + s,&ih,sizeof (ih)); s += sizeof (ih); memcpy(p1 + s,isection,ih.objects * sizeof(*isection)); s += ih.objects * sizeof(*isection); if (soimport) { set_le32(p1 + s,cimports); set_le32(p1 + s + 4,dllstrings); s += 8; } if (sorelocs) { set_le32(p1 + s,crelocs); p1[s + 4] = (unsigned char) (big_relocs & 6); s += 5; } if (soresources) { set_le16(p1 + s,icondir_count); s += 2; } // end of extra data set_le32(p1 + s,ptr_diff(p1,ibuf) - rvamin); s += 4; ph.u_len += s; obuf.allocForCompression(ph.u_len); // prepare packheader ph.u_len -= rvamin; // prepare filter Filter ft(ph.level); ft.buf_len = ih.codesize; ft.addvalue = ih.codebase - rvamin; // compress int filter_strategy = allow_filter ? 0 : -3; // disable filters for files with broken headers if (ih.codebase + ih.codesize > ph.u_len) { ft.buf_len = 1; filter_strategy = -3; } // limit stack size needed for runtime decompression upx_compress_config_t cconf; cconf.reset(); cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack compressWithFilters(&ft, 2048, &cconf, filter_strategy, ih.codebase, rvamin, 0, NULL, 0); // info: see buildLoader() newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1; /* if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4) tlsindex = 0; */ const unsigned lsize = getLoaderSize(); int identsize = 0; const unsigned codesize = getLoaderSection("IDENTSTR",&identsize); assert(identsize > 0); getLoaderSection("UPX1HEAD",(int*)&ic); identsize += ic; pe_section_t osection[4]; // section 0 : bss // 1 : [ident + header] + packed_data + unpacker + tls // 2 : not compressed data // 3 : resource data -- wince 5 needs a new section for this // identsplit - number of ident + (upx header) bytes to put into the PE header int identsplit = pe_offset + sizeof(osection) + sizeof(oh); if ((identsplit & 0x1ff) == 0) identsplit = 0; else if (((identsplit + identsize) ^ identsplit) < 0x200) identsplit = identsize; else identsplit = ALIGN_GAP(identsplit, 0x200); ic = identsize - identsplit; const unsigned c_len = ((ph.c_len + ic) & 15) == 0 ? ph.c_len : ph.c_len + 16 - ((ph.c_len + ic) & 15); obuf.clear(ph.c_len, c_len - ph.c_len); const unsigned s1size = ALIGN_UP(ic + c_len + codesize,4u) + sotls; const unsigned s1addr = (newvsize - (ic + c_len) + oam1) &~ oam1; const unsigned ncsection = (s1addr + s1size + oam1) &~ oam1; const unsigned upxsection = s1addr + ic + c_len; Reloc rel(1024); // new relocations are put here static const char* symbols_to_relocate[] = { "ONAM", "BIMP", "BREL", "FIBE", "FIBS", "ENTR", "DST0", "SRC0" }; for (unsigned s2r = 0; s2r < TABLESIZE(symbols_to_relocate); s2r++) { unsigned off = linker->getSymbolOffset(symbols_to_relocate[s2r]); if (off != 0xdeaddead) rel.add(off + upxsection, 3); } // new PE header memcpy(&oh,&ih,sizeof(oh)); oh.filealign = 0x200; // identsplit depends on this memset(osection,0,sizeof(osection)); oh.entry = upxsection; oh.objects = 4; oh.chksum = 0; // fill the data directory ODADDR(PEDIR_DEBUG) = 0; ODSIZE(PEDIR_DEBUG) = 0; ODADDR(PEDIR_IAT) = 0; ODSIZE(PEDIR_IAT) = 0; ODADDR(PEDIR_BOUNDIM) = 0; ODSIZE(PEDIR_BOUNDIM) = 0; // tls is put into section 1 ic = s1addr + s1size - sotls; super::processTls(&rel,&tlsiv,ic); ODADDR(PEDIR_TLS) = sotls ? ic : 0; ODSIZE(PEDIR_TLS) = sotls ? 0x18 : 0; ic += sotls; // these are put into section 2 ic = ncsection; // wince wants relocation data at the beginning of a section processRelocs(&rel); ODADDR(PEDIR_RELOC) = soxrelocs ? ic : 0; ODSIZE(PEDIR_RELOC) = soxrelocs; ic += soxrelocs; processImports(ic, linker->getSymbolOffset("IATT") + upxsection); ODADDR(PEDIR_IMPORT) = ic; ODSIZE(PEDIR_IMPORT) = soimpdlls; ic += soimpdlls; processExports(&xport,ic); ODADDR(PEDIR_EXPORT) = soexport ? ic : 0; ODSIZE(PEDIR_EXPORT) = soexport; if (!isdll && opt->win32_pe.compress_exports) { ODADDR(PEDIR_EXPORT) = IDADDR(PEDIR_EXPORT); ODSIZE(PEDIR_EXPORT) = IDSIZE(PEDIR_EXPORT); } ic += soexport; ic = (ic + oam1) &~ oam1; const unsigned res_start = ic; if (soresources) processResources(&res,ic); ODADDR(PEDIR_RESOURCE) = soresources ? ic : 0; ODSIZE(PEDIR_RESOURCE) = soresources; ic += soresources; const unsigned onam = ncsection + soxrelocs + ih.imagebase; linker->defineSymbol("start_of_dll_names", onam); linker->defineSymbol("start_of_imports", ih.imagebase + rvamin + cimports); linker->defineSymbol("start_of_relocs", crelocs + rvamin + ih.imagebase); linker->defineSymbol("filter_buffer_end", ih.imagebase + ih.codebase + ih.codesize); linker->defineSymbol("filter_buffer_start", ih.imagebase + ih.codebase); linker->defineSymbol("original_entry", ih.entry + ih.imagebase); linker->defineSymbol("uncompressed_length", ph.u_len); linker->defineSymbol("start_of_uncompressed", ih.imagebase + rvamin); linker->defineSymbol("compressed_length", ph.c_len); linker->defineSymbol("start_of_compressed", ih.imagebase + s1addr + identsize - identsplit); defineDecompressorSymbols(); relocateLoader(); MemBuffer loader(lsize); memcpy(loader, getLoader(), lsize); patchPackHeader(loader, lsize); // this is computed here, because soxrelocs changes some lines above const unsigned ncsize = soxrelocs + soimpdlls + soexport; const unsigned fam1 = oh.filealign - 1; // fill the sections strcpy(osection[0].name,"UPX0"); strcpy(osection[1].name,"UPX1"); strcpy(osection[2].name, "UPX2"); strcpy(osection[3].name, ".rsrc"); osection[0].vaddr = rvamin; osection[1].vaddr = s1addr; osection[2].vaddr = ncsection; osection[3].vaddr = res_start; osection[0].size = 0; osection[1].size = (s1size + fam1) &~ fam1; osection[2].size = (ncsize + fam1) &~ fam1; osection[3].size = (soresources + fam1) &~ fam1; osection[0].vsize = osection[1].vaddr - osection[0].vaddr; //osection[1].vsize = (osection[1].size + oam1) &~ oam1; //osection[2].vsize = (osection[2].size + oam1) &~ oam1; osection[1].vsize = osection[1].size; osection[2].vsize = osection[2].size; osection[3].vsize = osection[3].size; osection[0].rawdataptr = 0; osection[1].rawdataptr = (pe_offset + sizeof(oh) + sizeof(osection) + fam1) &~ fam1; osection[2].rawdataptr = osection[1].rawdataptr + osection[1].size; osection[3].rawdataptr = osection[2].rawdataptr + osection[2].size; osection[0].flags = (unsigned) (PEFL_BSS|PEFL_EXEC|PEFL_WRITE|PEFL_READ); osection[1].flags = (unsigned) (PEFL_DATA|PEFL_EXEC|PEFL_WRITE|PEFL_READ); osection[2].flags = (unsigned) (PEFL_DATA|PEFL_READ); osection[3].flags = (unsigned) (PEFL_DATA|PEFL_READ); oh.imagesize = (osection[3].vaddr + osection[3].vsize + oam1) &~ oam1; oh.bsssize = osection[0].vsize; oh.datasize = osection[2].vsize + osection[3].vsize; oh.database = osection[2].vaddr; oh.codesize = osection[1].vsize; oh.codebase = osection[1].vaddr; oh.headersize = osection[1].rawdataptr; if (rvamin < osection[0].rawdataptr) throwCantPack("object alignment too small"); if (opt->win32_pe.strip_relocs && !isdll) oh.flags |= RELOCS_STRIPPED; //for (ic = 0; ic < oh.filealign; ic += 4) // set_le32(ibuf + ic,get_le32("UPX ")); ibuf.clear(0, oh.filealign); info("Image size change: %u -> %u KiB", ih.imagesize / 1024, oh.imagesize / 1024); infoHeader("[Writing compressed file]"); if (soresources == 0) { oh.objects = 3; memset(&osection[3], 0, sizeof(osection[3])); } // write loader + compressed file fo->write(&oh,sizeof(oh)); fo->write(osection,sizeof(osection)); // some alignment if (identsplit == identsize) { unsigned n = osection[1].rawdataptr - fo->getBytesWritten() - identsize; assert(n <= oh.filealign); fo->write(ibuf, n); } fo->write(loader + codesize,identsize); infoWriting("loader", fo->getBytesWritten()); fo->write(obuf,c_len); infoWriting("compressed data", c_len); fo->write(loader,codesize); if (opt->debug.dump_stub_loader) OutputFile::dump(opt->debug.dump_stub_loader, loader, codesize); if ((ic = fo->getBytesWritten() & 3) != 0) fo->write(ibuf,4 - ic); fo->write(otls,sotls); if ((ic = fo->getBytesWritten() & fam1) != 0) fo->write(ibuf,oh.filealign - ic); fo->write(oxrelocs,soxrelocs); fo->write(oimpdlls,soimpdlls); fo->write(oexport,soexport); if ((ic = fo->getBytesWritten() & fam1) != 0) fo->write(ibuf,oh.filealign - ic); fo->write(oresources,soresources); if ((ic = fo->getBytesWritten() & fam1) != 0) fo->write(ibuf,oh.filealign - ic); #if 0 printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh)); printf("%-13s: sections : %8ld bytes\n", getName(), (long) sizeof(osection)); printf("%-13s: ident : %8ld bytes\n", getName(), (long) identsize); printf("%-13s: compressed : %8ld bytes\n", getName(), (long) c_len); printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) codesize); printf("%-13s: tls : %8ld bytes\n", getName(), (long) sotls); printf("%-13s: resources : %8ld bytes\n", getName(), (long) soresources); printf("%-13s: imports : %8ld bytes\n", getName(), (long) soimpdlls); printf("%-13s: exports : %8ld bytes\n", getName(), (long) soexport); printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs); #endif // verify verifyOverlappingDecompression(); // copy the overlay copyOverlay(fo, overlay, &obuf); // finally check the compression ratio if (!checkFinalCompressionRatio(fo)) throwNotCompressible(); }