3

This is a question related to another question I asked a few days ago; I recommend you to give a quick read to it here because it can contain useful information. Anyway, I have two static classes inside my target executable (ECX register always spotted inside classes' methods), and it clearly looks like the first one contains the second one:

.data:0190BD08 CFG_DB db ; DATA XREF: sub_40FFF0:loc_410049o
// 4 Bytes
.data:0190BD0C CFG_DB_TABLE<struct CFG_ENTRY[500], unsigned int> db ; DATA XREF: sub_A3DDD0+2Co
// 30 Bytes
.data:0190BD3C dword_190BD3C dd ? ; int dword_190BD3C[] DATA XREF: sub_5F5F70+B2r

With sub_40FFF0:loc_410049o =
    CFG_DB_TABLE_Reset((int)&CFG_DB);

Here is the Virtual Function Table of the first one:

.rdata:0137A1F0 dd offset CFG_DB
.rdata:0137A1F4 ??_7CFG_DB@@6B@ dd offset CFG_DB_Constructor
.rdata:0137A1F4     ; DATA XREF: CFG_DB_CreateInstance+8o
.rdata:0137A1F8 dd offset nullsub_008EF050
.rdata:0137A1FC dd offset sub_8EAB30
.rdata:0137A200 dd offset sub_8EF060
.rdata:0137A204 dd offset CFG_DB_TABLE_Reset
.rdata:0137A208 dd offset CFG_DB_ParseData
.rdata:0137A20C dd offset CFG_DB_ReadFile

And the Virtual Function Table of the second one:

.rdata:0137A1D4 dd offset CFG_DB_TABLE
.rdata:0137A1D8 ??_7?$CFG_DB_TABLE@UCFG_ENTRY@@$0BPE@I@@6B@ dd offset CFG_DB_TABLE_Constructor
.rdata:0137A1D8     ; DATA XREF: CFG_DB_TABLE_Destructor+1Do
.rdata:0137A1D8     ; DATA XREF: CFG_DB_TABLE_CreateInstance+38o
.rdata:0137A1DC dd offset nullsub_008EF050
.rdata:0137A1E0 dd offset sub_8EAB30
.rdata:0137A1E4 dd offset sub_8EF060
.rdata:0137A1E8 dd offset CFG_DB_TABLE_Reset
.rdata:0137A1EC dd offset CFG_DB_ParseData

In pseudo-code all this should look like this:

static CFG_DB cfgDB;

class CFG_DB
{
    int memoryAddress;
    static CFG_DB_TABLE _DBTable;
    // more data?
};

struct CFG_DB_TABLE
{
    int memoryAddress;
    CFG_ENTRY cfgEntries[500];
    int       filledSlotsCount;
    // more data...
};

All I want to do is to increase the size of CFG_ENTRY structure's array located in CFG_DB_TABLE from 500 to 1000. Knowing the size of CFG_ENTRY structure (it's 996 bytes), it appears to be a quite simple task to do. Becaose of the fact that the filledSlotsCount (referenced by many times in the code) is placed at the end of the struct I can proceed using two different approchaes:

  1. Increasing the size of the existing cfgEntries to 1000 and increasing also every pointer reference to filledSlotsCount and other variables by 996*500.
  2. Appending a CFG_ENTRY newCfgEntries[1000] to the end of the structure and setting every pointer reference to cfgEntries by sizeof(CFG_DB_TABLE)-(996*1000). This one seems to be the simpler one.

So, for example, using the first approach, this small piece of CFG_DB_ParseData's code:

