Page 1 of 2 12 LastLast
Results 1 to 15 of 17

Thread: IDA Pro, find out what created the object

  1. #1

    IDA Pro, find out what created the object

    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?

  2. #2
    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.)

  3. #3
    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?

  4. #4
    ::[ Reverse Engineer ]:: OHPen's Avatar
    Join Date
    Nov 2002
    Blog Entries

    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

    - Reverse Enginnering can be everything, but sometimes it's more than nothing. Really rare moments but then they appear to last ages... -

  5. #5
    Break at 0x007718A8.

    .text:00771850 sub_771850      proc near               ; CODE XREF: sub_771D70+66p
    .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                 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 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 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...

    ew, its breaking over 100 times at that location 0.o
    Last edited by RCE; April 18th, 2011 at 11:06.

  6. #6
    Quote Originally Posted by RCE View Post
    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?

  7. #7
    The final goal is to hook the function that created a certain object.

  8. #8
    Quote Originally Posted by RCE View Post
    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..

  9. #9
    Quote Originally Posted by RCE View Post
    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.

  10. #10
    The application only loads the default dll's on windows.
    	.text:00542DC7 movss   xmm0, dword ptr [esi+24]
    Object 1:
            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:
    	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:
    	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.

  11. #11
    Registered User
    Join Date
    Feb 2004
    Hi !

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

    .text:00771850 sub_771850      proc near               ; CODE XREF: sub_771D70+66p
    .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                 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:

    !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:

    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.
    Last edited by Neitsa; May 8th, 2011 at 08:05. Reason: typos
    Omne tulit punctum qui miscuit utile dulci

  12. #12
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Blog Entries
    I'll say it first. Nice explanation Neitsa


  13. #13
    Quote Originally Posted by Kayaker View Post
    I'll say it first. Nice explanation Neitsa

    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.

  14. #14
    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.

  15. #15
    Registered User
    Join Date
    Feb 2004

    Thank you for your kind words guys


    @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):

    class A{ // abstract
        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;};
        int iprivA1;
        int iprivA2;
    class B: public A{
        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"); }
        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;
    Omne tulit punctum qui miscuit utile dulci

Similar Threads

  1. COM object DLL?
    By FrankRizzo in forum Advanced Reversing and Programming
    Replies: 1
    Last Post: July 12th, 2013, 14:18
  2. The kernel object namespace and Win32, part 1
    By Nynaeve in forum Blogs Forum
    Replies: 0
    Last Post: April 24th, 2008, 09:42
  3. wibu - COM object used
    By Ziggy in forum The Newbie Forum
    Replies: 1
    Last Post: August 22nd, 2005, 07:40
  4. problem extract resources from exe created by meta card?
    By thematrix in forum Advanced Reversing and Programming
    Replies: 14
    Last Post: November 13th, 2003, 05:10
  5. How do I debug IE plugins like an OCX object?
    By zhudachang in forum OllyDbg Support Forums
    Replies: 1
    Last Post: July 3rd, 2003, 06:41


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts