I’m not new to StackExchange, but I’m quite new to reverse engineering, so please be patient with me! 😛
At present I’m dealing with an executable that I would like to modify a little bit, for personal use; the source code of the application is not available so I can only modify it or die trying. I’m using both IDA Pro 6.1 and OllyDBG 2.0 as tools.
To be exact, I would just like to increase the amount of CFG_ENTRY that the application can read from
[EDIT 1 – All what I should have known since the beginning!]
After following the suggestions of the answer of @sealed…, I used a class inspector to detect the Virtual Function Table and I found the full class descriptor. Well… in fact there are two classes referring to my target method
[EDIT 2 – The adventure continues! Yay!]
After reading the answer of @Guntram Blohm, I investigated some more in order to collect and analyze the data he suggested. The first thing I did is to analyze the executable with PEiD and here is the information I got from it:
When I set a breakpoint on my
The, I digged a little bit more finding out the
So it looks like the “array” of
And following the address
It looks like a dead end to me…
It seems to me that the problem is a bit worse than you describe, and there’s no easy way to get around it.
First, @sealed seems to be right with the function being a class method, and your compiler passing the class pointer in
to make sense – other parameters are pushed on the stack, and the values of eax, edx and ebx seem not to be very meaningful, so the compiler doesn’t use some kind of parameters-in-registers fastcall abi.
Now, let me reorder the statements from the loop start to the call a bit (without changing the meaning, just to make a bit clearer what happens). The compiler spread the “increment the count by one” instructions between the others, probably to take advantage of pipelining within the processor:
This seems like ReadCfgEntry is a class method as well, which gets its
with ConfigurationEntry being a 996 byte class. Now, the bad news is: These two class members need 4+(500*996) bytes. This is equal to 498004, or 0x79954. So your entry count is directly behind the entries at 0x79954, with another variable at 0x79958:
Now, if the entries had been a pointer and allocated with
I was just about to post this, when i saw your edit to the question.
As you realized in your edit, you need to change all accesses to structure components behind the array of entries that you want to increase. You need to do this in your class methods (which you can find easily as you have the vtables), but also in the rest of your program (as you don’t know which of the original class variables where public and might be accessed from outside the class itself). Unfortunately, you can’t really automate that, because, for every occurence of, say 0x79954, you’d have to check if it’s an index into your class, or something else.
Since i don’t know which compiler was used to write your program, i can’t tell much about how it stores the function vtable. With a bit of luck, the first entry (the one i called
Then, there must be some allocator function for your classes. Since you seem to have a class called DATABASE_TABLE, and a derived one called CFG_DB, the second one is probably larger. Try finding the initializing method of this second, larger class. It should call
After you find where the class is instantiated, i’d probably try not to increase the array size from 500 to 1000, but, instead, just allocate a larger array behind the structure. For example, if your current function allocates 79a00h bytes, add the 996000d bytes to it that 1000 entries need, resulting in 16cca0h bytes. Then, change the
in front of ReadCfgEntry to
That way, you’ve created another array behind the current structure instead of extending the current one. Which means none of your structure offsets, except the config items themselves, have changed.
Speaking in C++, we just changed the class to
and in the next step we have to re-write all accessed to
Check your member functions for accesses to the original array, and replace them as well. The most simple way to do this is probably
Since the hardware breakpoint is on entries, chances are good that every access to an entry hits the 0-th of it at some point.
Also, since ReadCfgEntry is probably a class method, chances are good that there is a loop somewhere that just allocates one class instance for each entry – something like
Your hardware breakpoint should catch this loop quite quickly. Patch the executable to change the 500 to 1000, and the entries[i] calculation to your new array. After that, your new array will get initialized, but the old one will hold nothing but NULL pointers. Which means, you might get invalid memory acceses through those NULL pointers in the future, which help identifying accessed to your original array (that you can patch) as well.
Edit – Edit after reading OP’s 2nd answer
Dead end? Not at all, you gathered and posted very valuable information.
First, your pseudo code of the CFG_DB constructor
confirms that the 4 bytes at the beginning of the class structure are actually a pointer to the virtual function table of the class.
Second, your snippet
fits very well. (Again, i reordered the assembly instructions in a way that doesn’t change what they do, but makes it clearer to understand them). Remember your vtable that had a function offset, a nullsub, 3 more function offsets, and
Next, your constructor ends in
with the first parameter (v1+4) being the address of the ConfigurationEntries array within the Configuration class (i’m keeping my old invented variable/class names), the second parameter (0x3e4 == 996) the size of each array entry; the third (500) the number of entries, and a callback function. I’m almost sure this is the constructor function for the individual ConfigurationEntries. Which means this is the function i said you need to find, and which should be changed to
with XXXXX being the offset of the newEntries array once we allocate space for it.
Next, reconsidering a part of the code snippet before the indirect call to ReadConfigFile,
we see that there is a move to
Next, you found out the address 0190BD08, which is a very good thing. Along with the XREFs, and the data definition,
The class structure at that address is NOT allocated dynamically, and it is NOT initialized to anything, instead, it is an uninitialized global variable. In C++, it would have probably been a
with all the xrefs you’re seeing being a reference to myConfig. As the assembly instructions at those places are
i’m almost sure the calls to a class member function are one or 2 instructions after each of these. Congractulations, you’ve just found a way to catch many of the instances where the configuration gets accessed. To verify this, unk_190BD08 being a global variable for the configuration, you could run the program with a breakpoint on the constructor function (sub_8EEFC0), i bet it’s called only once, and 190BD08 is the parameter to it.
The bad thing about the configuration class instance being a static variable, not a new()-instantiated one, is that we can’t just increase the size in the new() call. Instead, we’ll have to move it to a part of the address space where it doesn’t disturb anything else – at the end of the current uninitialized data segment. Find the very last entry in your data segment, then choose a nice address behind that, and rewrite all the xrefs to unk_190BD08 to that new address. Then, run the program using ollydbg, place a hardware breakpoint on 190BD08 just in case, and check that the functions you know to be class member functions, and the initialized, all get the new address instead of 190BD08 as their
The fact that we’re missing a new() call for the Configuration variable means we can’t use its parameter to get the class size. But we already know the class size is at least 7A938h, so the static variable occupies the address space from 0x190BD08 to at least 0x1986640. With a bit of luck, your .data segment has that unk_190BD08 label, with the next label being at an address a bit after 0x1986640, so the next label is some other variable, and the difference between both labels the size of the Configuration instance.
There’s one thing left to do – when you move the configuration variable behind everything else, you’ll also have to increase the size of that data segment in the PE file. Unfortunately, i’m not that skilled in the windows PE file format, so i’d have to do a lot of research how to do this correctly myself, so maybe you’re lucky and someone else, who has more experience in this than i have, can help you with this.
Edit – Edit to answer to comment
The original C++ program will have had something like
(int as an example, the data type could be anything) and the compiler should place all of these varuables into the uninitialized part of the .data segment. Any access to one of the variables will make IDA create a label at that memory address, with an XREF to where it’s accessed. So, if your .data dump looks like this
and you know that 0190BD08 is your
This is not 100% foolproof, because if anything accesses globalConfig.somemember, with somemember having a structure offset of, say, 500000 (=0x7a120), then IDA will generate a label and an XREF at 0x190BD08+0x7a120=0x1985E28 ass well. But with a bit of luck, the “rest” of the program will just use the globalConfig variable as an argument to a member function, where references are indirect, so they won’t be used by IDA to create labels.
If they access anything but the 500 individual config entries, nothing at all, because these haven’t changed their offset. The thing that might be dangerous is when they access the entries, because those accesses should be rewritten to newEntries. You have to find out where they are (if you’re lucky, that’s just in the member functions) and patch the code at that point. The hardware breakpoint on the (old) entries address (which is 0x190BD0C in your case, structure start + 4) should help with this, because anything that’s likely to access any entry, is likely to access entry as well. So, if you hit the hardware breakpoint, on, say,
Unfortunately, you can’t create a hardware breakpoint that covers the whole structure to catch any access. That’s where the null pointer exceptions kick in. If, after the change, your program throws a NPE where it normally doesn’t, it’s probably because ‘something’ accessed the old array, which contains nothing but NULLs now, instead of the new one. Catching the NPE in the debugger, and checking the disassembly/call stack that lead to it, should give you an idea where the NULL pointer was read from the old array, so you know which instruction to change to point to the new one.