Log in

View Full Version : IDA Pro, find out what created the object


RCE
April 14th, 2011, 16:14
In IDA Pro I found 3 objects all instantiated from the same class.
I also found a variable that holds the total number of these objects.

Because of this, I assume that these objects are created by a manager class. What do I need to do to figure out which function created these objects?

anom
April 15th, 2011, 04:45
Quote:
I also found a variable that holds the total number of these objects.

Either that's a static variable of the class you got objects of or it's a variable of that manager class. Let's hope the latter so xref should do the trick. You can also try to set a hardware bp on write on the locations the objects this pointer reside in.

(Assuming debugging is feasible.)

RCE
April 17th, 2011, 08:41
When I do so I end up with the Object Manager. But I do not recognize the function that creates these objects.

Isn't there a way to trace back to the creating from the object?

OHPen
April 18th, 2011, 10:23
Hi,

anom is right. Use these two possibilities to track where the counter is increased. Probably you will directly break in the function which is creating all the object.

When you found that function, restart with same breakpoint settings and see if you break before you objects are created. if that is the case you got what you want.

Usually objects are created by calling the constructor of a class. as the constructor function pointer should be part of the vtable which contains all the instance method points you can set an breakpoint on all of those functions and restart again with these settings. you will then break in one of these functions, the constructor because the constructor is the first function which is called when a object is created.

just return from the constructor call and you will see where the "real" object creation happend. but be carefully it is not 100% for sure that the object will be fully initialized at the point. i cannot go into detail as it depends on the compiler who generated the code...

there are a lot of ways to get what you want just take the two approaches anom pointed out or use the vtable-pointer approach. all will work!! ;D

regards,
OHPen

RCE
April 18th, 2011, 11:01
Break at 0x007718A8.

Code:
.text:00771850 sub_771850 proc near ; CODE XREF: sub_771D70+66p
.text:00771850
.text:00771850 var_28 = dword ptr -28h
.text:00771850 var_24 = dword ptr -24h
.text:00771850 var_20 = dword ptr -20h
.text:00771850 var_1C = dword ptr -1Ch
.text:00771850 var_18 = dword ptr -18h
.text:00771850 var_14 = dword ptr -14h
.text:00771850 var_10 = byte ptr -10h
.text:00771850
.text:00771850 push ebp
.text:00771851 mov ebp, esp
.text:00771853 and esp, 0FFFFFFF0h
.text:00771856 sub esp, 34h
.text:00771859 push ebx
.text:0077185A mov ebx, ecx
.text:0077185C mov eax, [ebx+48h] ; Move value of EBX+48 into EAX (Object Instantiation?)
.text:0077185F xor ecx, ecx
.text:00771861 cmp eax, ecx ; ?
.text:00771863 push esi
.text:00771864 push edi
.text:00771865 mov [esp+40h+var_28], ecx
.text:00771869 mov [ebx+60h], ecx
.text:0077186C mov [ebx+68h], cl
.text:0077186F mov [ebx+69h], cl
.text:00771872 mov [ebx+6Ah], cl
.text:00771875 mov dl, 1
.text:00771877 jz short loc_7718C8
.text:00771879 mov edi, eax ; Move address of Object into EDI
.text:0077187B jmp short loc_771880
.text:0077187B ; ---------------------------------------------------------------------------
.text:0077187D align 10h
.text:00771880
.text:00771880 loc_771880: ; CODE XREF: sub_771850+2Bj
.text:00771880 ; sub_771850+76j
.text:00771880 mov eax, edi ; Move address of Object into EAX
.text:00771882 mov esi, [eax] ; Move value of Object into ESI
.text:00771884 test esi, esi ; ?
.text:00771886 mov edi, [edi+4] ; Move member variable (+4) into ESI
.text:00771889 jz short loc_7718C4
.text:0077188B mov cl, [esi+1405h]
.text:00771891 test cl, cl
.text:00771893 jz short loc_77189D
.text:00771895 add [esp+40h+var_28], 1
.text:0077189A or [ebx+68h], cl
.text:0077189D
.text:0077189D loc_77189D: ; CODE XREF: sub_771850+43j
.text:0077189D mov ecx, [eax] ; Move Object in ECX
.text:0077189F cmp byte ptr [ecx+1404h], 0 ; Compare object against null
.text:007718A6 jz short loc_7718B7 ; Skip counter if object not created
.text:007718A8 add dword ptr [ebx+60h], 1 ; Add 1 to object count


Am I correct that the object is created at 0x0077185C ?

This application is compiled with visual studio 2005 or visual C++ ver. 8. So I kinda expected a new operator...

*edit
ew, its breaking over 100 times at that location 0.o

WaxfordSqueers
May 3rd, 2011, 13:15
Quote:
[Originally Posted by RCE;90059]In IDA Pro I found 3 objects all instantiated from the same class.
I also found a variable that holds the total number of these objects. Because of this, I assume that these objects are created by a manager class. What do I need to do to figure out which function created these objects?


I am probably sticking my nose in where it doesn't belong. You did not say what your aim is in using objects and classes as applied to an IDA disassembly. Forgive me for being presumptive, but if you are trying to find the caller of a function there are other ways to go about it, even when the xrefs are missing.

Are you just trying to find the caller, or are you trying to reconstruct the source code? Or are you writing programs in C++ to see what they look like disassembled in IDA?

RCE
May 3rd, 2011, 16:43
The final goal is to hook the function that created a certain object.

WaxfordSqueers
May 3rd, 2011, 21:24
Quote:
[Originally Posted by RCE;90205]The final goal is to hook the function that created a certain object.
In IDA, you are looking at assembly code. Although the assembly code may be disassembled from an OOP app, I find it unhelpful to think in terms of objects and other OOP jargon.

Of course, I have a background in computer hardware and electronics and OOP is an abstraction of real devices. If you have an OOP background, it may be helpful for you to think in those terms, but it seems to take away from the reality you are dealing with.

I also began with languages like Fortran, Basic and Assembly, before OOP became popular. I still tend to think in terms of functions and sub-routines, although that is discouraged in modern programming. Still, programs are nothing more than code that is executed in a linear mode, even if they are modular.

Windows has a beginning, a loop and an exit routine. I think of the loop winmain() as one long series of sub-routines that loop continuously till an exit function is called. At least, it is after it does its housekeeping, liking setting up windows, etc.

When I use IDA, I do so at a basic level, not bothering to reconstruct the disassembly to any degree. I realize it is probably better with more complex apps to re-organize the IDA output better. However, sometimes if you are just looking for a function that called another function, and it is not cross-referenced in IDA, it might be more helpful to think in terms of assembly than in OOP.

At my level, it is sometimes not possible for me to find the calling function, possibly because the code belonged to a dll that was not disassembled. I'm wondering if you are aware that an app sometimes calls out to a dll that calls back into the app. Maybe the calling code is not in your app.

Perhaps I am being overly simplistic and presuming too much..

WaxfordSqueers
May 3rd, 2011, 22:11
Quote:
[Originally Posted by RCE;90205]The final goal is to hook the function that created a certain object.
Without naming the app you are working on, can you say what it does and what it is your are trying to do?

Saying you are trying to a hook a function that created an object is too narrow for my liking. Why are you trying to hook the function? Are you trying to redirect it to code you have written?

What do you want the code to do?

As far as what you are trying to do, there are two replies that offer suggestions. Do you understand what they are getting at with regard to vtables? If not, ask for clarification. There may be simpler ways of dealing with your hooking problem.

RCE
May 4th, 2011, 04:41
The application only loads the default dll's on windows.
--------------------------
Breakpoint:
Code:
.text:00542DC7 movss xmm0, dword ptr [esi+24]


Object 1:
Code:
debug069:157AA4AC db 54h ; T
debug069:157AA4AD db 0CAh ; -
debug069:157AA4AE db 0C0h ; +
debug069:157AA4AF db 0
debug069:157AA4B0 db 0F9h ; ·
debug069:157AA4B1 db 4Dh ; M
debug069:157AA4B2 db 0
debug069:157AA4B3 db 0Fh
debug069:157AA4B4 db 0
debug069:157AA4B5 db 0
debug069:157AA4B6 db 0
debug069:157AA4B7 db 0
debug069:157AA4B8 db 0
debug069:157AA4B9 db 0
debug069:157AA4BA db 0
debug069:157AA4BB db 0
debug069:157AA4BC db 0
debug069:157AA4BD db 0
debug069:157AA4BE db 80h ; Ç
debug069:157AA4BF db 3Fh ; ?
debug069:157AA4C0 db 0
debug069:157AA4C1 db 0
debug069:157AA4C2 db 0
debug069:157AA4C3 db 0
debug069:157AA4C4 db 0 ; break
...


