⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_vmlinx.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        }        fo->write(&hdr_info, sizeof(hdr_info)); fo_off += sizeof(hdr_info);        ppc32_extra += sizeof(hdr_info);        if (ph.u_len!=f_len) {            set_be32(&hdr_info.sz_unc, f_ptr - (upx_bytep) ibuf);            set_be32(&hdr_info.sz_cpr, f_len);            fo->write(&hdr_info, 2*sizeof(unsigned)); fo_off += 2*sizeof(unsigned);            ppc32_extra += 2*sizeof(unsigned);        }#if 0  /*{ Documentation: changes to arch/powerpc/boot/main.c */struct b_info {	unsigned sz_unc;	unsigned sz_cpr;	unsigned char b_method;	unsigned char b_ftid;	unsigned char b_cto8;	unsigned char b_unused;};typedef int (*upx_f_unc)(  /* uncompress */	unsigned char const *src, unsigned  src_len,	unsigned char       *dst, unsigned *dst_len,	int method);typedef int (*upx_f_unf)(  /* unfilter */	unsigned char *buf,	unsigned len,	unsigned cto8,	unsigned ftid);unsigned char const *upx_expand(  // return updated src [aligned, too]	unsigned char const *src,	unsigned char       *dst,	unsigned *const dst_len,	upx_f_unc const f_unc){	if (0==*dst_len) {		*dst_len = ((struct b_info const *)src)->sz_unc;	}	upx_f_unf const f_unf = (upx_f_unf)(sizeof(int) + (char *)f_unc);	unsigned total_len = 0;	unsigned need = *dst_len;	while (0 < need) {		struct b_info const *const b_hdr = (struct b_info const *)src;		src = (unsigned char const *)(1+ b_hdr);		unsigned blk_len = b_hdr->sz_unc;		int const rv = (*f_unc)(src, b_hdr->sz_cpr, dst, &blk_len, b_hdr->b_method);		if (0!=rv) {			printf("decompress error %d\n\r", rv);			exit();		}		if (b_hdr->b_ftid) {			(*f_unf)(dst, b_hdr->sz_unc, b_hdr->b_cto8, b_hdr->b_ftid);		}		src += b_hdr->sz_cpr;		src += (3& -(int)src);  // 4-byte align		dst += b_hdr->sz_unc;		total_len += b_hdr->sz_unc;		need -= b_hdr->sz_unc;	}	*dst_len = total_len;	return src;}void prep_kernel(unsigned long a1, unsigned long a2){	upx_f_unc f_unc = (upx_f_unc)0;	vmlinuz.addr = (unsigned long)_vmlinux_start;	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);	if (0x55505821 == *(unsigned *)vmlinuz.addr) {		/* was compressed by upx */		/* Uncompress elfheader */		unsigned const *const fwa = (unsigned *)vmlinuz.addr;		f_unc = (upx_f_unc)((char *)&fwa[2] + fwa[1]);		unsigned dst_len = 0;		unsigned char const *src = (unsigned char const *)&fwa[2];		src = upx_expand(src, (unsigned char *)elfheader, &dst_len, f_unc);		unsigned const src_len = src - (unsigned char const *)&fwa[0];		vmlinuz.addr += src_len;		vmlinuz.size -= src_len;	} else {		memcpy(elfheader, (const void *)vmlinuz.addr,		       sizeof(elfheader));	}=====	/* Eventually gunzip the kernel */	if (f_unc) {		/* was compressed by upx */		printf("upx_expand (0x%lx <- 0x%lx:0x%0lx)...",		       vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);		unsigned dst_len = vmlinux.size - elfoffset;		upx_expand((unsigned char const *)vmlinuz.addr,		           (unsigned char       *)vmlinux.addr, &dst_len, f_unc);		printf("done 0x%lx bytes\n\r", len);	} else {		memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,			vmlinuz.size);		/* Skip over the ELF header */#ifdef DEBUG		printf("... skipping 0x%lx bytes of ELF header\n\r",				elfoffset);#endif		vmlinux.addr += elfoffset;	}=====}#endif  /*}*/    }    else {        compressWithFilters(&ft, 512, &cconf, getStrategy(ft));    }    unsigned const txt_c_len = ph.c_len;    const unsigned lsize = getLoaderSize();    defineDecompressorSymbols();    defineFilterSymbols(&ft);    relocateLoader();    MemBuffer loader(lsize);    memcpy(loader, getLoader(), lsize);    patchPackHeader(loader, lsize);#define shstrtab local_shstrtab // avoid -Wshadow warning    char const shstrtab[]= "\0.text\0.note\0.shstrtab\0.symtab\0.strtab";    char const *p = shstrtab;    while (0!=*p++) ;    shdro[1].sh_name = ptr_diff(p, shstrtab);    shdro[1].sh_type = Shdr::SHT_PROGBITS;    shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR;    shdro[1].sh_offset = fo_off - ppc32_extra;    shdro[1].sh_size = ppc32_extra + txt_c_len + lsize;  // plus more ...    shdro[1].sh_addralign = 1;  // default    fo_off += write_vmlinux_head(fo, &shdro[1]);    fo->write(obuf, txt_c_len); fo_off += txt_c_len;    unsigned const a = (shdro[1].sh_addralign -1) & (0u-(ppc32_extra + txt_c_len));    if (0!=a) { // align        fo_off += a;        shdro[1].sh_size += a;        fo->seek(a, SEEK_CUR);    }    fo->write(loader, lsize); fo_off += lsize;#if 0    printf("%-13s: compressed   : %8u bytes\n", getName(), txt_c_len);    printf("%-13s: decompressor : %8u bytes\n", getName(), lsize);#endif    verifyOverlappingDecompression();    // .note with 1st page --------------------------------    ph.u_len = phdri[0].p_offset;    fi->seek(0, SEEK_SET);    fi->readx(ibuf, ph.u_len);    compress(ibuf, ph.u_len, obuf, &cconf);    while (0!=*p++) ;    shdro[2].sh_name = ptr_diff(p, shstrtab);    shdro[2].sh_type = Shdr::SHT_NOTE;    shdro[2].sh_offset = fo_off;    shdro[2].sh_size = sizeof(ph.u_len) + ph.c_len;    shdro[2].sh_addralign = 1;    tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);    fo->write(obuf, ph.c_len); fo_off += shdro[2].sh_size;    // .note with rest     --------------------------------    ph.u_len = file_size - (sz_ptload + phdri[0].p_offset);    fi->seek(sz_ptload + phdri[0].p_offset, SEEK_SET);    fi->readx(ibuf, ph.u_len);    // Temporarily decrease ph.level by about (1+ log2(sz_rest / sz_ptload))    // to avoid spending unreasonable effort compressing large symbol tables    // that are discarded 99.9% of the time anyway.    int const old_level = ph.level;    for (unsigned v = ((ph.u_len>>3) + ph.u_len) / sz_ptload; 0 < v; v>>=1) {        if (0== --ph.level) {            ph.level = 1;        }    }    compress(ibuf, ph.u_len, obuf, &cconf);    ph.level = old_level;    // while (0!=*p++) ;  // name is the same    shdro[3].sh_name = ptr_diff(p, shstrtab);    shdro[3].sh_type = Shdr::SHT_NOTE;    shdro[3].sh_offset = fo_off;    shdro[3].sh_size = sizeof(ph.u_len) + ph.c_len;    shdro[3].sh_addralign = 1;    tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);    fo->write(obuf, ph.c_len); fo_off += shdro[3].sh_size;    while (0!=*p++) ;    shdro[4].sh_name = ptr_diff(p, shstrtab);    shdro[4].sh_type = Shdr::SHT_STRTAB;    shdro[4].sh_offset = fo_off;    shdro[4].sh_size = sizeof(shstrtab);  // already includes terminating '\0'    shdro[4].sh_addralign = 1;    fo->write(shstrtab, shdro[4].sh_size); fo_off += shdro[4].sh_size;    fo_off = ~3 & (3+ fo_off); fo->seek(fo_off, SEEK_SET);    while (0!=*p++) ;    shdro[5].sh_name = ptr_diff(p, shstrtab);    shdro[5].sh_type = Shdr::SHT_SYMTAB;    shdro[5].sh_offset = fo_off;    shdro[5].sh_size = ((Ehdr::EM_PPC==my_e_machine) + 5)*sizeof(Sym);    //shdro[5].sh_flags = Shdr::SHF_INFO_LINK;    shdro[5].sh_link = 6;  // to .strtab for symbols    shdro[5].sh_info = 1+3;  // number of non-global symbols [binutils/bfd/elf.c]    shdro[5].sh_addralign = 4;    shdro[5].sh_entsize = sizeof(Sym);    Sym sec_sym;    // Symbol 0; no references, but bfd demands it.    memset(&sec_sym, 0, sizeof(sec_sym));    fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);    // Each section before .shstrtab needs a symbol.    sec_sym.st_info = sec_sym.make_st_info(Sym::STB_LOCAL, Sym::STT_SECTION);    sec_sym.st_other = Sym::STV_DEFAULT;    sec_sym.st_shndx = 1;  // .text    fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);    sec_sym.st_shndx = 2;  // .note    fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);    sec_sym.st_shndx = 3;  // .note    fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);    // the symbol we care about    Sym unc_ker;    unc_ker.st_name = 1;  // 1 byte into strtab    unc_ker.st_value = 0;    unc_ker.st_size = ppc32_extra + txt_c_len;    unc_ker.st_info = unc_ker.make_st_info(Sym::STB_GLOBAL, Sym::STT_FUNC);    unc_ker.st_other = Sym::STV_DEFAULT;    unc_ker.st_shndx = 1;  // .text    fo->write(&unc_ker, sizeof(unc_ker)); fo_off += sizeof(unc_ker);    unsigned const lablen = strlen(my_boot_label);    if (Ehdr::EM_PPC==my_e_machine) {        unc_ker.st_name += 1+ lablen;        unc_ker.st_value = unc_ker.st_size;        unc_ker.st_size = 0;        fo->write(&unc_ker, sizeof(unc_ker)); fo_off += sizeof(unc_ker);    }    while (0!=*p++) ;    shdro[6].sh_name = ptr_diff(p, shstrtab);    shdro[6].sh_type = Shdr::SHT_STRTAB;    shdro[6].sh_offset = fo_off;    shdro[6].sh_size = 2+ lablen + (Ehdr::EM_PPC==my_e_machine)*(1+ 12);  // '\0' before and after    shdro[6].sh_addralign = 1;    fo->seek(1, SEEK_CUR);  // the '\0' before    fo->write(my_boot_label, 1+ lablen);  // include the '\0' terminator    if (Ehdr::EM_PPC==my_e_machine) {        fo->write("_vmlinux_end", 1+ 12); fo_off += 1+ 12;    }    fo_off += 2+ lablen;    fo->seek(0, SEEK_SET);    fo->write(&ehdro, sizeof(ehdro));    fo->write(&shdro, sizeof(shdro));    if (Ehdr::EM_PPC==my_e_machine) {        fo->seek(sizeof(unsigned), SEEK_CUR);        set_be32(&ppc32_extra, ppc32_extra - 2*sizeof(unsigned) + txt_c_len);        fo->write(&ppc32_extra, sizeof(ppc32_extra));    }    if (!checkFinalCompressionRatio(fo))        throwNotCompressible();#undef shstrtab}template <class T>int PackVmlinuxBase<T>::canUnpack(){    fi->seek(0, SEEK_SET);    fi->readx(&ehdri, sizeof(ehdri));    // now check the ELF header    if (memcmp(&ehdri, "\x7f\x45\x4c\x46", 4)    ||  ehdri.e_ident[Ehdr::EI_CLASS] != my_elfclass    ||  ehdri.e_ident[Ehdr::EI_DATA] != my_elfdata    ||  ehdri.e_ident[Ehdr::EI_VERSION] != Ehdr::EV_CURRENT    ||  !memcmp(&ehdri.e_ident[8], "FreeBSD", 7)  // branded    ||  ehdri.e_machine != my_e_machine    ||  ehdri.e_version != 1  // version    ||  ehdri.e_ehsize != sizeof(ehdri)  // different <elf.h> ?    )        return false;    if (ehdri.e_type != Ehdr::ET_REL    //i386 fails  ||  ehdri.e_shoff != sizeof(ehdri)  // Shdr not contiguous with Ehdr    ||  ehdri.e_shentsize!=sizeof(Shdr)    ||  ehdri.e_shnum < 4    ||  (unsigned)file_size < (ehdri.e_shnum * sizeof(Shdr) + ehdri.e_shoff)    )        return false;    // find the .shstrtab section    Shdr const *const shstrsec = getElfSections();    if (0==shstrsec) {        return false;    }    // check for .text .note .note  and sane (.sh_size + .sh_offset)    p_note0 = p_note1 = p_text = 0;    int j;    Shdr *p;    for (p= shdri, j= ehdri.e_shnum; --j>=0; ++p) {        if ((unsigned)file_size < (p->sh_size + p->sh_offset)        ||  shstrsec->sh_size < (5+ p->sh_name) ) {            continue;        }        if (0==strcmp(".text", shstrtab + p->sh_name)) {            p_text = p;        }        if (0==strcmp(".note", shstrtab + p->sh_name)) {            if (0==p_note0) {                p_note0 = p;            } else            if (0==p_note1) {                p_note1 = p;            }        }    }    if (0==p_text || 0==p_note0 || 0==p_note1) {        return false;    }    char buf[1024];    fi->seek(p_text->sh_offset + p_text->sh_size - sizeof(buf), SEEK_SET);    fi->readx(buf, sizeof(buf));    if (!getPackHeader(buf, sizeof(buf)))        return -1; // format is known, but definitely is not packed    return true;}template <class T>void PackVmlinuxBase<T>::unpack(OutputFile *fo){    U32 word;    PackHeader const ph_tmp(ph);    fi->seek(p_note0->sh_offset, SEEK_SET);    fi->readx(&word, sizeof(word));    ph.u_len = word;    ph.c_len = p_note0->sh_size - sizeof(word);    ibuf.alloc(ph.c_len);    fi->readx(ibuf, ph.c_len);    obuf.allocForUncompression(ph.u_len);    decompress(ibuf, obuf, false);    fo->write(obuf, ph.u_len);    obuf.dealloc();    ibuf.dealloc();    ph = ph_tmp;    if (!has_valid_vmlinux_head()) {        throwCantUnpack(".text corrupted");    }    ibuf.alloc(ph.c_len);    fi->readx(ibuf, ph.c_len);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -