Example #1
0
void PEObject::WriteHeader(std::fstream &stream)
{
    unsigned zero = 0;
    for (int i =0; i < name.size() && i < 8; i++)
        stream.write(&name[i], 1);
    for (int i = name.size(); i < 8; i++)
        stream.write((char *)&zero, 1);
    unsigned msize = ObjectAlign(objectAlign, size);
    stream.write((char *)&msize, 4);
    stream.write((char *)&virtual_addr, 4);
    msize = ObjectAlign(fileAlign, initSize);
    stream.write((char *)&msize, 4);
    stream.write((char *)&raw_addr, 4);
    stream.write((char *)&zero, 4);
    stream.write((char *)&zero, 4);
    stream.write((char *)&zero, 4);
    int flg = (flags ^ WINF_NEG_FLAGS) & WINF_IMAGE_FLAGS; /* get characteristice for section */
    stream.write((char *)&flg, 4);
}
Example #2
0
void PEObject::Write(std::fstream &stream)
{
    stream.write((char *)data, initSize);
    int n = ObjectAlign(fileAlign, initSize) - initSize;
    char buf[512];
    memset(buf,0, sizeof(buf));
    while (n > 0)
    {
        int s = sizeof(buf);
        if (n < s)
            s = n;
        stream.write(buf, s);
        n -= s;
    }
}
Example #3
0
void PEImportObject::Setup(ObjInt &endVa, ObjInt &endPhys)
{
    if (virtual_addr == 0)
    {
        virtual_addr = endVa;
    }
    else
    {
        if (virtual_addr != endVa)
            Utils::fatal("Internal error");
    }
    raw_addr = endPhys;
    std::map<ObjString, ObjSymbol *> externs;
    for (ObjFile::SymbolIterator it = file->ExternalBegin(); it != file->ExternalEnd(); ++it)
    {
        externs[(*it)->GetName()] = (*it);
    }
    std::map<std::string, Module *> modules;
    int nameSize = 0;
    int impNameSize = 0;
    int importCount = 0;
    int dllCount = 0;
    for (ObjFile::SymbolIterator it = file->ImportBegin(); it != file->ImportEnd(); ++it)
    {
        ObjImportSymbol *s = (ObjImportSymbol *)(*it);
        // uppercase the module name for NT... 98 doesn't need it but can accept it
        std::string name = s->GetDllName();
        for (int i =0; i < name.size(); i++)
            name[i] = toupper(name[i]);
        s->SetDllName(name);
        if (externs.find((*it)->GetName()) != externs.end())
        {
            Module *m = modules[s->GetDllName()];
            int sz = s->GetDllName().size() + 1;
            if (sz & 1)
                sz ++;
            nameSize += sz;
            if (m == NULL)
            {
                modules[s->GetDllName()] = m = new Module;
                m->module = s->GetDllName();
                dllCount++;
            }
            if (s->GetExternalName().size() == 0)
            {
                m->externalNames.push_back(s->GetName());
                sz = s->GetName().size() + 1;
            }
            else
            {
                m->externalNames.push_back(s->GetExternalName());
                sz = s->GetExternalName().size() + 1;
            }
            sz += 2;
            if (sz & 1)
                sz ++;
            impNameSize += sz;
            m->publicNames.push_back(s->GetName());
            m->ordinals.push_back(s->GetByOrdinal() ? s->GetOrdinal() : 0xffffffff);
            importCount ++;
        }
    }
    data = new unsigned char[(modules.size() + 1) * sizeof(Dir) +
                             ((nameSize + 3) & ~3) + (importCount + dllCount) * sizeof(Entry) * 2 +
                             ((impNameSize + 3) & ~3)];
    Dir *dirPos = (Dir *)data;
    char *namePos = (char *)data + sizeof(Dir) * (modules.size() + 1);
    Entry *lookupPos = (Entry *)((char *)namePos + ((nameSize + 3) & ~3));
    char *hintPos = ((char *)lookupPos)	+ (importCount + dllCount) * sizeof(Entry);
    Entry *addressPos = (Entry *)(hintPos + ((impNameSize + 3) & ~3));
    size = initSize = (unsigned)(((unsigned char *)addressPos) - data + (importCount + dllCount) * sizeof(Entry));
    memset(data, 0, size); // note this does clean out some areas we deliberately are not initializing
    for (std::map<std::string, Module *>::iterator it = modules.begin(); it != modules.end(); ++it)
    {
        dirPos->time = 0;
        dirPos->version = 0;
        dirPos->dllName = (unsigned char *)namePos - data + virtual_addr;
        dirPos->thunkPos = ((unsigned char *)lookupPos) - data + virtual_addr;
        dirPos->thunkPos2 = ((unsigned char *)addressPos) - data + virtual_addr;
        dirPos++;
        strcpy(namePos, it->first.c_str());
        int n = it->first.size() + 1;
        if (n & 1)
            n++;
        namePos += n;
        for (int i = 0; i < it->second->externalNames.size(); i++)
        {
            const std::string &str = it->second->externalNames[i];
            if (str.size())
            {
                lookupPos->ord_or_rva = (unsigned char *)hintPos - data + virtual_addr;
                addressPos->ord_or_rva = (unsigned char *) hintPos - data + virtual_addr;
                *(short *)hintPos = 0; //it->second->ordinals[i];
                hintPos += 2;
                strcpy(hintPos, str.c_str());
                int n = str.size() + 1;
                if (n & 1)
                    n++;
                hintPos += n;
            }
            else
            {
                lookupPos->ord_or_rva = addressPos->ord_or_rva = it->second->ordinals[i] | IMPORT_BY_ORDINAL;
            }
            // next up we make a thunk that will get us from the rel calls genned by
            // the compiler to the import table;		
            ObjSymbol *sym = externs[it->second->publicNames[i]];
            int en = sym->GetIndex();
            for (std::deque<PEObject *>::iterator it1 = objects.begin(); it1 != objects.end(); ++ it1)
            {
                ObjInt val;
                if ((val = (*it1)->SetThunk(en, ((unsigned char *)lookupPos) - data + virtual_addr + imageBase)) != -1)
                    sym->SetOffset(new ObjExpression(val));
            }
            lookupPos++;
            addressPos++;
        }
        // skip the null entry at the end of a module
        lookupPos++;
        addressPos++;
    }
    for (std::map<std::string, Module *>::iterator it = modules.begin(); it != modules.end(); ++it)
    {
        Module *p = it->second;
        delete p;
    }

    endVa = ObjectAlign(objectAlign, endVa + size);
    endPhys = ObjectAlign(fileAlign, endPhys + initSize);
}
Example #4
0
void PEFixupObject::Setup(ObjInt &endVa, ObjInt &endPhys)
{
    if (virtual_addr == 0)
    {
        virtual_addr = endVa;
    }
    else
    {
        if (virtual_addr != endVa)
            Utils::fatal("Internal error");
    }
    raw_addr = endPhys;
    if (fixups.size() == 0)
    {
        // for WINNT, he needs some reloc data even if it is empty...
        Block block;
        block.rva = 0;
        block.size = 12;
        block.data[0] = block.data[1] = 0;
        data = new unsigned char[block.size];
        memcpy(data, &block, block.size);
        size = initSize = block.size;
    }
    else
    {
        int base = -1;
        initSize = 0;
        for (auto fixup : fixups)
        {
            if ((base ^ fixup) & ~4095)
            {
                if (initSize & 2)
                    initSize += 2;
                initSize += 8;
                base = fixup;
            }
            initSize += 2;
        }
        if (initSize & 2)
            initSize += 2;
        size = initSize;
        data = new unsigned char[initSize];
        memset(data, 0, initSize);
        // we relied on the set implementation to sort the fixups...
        int curSize = 0;
        Block *block = (Block *)data;
        for (auto it = fixups.begin(); it != fixups.end();)
        {
            ObjInt base = (*it) & ~(4096 - 1);
            int current = 0;
            block->rva = base - imageBase;
            block->size = 8;
            while (it != fixups.end() && ((*it) & ~(4096 - 1)) == base)
            {
                block->size+=2;
                block->data[current++] = ((*it) & (4096 -1)) + ( PE_FIXUP_HIGHLOW << 12);
                ++it;
            }
            if (block->size & 2)
            {
                block->size += 2;
                block->data[current++] = 0;
            }
            block = (Block *)((unsigned char *)block + block->size);
        }
    }
    endVa = ObjectAlign(objectAlign, endVa + size);
    endPhys = ObjectAlign(fileAlign, endPhys + initSize);
}
Example #5
0
void PEExportObject::Setup(ObjInt &endVa, ObjInt &endPhys)
{
    if (virtual_addr == 0)
    {
        virtual_addr = endVa;
    }
    else
    {
        if (virtual_addr != endVa)
            Utils::fatal("Internal error");
    }
    raw_addr = endPhys;
    std::map<std::string, ObjInt> publics;
    for (ObjFile::SymbolIterator it = file->PublicBegin(); it != file->PublicEnd(); ++it)
    {
        publics[(*it)->GetName()] = (*it)->GetOffset()->Eval(0);
    }


    int pos = moduleName.find_last_of("\\");
    if (pos == std::string::npos)
    {
        pos = moduleName.find_last_of(":");
        if (pos == std::string::npos)
            pos = 0;
    }
    std::string name = moduleName.substr(pos);

    size = initSize = sizeof(Header) + 1 + name.size();

    unsigned minOrd=0xffffffff; /* max ordinal num */
    unsigned maxOrd=0;
    unsigned count = 0;
    std::set<ObjExportSymbol *, namelt> names;
    for (ObjFile::SymbolIterator it = file->ExportBegin(); it != file->ExportEnd(); ++it)
    {
        ObjExportSymbol *s = (ObjExportSymbol *)(*it);
        names.insert(s);
        if (!s->GetByOrdinal())
        {
            initSize = (size += s->GetName().size() + 1 + 6);
        }
        if (s->GetOrdinal() != 0xffffffff)
        {
            int n = s->GetOrdinal();
            if (n < minOrd)
                minOrd = n;
            if (n > maxOrd)
                maxOrd = n;
        }
        count++;
    }				
    if (maxOrd >= minOrd)
    {
        count = count > (maxOrd-minOrd + 1) ? count : maxOrd-minOrd + 1;
    }
    else
    {
        minOrd = 1;
        maxOrd = count + minOrd - 1;
    }
    initSize = (size +=	4 * count);
    data = new unsigned char[initSize];
    memset(data, 0, initSize);
    Header *header = (Header *)data;

    header->time = time(0);
    header->ord_base = minOrd;
    header->n_eat_entries = count;
    header->n_name_ptrs = names.size();
    unsigned *rvaTable = (unsigned *)(data + sizeof(Header));
    unsigned *nameTable = (unsigned *)(((unsigned char *)rvaTable) + 4 * count);
    unsigned short *ordinalTable = (unsigned short *)(((unsigned char *)nameTable) + 4 * names.size());
    unsigned char *stringTable = (unsigned char *)(((unsigned char *)ordinalTable) + 2 * names.size());

    header->address_rva = virtual_addr + ((unsigned char *)rvaTable) - data;
    header->name_rva = virtual_addr + ((unsigned char *)nameTable) - data;
    header->ordinal_rva = virtual_addr + ((unsigned char *)ordinalTable) - data;

    /* process numbered exports */
    for (ObjFile::SymbolIterator it = file->ExportBegin(); it != file->ExportEnd(); ++it)
    {
        ObjExportSymbol *s = (ObjExportSymbol *)(*it);
        if (s->GetByOrdinal())
        {
            int n = s->GetOrdinal();
            if (rvaTable[n - minOrd] != 0)
                std::cout << "Warning: Export '" << s->GetName() << "' duplicates an ordinal" << std::endl;
            int addr = publics[s->GetName()];
            if (addr == 0)
                std::cout << "Warning: Export '" << s->GetName() << "' has no related public" << std::endl;
                
            rvaTable[n - minOrd] = addr - imageBase;
        }
    }			
                
    /* process non-numbered exports */
    pos = 0;
    for (ObjFile::SymbolIterator it = file->ExportBegin(); it != file->ExportEnd(); ++it)
    {
        ObjExportSymbol *s = (ObjExportSymbol *)(*it);
        if (!s->GetByOrdinal())
        {
            while(rvaTable[pos])
                pos++;
            s->SetOrdinal(pos + minOrd);
            int addr = publics[s->GetName()];
            if (addr == 0)
                std::cout << "Warning: Export '" << s->GetName() << "' has no related public" << std::endl;
            rvaTable[pos] = addr - imageBase;
        }
    }
    // process named exports
    for (std::set<ObjExportSymbol *, namelt>::iterator it = names.begin(); it != names.end(); ++it)
    {
        *nameTable++ = (unsigned)((unsigned char *)stringTable - data + virtual_addr);
        *ordinalTable++ = (*it)->GetOrdinal() - minOrd;
        strcpy((char *)stringTable, (*it)->GetName().c_str());
        stringTable += (*it)->GetName().size();
        *stringTable++ = 0;
    }
    // throw in the DLL name
    if (name.size())
    {
        header->exe_name_rva = (unsigned)((unsigned char *)stringTable - data + virtual_addr);
        for (int i=0; i < name.size(); i++)
            *stringTable++ = toupper(name[i]);
        *stringTable++ = 0;
    }
    endVa = ObjectAlign(objectAlign, endVa + size);
    endPhys = ObjectAlign(fileAlign, endPhys + initSize);
}