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

📄 pefile.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
struct tls{    LE32 datastart; // VA tls init data start    LE32 dataend;   // VA tls init data end    LE32 tlsindex;  // VA tls index    LE32 callbacks; // VA tls callbacks    char _[8];      // zero init, characteristics}__attribute_packed;void PeFile::processTls(Interval *iv) // pass 1{    COMPILE_TIME_ASSERT(sizeof(tls) == 24);    if ((sotls = ALIGN_UP(IDSIZE(PEDIR_TLS),4)) == 0)        return;    const tls * const tlsp = (const tls*) (ibuf + IDADDR(PEDIR_TLS));    // note: TLS callbacks are not implemented in Windows 95/98/ME    if (tlsp->callbacks)    {        if (tlsp->callbacks < ih.imagebase)            throwCantPack("invalid TLS callback");        else if (tlsp->callbacks - ih.imagebase + 4 >= ih.imagesize)            throwCantPack("invalid TLS callback");        unsigned v = get_le32(ibuf + tlsp->callbacks - ih.imagebase);        if (v != 0)        {            //fprintf(stderr, "TLS callbacks: 0x%0x -> 0x%0x\n", (int)tlsp->callbacks, v);            throwCantPack("TLS callbacks are not supported");        }    }    const unsigned tlsdatastart = tlsp->datastart - ih.imagebase;    const unsigned tlsdataend = tlsp->dataend - ih.imagebase;    // now some ugly stuff: find the relocation entries in the tls data area    unsigned pos,type;    Reloc rel(ibuf + IDADDR(PEDIR_RELOC),IDSIZE(PEDIR_RELOC));    while (rel.next(pos,type))        if (pos >= tlsdatastart && pos < tlsdataend)            iv->add(pos,type);    sotls = sizeof(tls) + tlsdataend - tlsdatastart;    // the PE loader wants this stuff uncompressed    otls = new upx_byte[sotls];    memset(otls,0,sotls);    memcpy(otls,ibuf + IDADDR(PEDIR_TLS),0x18);    // WARNING: this can acces data in BSS    memcpy(otls + sizeof(tls),ibuf + tlsdatastart,sotls - sizeof(tls));    tlsindex = tlsp->tlsindex - ih.imagebase;    info("TLS: %u bytes tls data and %u relocations added",sotls - (unsigned) sizeof(tls),iv->ivnum);    // makes sure tls index is zero after decompression    if (tlsindex && tlsindex < ih.imagesize)        set_le32(ibuf + tlsindex, 0);}void PeFile::processTls(Reloc *rel,const Interval *iv,unsigned newaddr) // pass 2{    if (sotls == 0)        return;    // add new relocation entries    unsigned ic;    for (ic = 0; ic < 12; ic += 4)        rel->add(newaddr + ic,3);    tls * const tlsp = (tls*) otls;    // now the relocation entries in the tls data area    for (ic = 0; ic < iv->ivnum; ic += 4)    {        void *p = otls + iv->ivarr[ic].start - (tlsp->datastart - ih.imagebase) + sizeof(tls);        unsigned kc = get_le32(p);        if (kc < tlsp->dataend && kc >= tlsp->datastart)        {            kc +=  newaddr + sizeof(tls) - tlsp->datastart;            set_le32(p,kc + ih.imagebase);            rel->add(kc,iv->ivarr[ic].len);        }        else            rel->add(kc - ih.imagebase,iv->ivarr[ic].len);    }    tlsp->datastart = newaddr + sizeof(tls) + ih.imagebase;    tlsp->dataend = newaddr + sotls + ih.imagebase;    tlsp->callbacks = 0; // note: TLS callbacks are not implemented in Windows 95/98/ME}/*************************************************************************// resource handling**************************************************************************/struct PeFile::Resource::res_dir_entry{    LE32  tnl; // Type | Name | Language id - depending on level    LE32  child;}__attribute_packed;struct PeFile::Resource::res_dir{    char  _[12]; // flags, timedate, version    LE16  namedentr;    LE16  identr;    unsigned Sizeof() const { return 16 + sizeof(res_dir_entry)*(namedentr + identr); }    res_dir_entry entries[1];    // it's usually safe to assume that every res_dir contains    // at least one res_dir_entry - check() complains otherwise}__attribute_packed;struct PeFile::Resource::res_data{    LE32  offset;    LE32  size;    char  _[8]; // codepage, reserved}__attribute_packed;struct PeFile::Resource::upx_rnode{    unsigned        id;    upx_byte        *name;    upx_rnode       *parent;};struct PeFile::Resource::upx_rbranch : public upx_rnode{    unsigned        nc;    upx_rnode       **children;    res_dir         data;};struct PeFile::Resource::upx_rleaf : public upx_rnode{    upx_rleaf       *next;    unsigned        newoffset;    res_data        data;};PeFile::Resource::Resource() : root(NULL){}PeFile::Resource::Resource(const upx_byte *p){    init(p);}PeFile::Resource::~Resource(){    if (root) destroy (root,0);}unsigned PeFile::Resource::dirsize() const{    return ALIGN_UP(dsize + ssize, 4u);}bool PeFile::Resource::next(){    // wow, builtin autorewind... :-)    return (current = current ? current->next : head) != NULL;}unsigned PeFile::Resource::itype() const{    return current->parent->parent->id;}const upx_byte *PeFile::Resource::ntype() const{    return current->parent->parent->name;}unsigned PeFile::Resource::size() const{    return ALIGN_UP(current->data.size,4);}unsigned PeFile::Resource::offs() const{    return current->data.offset;}unsigned &PeFile::Resource::newoffs(){    return current->newoffset;}void PeFile::Resource::dump() const{    dump(root,0);}unsigned PeFile::Resource::iname() const{    return current->parent->id;}const upx_byte *PeFile::Resource::nname() const{    return current->parent->name;}/*    unsigned ilang() const {return current->id;}    const upx_byte *nlang() const {return current->name;}*/void PeFile::Resource::init(const upx_byte *res){    COMPILE_TIME_ASSERT(sizeof(res_dir_entry) == 8)    COMPILE_TIME_ASSERT(sizeof(res_dir) == 16 + 8)    COMPILE_TIME_ASSERT(sizeof(res_data) == 16)    COMPILE_TIME_ASSERT_ALIGNED1(res_dir_entry)    COMPILE_TIME_ASSERT_ALIGNED1(res_dir)    COMPILE_TIME_ASSERT_ALIGNED1(res_data)    start = res;    root = head = current = NULL;    dsize = ssize = 0;    check((const res_dir*) start,0);    root = convert(start,NULL,0);}void PeFile::Resource::check(const res_dir *node,unsigned level){    int ic = node->identr + node->namedentr;    if (ic == 0)        return;    for (const res_dir_entry *rde = node->entries; --ic >= 0; rde++)        if (((rde->child & 0x80000000) == 0) ^ (level == 2))            throwCantPack("unsupported resource structure");        else if (level != 2)            check((const res_dir*) (start + (rde->child & 0x7fffffff)),level + 1);}PeFile::Resource::upx_rnode *PeFile::Resource::convert(const void *rnode,                                                       upx_rnode *parent,                                                       unsigned level){    if (level == 3)    {        const res_data *node = (const res_data *) rnode;        upx_rleaf *leaf = new upx_rleaf;        leaf->name = NULL;        leaf->parent = parent;        leaf->next = head;        leaf->newoffset = 0;        leaf->data = *node;        head = leaf; // append node to a linked list for traversal        dsize += sizeof(res_data);        return leaf;    }    const res_dir *node = (const res_dir *) rnode;    int ic = node->identr + node->namedentr;    if (ic == 0)        return NULL;    upx_rbranch *branch = new upx_rbranch;    branch->name = NULL;    branch->parent = parent;    branch->nc = ic;    branch->children = new upx_rnode*[ic];    branch->data = *node;    for (const res_dir_entry *rde = node->entries + ic - 1; --ic >= 0; rde--)    {        upx_rnode *child = convert(start + (rde->child & 0x7fffffff),branch,level + 1);        branch->children[ic] = child;        child->id = rde->tnl;        if (child->id & 0x80000000)        {            const upx_byte *p = start + (child->id & 0x7fffffff);            const unsigned len = 2 + 2 * get_le16(p);            child->name = new upx_byte[len];            memcpy(child->name,p,len); // copy unicode string            ssize += len; // size of unicode strings        }    }    dsize += node->Sizeof();    return branch;}void PeFile::Resource::build(const upx_rnode *node, unsigned &bpos,                             unsigned &spos, unsigned level){    if (level == 3)    {        res_data *l = (res_data*) (newstart + bpos);        const upx_rleaf *leaf = (const upx_rleaf*) node;        *l = leaf->data;        if (leaf->newoffset)            l->offset = leaf->newoffset;        bpos += sizeof(*l);        return;    }    res_dir * const b = (res_dir*) (newstart + bpos);    const upx_rbranch *branch = (const upx_rbranch*) node;    *b = branch->data;    bpos += b->Sizeof();    res_dir_entry *be = b->entries;    for (unsigned ic = 0; ic < branch->nc; ic++, be++)    {        be->tnl = branch->children[ic]->id;        be->child = bpos + ((level < 2) ? 0x80000000 : 0);        const upx_byte *p;        if ((p = branch->children[ic]->name) != 0)        {            be->tnl = spos + 0x80000000;            memcpy(newstart + spos,p,get_le16(p) * 2 + 2);            spos += get_le16(p) * 2 + 2;        }        build(branch->children[ic],bpos,spos,level + 1);    }}upx_byte *PeFile::Resource::build(){    newstart = new upx_byte [dirsize()];    unsigned bpos = 0,spos = dsize;    build(root,bpos,spos,0);    // dirsize() is 4 bytes aligned, so we may need to zero    // up to 2 bytes to make valgrind happy    while (spos < dirsize())        newstart[spos++] = 0;    return newstart;}void PeFile::Resource::destroy(upx_rnode *node,unsigned level){    delete [] node->name; node->name = NULL;    if (level != 3)    {        upx_rbranch * const branch = (upx_rbranch *) node;        for (int ic = branch->nc; --ic >= 0; )            destroy(branch->children[ic],level + 1);        delete [] branch->children; branch->children = NULL;    }    delete node;}static void lame_print_unicode(const upx_byte *p){    for (unsigned ic = 0; ic < get_le16(p); ic++)        printf("%c",(char)p[ic * 2 + 2]);}void PeFile::Resource::dump(const upx_rnode *node,unsigned level) const{    if (level)    {        for (unsigned ic = 1; ic < level; ic++)            printf("\t\t");        if (node->name)            lame_print_unicode(node->name);        else            printf("0x%x",node->id);        printf("\n");    }    if (level == 3)        return;    const upx_rbranch * const branch = (const upx_rbranch *) node;    for (unsigned ic = 0; ic < branch->nc; ic++)        dump(branch->children[ic],level + 1);}void PeFile::Resource::clear(upx_byte *node,unsigned level,Interval *iv){    if (level == 3)        iv->add(node,sizeof (res_data));    else    {        const res_dir * const rd = (res_dir*) node;        const unsigned n = rd->identr + rd->namedentr;        const res_dir_entry *rde = rd->entries;        for (unsigned ic = 0; ic < n; ic++, rde++)            clear(newstart + (rde->child & 0x7fffffff),level + 1,iv);        iv->add(rd,rd->Sizeof());    }}bool PeFile::Resource::clear(){    newstart = const_cast<upx_byte*> (start);    Interval iv(newstart);    clear(newstart,0,&iv);    iv.flatten();    if (iv.ivnum == 1)        iv.clear();#if defined(DEBUG)    if (opt->verbose > 3)        iv.dump();#endif    return iv.ivnum == 1;}void PeFile::processResources(Resource *res,unsigned newaddr){    if (IDSIZE(PEDIR_RESOURCE) == 0)        return;    while (res->next())        if (res->newoffs())            res->newoffs() += newaddr;    upx_byte *p = res->build();    memcpy(oresources,p,res->dirsize());    delete [] p;}static bool match(unsigned itype, const unsigned char *ntype,                  unsigned iname, const unsigned char *nname,                  const char *keep){    // format of string keep: type1[/name1],type2[/name2], ....    // typex and namex can be string or number    // hopefully resource names do not have '/' or ',' characters inside    struct helper    {        static bool match(unsigned num, const unsigned char *unistr,                          const char *mkeep)        {            if (!unistr)                return (unsigned) atoi(mkeep) == num;            unsigned ic;            for (ic = 0; ic < get_le16(unistr); ic++)                if (unistr[2 + ic * 2] != (unsigned char) mkeep[ic])                    return false;            return mkeep[ic] == 0 || mkeep[ic] == ',' || mkeep[ic] == '/';        }    };    // FIXME this comparison is not too exact    while (1)    {        char *delim1 = strchr(keep, '/');        char *delim2 = strchr(keep, ',');        if (helper::match(itype, ntype, keep))        {            if (!delim1)

⌨️ 快捷键说明

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