WuPiN G XiN BloG

It is All about Traffic, and Programming

Search

Archives

0 visitors online now
0 guests, 0 members

Inside Aimsun ANGApp.close

Aimsun ANGApp is a class available to python scripting. It is a very interesting class that TSS provides to its general users, and can be very powerful if the user really appreciates how it works.

In the past a few days, I have been cleaning up my previous codes, while working on a project proposal that may require Aimsun micro + meso. And for some reason, one code snippet that has worked previously crashes on ANGApp.close … …

This time I am pretty hesitant to write to TSS for help – though I am sure they are going to help, as always TSS is very kind and prompt in supporting their users – sometimes a little delay if they are busy. And for these couple of days, I know they are being working their tails off on the new release of Aimsun 6.1.0 – couldn’t be more busier.

So I decided not to bother them and find out myself.

All rightee ……the question is, what is really going on inside ANGAPP.close()? And why there is a crash? Let’s take a partial look at the code segment:

OK, save the current state of ESI by pushing it to stack. This is a no brainer.
.text:00B620E0 push esi

Note, ECX always holds the “this” pointer for C++ class. So, after mov ESI, ECX, ESI stores the starting address of the current ANGApp instance
.text:00B620E1 mov esi, ecx

Now, since ESI+0 is the starting address of the subject ANGApp instance, ESI + 8 must be the address for some private member-variable, and by looking at the instruction at 00B620EA , we can immediately get the hint that it must be the address for a GGui* pointer . Now, what about ESI + 4? Note the fact that ANGApp inherits from QObject, thus ESI+4 actually is the address for a protected pointer of type QObjectData. What about ESI+0xC? Hey, are you as curious as I am? That is a good question! That is actually the address for a pointer of type GKModel *.

Doh~!
.text:00B620E3 mov ecx, [esi+8]

IS the GGui* NULL?
.text:00B620E6 test ecx, ecx

.text:00B620E8 jz short loc_B620FC

If the GGui* is not NULL then call GGui.getActiveModel
.text:00B620EA call ds:__imp_?getActiveModel@GGui@@QBEPAVGKModel@@XZ ;

.text:00B620F0 mov ecx, [esi+8]

Now after invoking GGui.getActiveModel, EAX holds the returned pointer for GKModel
.text:00B620F3 push eax

Then GGui.closeDocument is called with the returned GKModel pointer from above instruction
.text:00B620F4 call ds:__imp_?closeDocument@GGui@@QAE_NPAVGKModel@@@Z

Okaydokay. So far so good! Now restore ESI.
.text:00B620FA pop esi
.text:00B620FB retn
.text:00B620FC ; —————————————————————————
.text:00B620FC

.text:00B620FC loc_B620FC:
[ESI + 0xC] is the address that holds the pointer of type GKModel*
.text:00B620FC mov ecx, [esi+0Ch]

Now ECX holds the pointer to GKModel
.text:00B620FF test ecx, ecx

.text:00B62101 jz short loc_B62112

Here is the tricky part. [ECX +0] is the address of the v-table of GKModel class
.text:00B62103 mov eax, [ecx]

Now EDX stores the address of the v-table of GKModel class
.text:00B62105 mov edx, [eax]

Index 1 means the first virtual function in the v-table. Note, GKModel inherits from GKObject. Therefore, the first virtual function in the v-table is the destructor ~GKObject()
.text:00B62107push 1

Now call the destructor
.text:00B62109 call edx

Reset the GKModel* pointer to zero.
.text:00B6210B mov dword ptr [esi+0Ch], 0

This is perfect code logically showing no problem at all! And it turns out that the crash was caused by a corrupted memoy I artificially manipulated which screw up ANGApp’s initernal data!