Object 2:
Code:
debug069:1581C6FC db 54h ; T
debug069:1581C6FD db 0CAh ; -
debug069:1581C6FE db 0C0h ; +
debug069:1581C6FF db 0
debug069:1581C700 db 0F9h ; ·
debug069:1581C701 db 4Dh ; M
debug069:1581C702 db 0
debug069:1581C703 db 0Fh
debug069:1581C704 db 0
debug069:1581C705 db 0
debug069:1581C706 db 0
debug069:1581C707 db 0
debug069:1581C708 db 0
debug069:1581C709 db 0
debug069:1581C70A db 0
debug069:1581C70B db 0
debug069:1581C70C db 0
debug069:1581C70D db 0
debug069:1581C70E db 80h ; Ç
debug069:1581C70F db 3Fh ; ?
debug069:1581C710 db 0
debug069:1581C711 db 0
debug069:1581C712 db 0
debug069:1581C713 db 0
debug069:1581C714 db 0 ; break
...


Object 3:
Code:
debug069:1585F6DC db 54h ; T
debug069:1585F6DD db 0CAh ; -
debug069:1585F6DE db 0C0h ; +
debug069:1585F6DF db 0
debug069:1585F6E0 db 0F9h ; ·
debug069:1585F6E1 db 4Dh ; M
debug069:1585F6E2 db 0
debug069:1585F6E3 db 0Fh
debug069:1585F6E4 db 0
debug069:1585F6E5 db 0
debug069:1585F6E6 db 0
debug069:1585F6E7 db 0
debug069:1585F6E8 db 0
debug069:1585F6E9 db 0
debug069:1585F6EA db 0
debug069:1585F6EB db 0
debug069:1585F6EC db 0
debug069:1585F6ED db 0
debug069:1585F6EE db 80h ; Ç
debug069:1585F6EF db 3Fh ; ?
debug069:1585F6F0 db 0
debug069:1585F6F1 db 0
debug069:1585F6F2 db 0
debug069:1585F6F3 db 0
debug069:1585F6F4 db 0 ; break
...


Not sure where to go from here.

Neitsa
May 7th, 2011, 11:46
Hi !

The function that you are analyzing is probably a thiscall function:

Code:

.text:00771850 sub_771850 proc near ; CODE XREF: sub_771D70+66p
.text:00771850
.text:00771850 var_28 = dword ptr -28h
.text:00771850 var_24 = dword ptr -24h
.text:00771850 var_20 = dword ptr -20h
.text:00771850 var_1C = dword ptr -1Ch
.text:00771850 var_18 = dword ptr -18h
.text:00771850 var_14 = dword ptr -14h
.text:00771850 var_10 = byte ptr -10h
.text:00771850
.text:00771850 push ebp
.text:00771851 mov ebp, esp
.text:00771853 and esp, 0FFFFFFF0h
.text:00771856 sub esp, 34h
.text:00771859 push ebx
.text:0077185A mov ebx, ecx ; ebx = ecx = this* pointer
.text:0077185C mov eax, [ebx+48h] ; eax = object member


If you want to find who (where was) created the class instance (lying in the ecx register on function entry), you might need to check on callers of this function.

BP on the function at 0x00771850 and check caller on the stack. You'll need to track down where the ecx register comes from.

Usually, object instances are allocated on the heap (use the 'new' C++ keyword) so you'll probably find a function which ultimately calls HeapAlloc() and set the ecx register with the result returned by this API. (if the object is on the stack, it is probably not very far from this function).

It might gets complicated on big programs where an object can be allocated long before (in terms of assembly lines executed) its real use, or when backtracking where the ecx register comes from gets messy.

In this case I tend to go with Windbg to find where the object (the pointer in ecx register) was allocated.