while (true)
{
    currentFilledSlotsCount = *(_DWORD *)(pointerToCFG_DB_TABLE + 498004);

    if ( currentFilledSlotsCount >= 500 )
        break;

    *(_DWORD *)(pointerToCFG_DB_TABLE + 498004) = currentFilledSlotsCount + 1;

    if (!CFG_DB_ParseEntry((void *)(pointerToCFG_DB_TABLE + 996 * currentFilledSlotsCount + 4), v5) )
    {

Becomes:

while (true)
{
    currentFilledSlotsCount = *(_DWORD *)(pointerToCFG_DB_TABLE + 996004);

    if ( currentFilledSlotsCount >= 1000 )
        break;

    *(_DWORD *)(pointerToCFG_DB_TABLE + 996004) = currentFilledSlotsCount + 1;

    if (!CFG_DB_ParseEntry((void *)(pointerToCFG_DB_TABLE + 996 * currentFilledSlotsCount + 4), v5) )
    {

And the code of method CFG_DB_TABLE_CreateInstance becomes:

int __thiscall CFG_DB_TABLE_CreateInstance(int this)
{
    int v1; // esi@1
    int v2; // [sp+18h] [bp-28h]@1

    v1 = this;
    v2 = this;

    *(_DWORD *)this = &CFG_DB_TABLE<CFG_ENTRY_500_unsigned_int>::_vftable_;
    unknown_libname_2672((void *)(this + 4), 996, 1000, sub_8EECA0, sub_8EEA00);

Now... doing these modifications I avoided memory overlapping/overwriting into the classes themselves, but I still have to deal with the .data segment itself, right? In fact I think I have to extend its size by 996*500 and, as suggested by other users that helped me out in my previous question, I should also move:

.data:0190BD08 CFG_DB db
.data:0190BD0C CFG_DB_TABLE<struct CFG_ENTRY[500], unsigned int> db

To the bottom of the .data segment, right? Otherwise the memory of those static classes risks to run over the memory of static instances that are located after them in the segment.

My questions are quite simple:

1) How can it be possible that the size of the static CFG_DB_TABLE is only 30 bytes in the .data segment (data:0190BD3C - data:0190BD0C) if it contains 4+996*500*4=498008 bytes minimum (but probably even more because I saw some pointer references starting from it like this+502036)? Am I missing something very important in my calculations?

2) How can I move extend the size of the .data segment by 996*500? Do I have to manually edit the PE header values?

3) If this is really necessary... how can I move my static data references concerning CFG_DB and CFG_DB_TABLE instances from the middle to the bottom of the .data segment itself? Is there any tool out there that can do this also taking care of rewriting every reference to them?

2
  • 1
    Maybe an off the wall question, but what is the layout of a CFG_ENTRY? Does an individual entry really require 996 bytes? What is the largest single entry? If no entry is larger than say 498 bytes, perhaps it is possible to modify CFG_ENTRY to cut its size in half effectively doubling the capacity of your existing CFG_DB_TABLE table. Commented May 13, 2014 at 3:41
  • In fact yes, every single chunk of data is being modified for every CFG_ENTRY as soon as the routing for parsing the CFG file starts. The last DWORD [992 to 996] looks like a counter. It starts from 0 for the first entry and, for the last one, is 499. Even if the data on the middle is not being used... it would be a real hell to modify the structure.
    – Zarathos
    Commented May 13, 2014 at 3:56

1 Answer 1

1

There are many confusing things in your first question. With 2nd & 3rd question, I think the answer is absolutely possible but it requires many works (manually). You could use some PE Tools (PE Editor tools - Lord PE is a good example) to resize the section and modify the data in the section (in binary Hex mode). And to validate all the references of your old structure pointer, you can use some disassembly tools like IDA, OllyDbg to find the position of all the references and modify it in hex mode.

In brief, I summary my solution as follow:

  1. Use PE Editor (Lord PE) to resize the .data section and any sections you will modify (turn on the Write Flag in these sections).
  2. In some case PE Editor not update the PE Header, so you must do it manually to get a valid image (that can load in memory and run).
  3. Using OllyDbg to edit, modify binary data in memory (with disassembly support :)) to change your data structure and all references so it will be easier to trace, debug. After all your modifying, you should dump and fix IAT (like unpacking PE files). In some case, your modifying not work in OllyDbg, you should use a Hex Editor or Lord PE (again) to add binary data manually.

This is not difficult but requires hardworking and careful, Good luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.