Windbg + gflags: start gflags -> "Image File" tab -> enter the name of the application in the edit box -> press 'Tab'. check "Enable Heap Tagging" + "Enable Heap Tagging by DLL" (not necessarily needed, but that doesn't do any harm).
The important thing is to check "Create User mode stack trace database" and then "Enable stack backtrace". Enter an appropriate value (I usually use "64". Press "apply" then "ok".

Start your app under windbg (or attach) and then BP at 0x00771850, then:

Code:

!heap -p -a @ecx


You should get a stack backtrace of where the object was allocated (that is, when the 'new' was done).

If you want to track the member at offset +0x48, do the same as above and then put a HBP at offset 0x48:

Code:

ba w 4 @ecx+48


It should break when the member is set. From there you might need to track where this member was allocated once again...

Tracking object instantiation has never been so easy when you know the trick. It's damn cool for "use after free" errors and other bugs that are quite tricky.

Hope it helps.

Kayaker
May 7th, 2011, 14:01
I'll say it first. Nice explanation Neitsa

Regards,
Kayaker

WaxfordSqueers
May 7th, 2011, 16:25
Quote:
[Originally Posted by Kayaker;90236]I'll say it first. Nice explanation Neitsa

Regards,
Kayaker
I'll second that. Neitsa's explanation shows me how far out of the loop I have gotten but it also encourages me to crack open Windbg and learn it. I have been lost without Softice.

Either that, or fix ice to run on Win 7

Good stuff, Neatsa.

RCE
May 8th, 2011, 05:33
Yea, thanks for that Neitsa.
I understand what your saying and why it will work. Having some trouble getting everything to run in Windbg, ill report back when I got it working.

Neitsa
May 8th, 2011, 08:56
Hello,

Thank you for your kind words guys

@Kayaker:

@WaxfordSqueers : I really loved Softice and I used it a lot too, but the lack of support for latest Microsoft O.S was a decisive factor of change for me. From my POV Windbg has now a lot of advantages over Sice and it is really powerful when you begin to master it. The main problem with this power is that it is quite difficult to get used to at first: it has numerous commands, each commands as numerous switches, the documentation is huge and the GUI is not user friendly, but it really worth the try

@RCE : If you have problems with the application you are currently analyzing, you might try to break the problem into something simpler. Throw some C++ code into your favorite editor, compile it and checks the result in your favorite debugger / disassembler.

(Note: You may already know a lot of things about C++ reversing and the problem may be that your application is overly complex. In this case do not take into account the following advice.)

With the help of a simple C++ code, try to get the location where object are instantiated, step into functions and see how the this* pointer is passed, how the vftable (virtual function table) is used, how function member pointers are retrieved and used, how data members are set, etc.

If you compile it with Visual studio you'll get symbols support which makes things easier to understand. Olly (the 2.0 alpha 3 is quite good with symbols) , IDA and Windbg have full symbolic debugging enabled.

When you feel confident with it try to implement other things (protected functions and members, friend classes, multiple inheritance, copy ctor, overloaded functions and operators, etc.).

Something like that (sorry, dummy code not really tested):

Code:

class A{ // abstract
public:
A() { printf(" In A::ctor()\n"; }
~A() { printf(" In A::dtor()\n"; }
virtual void vfunc1() = 0; // pure virtual
virtual void vfunc2() { printf(" In A::vfunc2()\n"; }
virtual void vfunc3() { printf(" In A::vfunc3()\n"; }
virtual void vfunc4() { printf(" In A::vfunc4()\n"; }
virtual void setIPrivA1(int i = 0) { this->iprivA1 = i;};
virtual int getIPrivA1() { return this->iprivA1;};

private:
int iprivA1;
int iprivA2;
};

class B: public A{
public:
B() { printf(" In B::ctor()\n"; }
~B() { printf(" In B::dtor()\n"; }
virtual void vfunc1() { printf(" In B::vfunc1()\n"; }
virtual void vfunc4() { printf(" In B::vfunc4()\n"; }
virtual void vfunc5() { printf(" In B::vfunc5()\n"; }

private:
int iprivB1;
int iprivB2;
};

int main (void){

A a = new B();

// tests ... call some funcs, do crazy things

delete a; a = NULL;

B b = new B();

// tests

delete b; b = NULL;

return 0;
}

WaxfordSqueers
May 8th, 2011, 15:52
Quote:
[Originally Posted by RCE;90240] Having some trouble getting everything to run in Windbg, ill report back when I got it working.


Found this helpful:

http://www.codeproject.com/KB/debug/windbg_part1.aspx

Unfortunately the author hasn't gotten around to writing part 2.

WaxfordSqueers
May 8th, 2011, 16:03
Quote:
[Originally Posted by Neitsa;90243]
@WaxfordSqueers : ....From my POV Windbg has now a lot of advantages over Sice and it is really powerful when you begin to master it.


I have to sit down with it for a bit. Is there anything Microsoft puts our that is easy to understand? They steadfastly refuse to put Internet Explorer out with a dual-window pane, not that I'd use it if they did. Last night, I spent hours trying to figure out why Windows 7 backup insists on doing full backups instead of incremental backups. One would think by now they'd have stuff like that down pat, but Microsoft seems intent on moving back to Unix.

BTW, Comodo puts out a free backup app for Win 7-32/64. Haven't tried it yet, but if it's as good as their free firewall, it will rock.

I think windbg should be a lot easier now that laptops are so freely available, as well as the ability to run an OS in a virtual window.