Essay : Cracking a thermal simulation program - Written by MTB.

Published by +Tsehp Dec 2001




Sentinnel dongle





w32dsm89 for a check not really necessary (usefull for quick string searching)


IDA PRO 4.04

with the following plugins

  CyberHeg for Ida Hasp plugin

  killer_3k for Ida Sentinel SuperPro plugin

  Amante4 for Ida string plugin

  All formerly available on crackz'z site, who knows where now.


Some experience using IDA (this really helps)


HIEW (a good Hex editor)


A brain and time


Usefull Tutorials



Dongle Bashing by Frog's print

Zen and the Art of Dongle Cracking by zeezee

+HCU's special Project: 'How to undongle' All of it!

Dongle reverse engineering by Zafer/BSCA


Program history



This program is a graphics front end for SINDA and Trasys.  Besides being able

to write out a Sinda, etc decks it can also run it's own biult in

Sinda solver in graphical form.


You can get it by asking, go to


go to demo download, follow the instructions.   Hint say you are

analyzing circuit cards or heat exchangers.





To enable a newbie with proper tools, to reverse engineer a target

to make it usable ie, it can run without limitation, open files and

save files.   Note the save in this program works via a work around.


We will NOT be doing any fancy emulation of dongles in this tutorial.

Just JMP's and NOP's, lots of them.


The key is for you the newbie to find the dongle calls, and go UP in

the code to locate where that information is used!   This is not as

simple as it seems.   In this example I named the routines by either

the error messages they printed out, or by what I think they are called

for.   This is why IDA is used.


Running program



We first get the nasty nag running in demo mode key not found blah,

blah etc.


Now lets attack it with IDA, apply the sentinel dongle sigature and

go to bed it will take a while.


Save the IDA file to text form.  Using a text editor search for "demo".

The reason why you doing in a text editor is because IDA is SLOW for

text searches, even on a 1000MHz machine.   You also could use the

IDA string pluggin (if you can find it).



This first bit of a subroutine I named "help about"


0059B352          push edi

0059B353          cmp  [ebp+110h], ebx

0059B359          jz   loc_59B3E2            << this jump happens

0059B35F          lea  ecx, [esp+1E0h+var_1CC]


0059B3C1          push edx

0059B3C2          call sub_4C8A90

0059B3C7          or   edi, 0FFFFFFFFh

0059B3CA          lea  ecx, [esp+1E0h+var_1CC]

0059B3CE          mov  [ebp+108h], eax

0059B3D4          mov  [esp+1E0h+var_4], edi

0059B3DB          call ??1CString@@QAE@XZ ; CString::~CString(void)

0059B3E0          jmp  short loc_59B412 ;



0059B3E2 loc_59B3E2:                      ; CODE     XREF: help_about?+29j

0059B3E2          mov  ecx, ebp

0059B3E4          call software_maintance_has_expired  << see below

0059B3E9          cmp  eax, ebx

0059B3EB          mov  [ebp+108h], eax   << NOP

0059B3F1          jz   short loc_59B40F  << JMP

0059B3F3          lea  ecx, [ebp+334h]

0059B3F9          call time_limited_dongle

0059B3FE          test eax, eax

0059B400          jz   short loc_59B40F

0059B402          mov  ecx, ebp

0059B404          call check_for_demo_mode

0059B409          mov  [ebp+108h], eax ;  1 or 0


0059B40F loc_59B40F:                      ; CODE     XREF: help_about?+C1j

0059B40F                            ; help_about?+D0j

0059B40F          or   edi, 0FFFFFFFFh


0059B412 loc_59B412:                      ; CODE     XREF: help_about?+B0j

0059B412          cmp  [ebp+108h], ebx ; << NOP

0059B418          jnz  short good_jump ; << change to JMP

0059B41A          push ebx

0059B41B          push ebx

0059B41C          push offset     aThisProgramIsN   ; "This     program     is not licensed\nRunning in"...

0059B421          call sub_641FE9 ; ?AfxMessageBox@@YGHPBDII@Z

0059B421                            ; doubtful name


0059B426 good_jump:                       ; CODE     XREF: help_about?+E8j

0059B426          lea  ecx, [esp+1E0h+var_19C]

0059B42A          call ??0CCommandLineInfo@@QAE@XZ ; CCommandLineInfo::CCommandLineInfo(void)





0059BEC0 software_maintance_has_expired   proc near ; CODE XREF: help_about?+B4p

0059BEC0                            ; .text:0059C3A3p

0059BEC0          push esi

0059BEC1          mov  esi, ecx

0059BEC3          push edi

0059BEC4          mov  eax, [esi+7F8h]

0059BECA          mov  ecx, [esi+124h]

0059BED0          lea  edi, [esi+334h]

0059BED6          push eax

0059BED7          push ecx

0059BED8          mov  ecx, edi

0059BEDA          call check_key_3      ;

0059BEDF          test eax, eax             << NOP

0059BEE1          jnz  short loc_59BEE6     << NOP

0059BEE3          pop  edi

0059BEE4          pop  esi

0059BEE5          retn


Obviously you do NOT want to execute ANY of the code below!




0059BEE6 loc_59BEE6:                      ; CODE     XREF: software_maintance_has_expired+21j

0059BEE6          mov  ecx, edi

0059BEE8          call call_check_key_2

0059BEED          cmp  eax, 1

0059BEF0          jnz  short loc_59BF1F

0059BEF2          mov  eax, [esi+124h]

0059BEF8          push 0

0059BEFA          cmp  eax, 2

0059BEFD          push 0

0059BEFF          jnz  short loc_59BF15

0059BF01          push offset     aYourSoftwareMa   ; "Your     software maintenance has expired, "...

0059BF06          call sub_641FE9 ; ?AfxMessageBox@@YGHPBDII@Z

0059BF06                            ; doubtful name

0059BF0B          mov  ecx, edi

0059BF0D          call is_the_key_attached

0059BF12          pop  edi

0059BF13          pop  esi

0059BF14          retn



0059BF15 loc_59BF15:                      ; CODE     XREF: software_maintance_has_expired+3Fj

0059BF15          push offset     aYourSoftware_0   ; "Your     software maintenance has expired, "...

0059BF1A          call sub_641FE9 ; ?AfxMessageBox@@YGHPBDII@Z

0059BF1A                            ; doubtful name


0059BF1F loc_59BF1F:                      ; CODE     XREF: software_maintance_has_expired+30j

0059BF1F          mov  ecx, edi

0059BF21          call is_the_key_attached

0059BF26          pop  edi

0059BF27          pop  esi

0059BF28          retn

0059BF28 software_maintance_has_expired   endp



All we did is by pass the messages!  The programers gave us the flags to follow.  If the messages

where not in the code obviously this becomes a more difficult task!!  But don't worry, almost

every program will have these stupid messages.  (See Dongle Bashing by Frog's Print).


Now run the program, those nasty greetings dissapear!



The next step is to be able to export the model.  We find this piece of code called by

all these nice exporting functions.


0059BF30 top_level_key_check proc near           ; CODE XREF: .text:0059BFCBp

0059BF30                                         ; send_the_model+46p

0059BF30                                         ; export_the_model+46p

0059BF30                                         ; export_the_model_3+46p

0059BF30                                         ; export_the_model_4+46p

0059BF30                                         ; export_and_solve_model+34p

0059BF30                                         ; export_and_solve_transient+34p

0059BF30                                         ; unknown_security_check+18p

0059BF30                                         ; .text:005A9438p

0059BF30                                         ; .text:005A94A8p

0059BF30                 push    esi

0059BF31                 mov     esi, ecx

0059BF33                 mov     eax, [esi+110h]  << looks familiar

0059BF39                 test    eax, eax         << NOP

0059BF3B                 jz      short loc_59BF57 << NOP

0059BF3D                 mov     eax, [esi+7F4h]

0059BF43                 lea     ecx, [esi+7C8h]

0059BF49                 push    eax

0059BF4A                 call    sub_4C8A90

0059BF4F                 mov     [esi+108h], eax

0059BF55                 pop     esi

0059BF56                 retn

0059BF57 ; ---------------------------------------------------------------------------


0059BF57 loc_59BF57:                             ; CODE XREF: top_level_key_check+Bj

0059BF57                 lea     ecx, [esi+334h]

0059BF5D                 call    is_the_key_attached << obviously we don't want to call this

0059BF62                 mov     [esi+108h], eax

0059BF68                 pop     esi

0059BF69                 retn

0059BF69 top_level_key_check endp



first call


005A3FF0 send_the_model  proc near               ; CODE XREF: .text:004C20A9p


005A3FF0 var_5FC         = qword ptr -5FCh


005A4015                 call    sub_5ACFD0

005A401A                 test    eax, eax

005A401C                 jz      loc_5A444A

005A4022                 call    ?AfxGetModuleState@@YGPAVAFX_MODULE_STATE@@XZ ; AfxGetModuleState(void)

005A4027                 mov     esi, [eax+4]

005A402A                 mov     eax, [esi+108h]

005A4030                 test    eax, eax

005A4032                 jz      short loc_5A4045

005A4034                 mov     ecx, esi

005A4036                 call    top_level_key_check

005A403B                 mov     eax, [esi+108h]

005A4041                 test    eax, eax        ; << NOP the test

005A4043                 jnz     short loc_5A4064 ;<< JMP


005A4045 loc_5A4045:                             ; CODE XREF: send_the_model+42j

005A4045                 cmp     dword ptr [edi+84h], 12Ch

005A404F                 jle     short loc_5A4064

005A4051                 push    0

005A4053                 push    0

005A4055                 push    offset aCannotExportOv ; "Cannot export over 300 nodes in demo mo"...

005A405A                 call    sub_641FE9      ; ?AfxMessageBox@@YGHPBDII@Z

005A405A                                         ; doubtful name

005A405F                 jmp     loc_5A444A

005A4064 ; ---------------------------------------------------------------------------


005A4064 loc_5A4064:                             ; CODE XREF: send_the_model+53j

005A4064                                         ; send_the_model+5Fj

005A4064                 push    edi

005A4065                 lea     ecx, [esp+4BCh+var_49C]

005A4069                 call    sub_47B110

005A406E                 push    0

005A4070                 push    4

005A4072                 push    offset aCompactNodesBe ; "Compact nodes before exporting?"

005A4077                 mov     [esp+4C4h+var_4], 0

005A4082                 mov     esi, 1


Now there are several other routines that use the exact logic, it is your mission to FIX it.



005A79B0 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦



005A79B0 export_and_solve_model proc near        ; CODE XREF: .text:004C1F39p



005A79CE                 mov     esi, ecx

005A79D0                 call    ?AfxGetModuleState@@YGPAVAFX_MODULE_STATE@@XZ ; AfxGetModuleState(void)

005A79D5                 mov     edi, [eax+4]

005A79D8                 xor     ebx, ebx

005A79DA                 cmp     [edi+108h], ebx

005A79E0                 jz      short loc_5A79F1

005A79E2                 mov     ecx, edi

005A79E4                 call    top_level_key_check

005A79E9                 cmp     [edi+108h], ebx    << NOP

005A79EF                 jnz     short loc_5A7A0F ; << JMP


005A79F1 loc_5A79F1:                             ; CODE XREF: export_and_solve_model+30j

005A79F1                 cmp     dword ptr [esi+84h], 12Ch

005A79FB                 jle     short loc_5A7A0F

005A79FD                 push    0FFFFFFFFh

005A79FF                 push    ebx

005A7A00                 push    0F00Ah

005A7A05                 call    ?AfxMessageBox@@YGHIII@Z ; AfxMessageBox(uint,uint,uint)

005A7A0A                 jmp     exit_subroutine


Notice this bit of sneaky code, we check a different value for a flag to see weather we are

permitted to solve the model, or just export it.  FYI I missed this the first time through!

005A7A0F ; ---------------------------------------------------------------------------


005A7A0F loc_5A7A0F:                             ; CODE XREF: export_and_solve_model+3Fj

005A7A0F                                         ; export_and_solve_model+4Bj

005A7A0F                 cmp     dword ptr [edi+124h], 2 ; NOP

005A7A16                 jnz     short loc_5A7A24 ; JMP

005A7A18                 mov     ecx, esi

005A7A1A                 call    compact_nodes_b4_exporting

005A7A1F                 jmp     exit_subroutine

005A7A24 ; ---------------------------------------------------------------------------


005A7A24 loc_5A7A24:                             ; CODE XREF: export_and_solve_model+66j


Now there is another set of calls just like the one above, go and find it!


The last part of this excercise is the first piece of code that calls our checking routine.

Notice the cmp to 2, and jnz after it.  Look up a few lines, what did we do?   Good now do it

again.  Now was that hard?  It just takes patience!


The first thing calls top_level_check_key, skip this for the moment

0059BFCB                 call    top_level_key_check

0059BFD0                 cmp     dword ptr [esi+124h], 2 

0059BFD7                 jnz     short loc_59C02E        

0059BFD9                 lea     ecx, [esp+4]

0059BFDD                 call    display_version


0059C01B                 call    ??1CString@@QAE@XZ ; CString::~CString(void)

0059C020                 mov     dword ptr [esp+74h], 0FFFFFFFFh

0059C028                 lea     ecx, [esp+4]

0059C02C                 jmp     short loc_59C081

0059C02E ; ---------------------------------------------------------------------------


0059C02E loc_59C02E:                             ; CODE XREF: .text:0059BFD7j

0059C02E                 lea     ecx, [esp+4]

0059C032                 call    display_version_2

0059C037                 lea     ecx, [esp+4]


0059C070                 call    ??1CString@@QAE@XZ ; CString::~CString(void)

0059C075                 mov     dword ptr [esp+74h], 0FFFFFFFFh

0059C07D                 lea     ecx, [esp+4]



I haven't a clue what difference between display_version and 2 is?


The last thing to fix is right below, see above!  The other way is do a NOP and JMP, if

it doesn't work try NOP and NOP!


005A87B0 unknown_security_check proc near        ; DATA XREF: .rdata:0069C350o

005A87B0                                         ; .rdata:006AB208o

005A87B0                 push    esi

005A87B1                 push    edi

005A87B2                 mov     edi, ecx

005A87B4                 call    ?AfxGetModuleState@@YGPAVAFX_MODULE_STATE@@XZ ; AfxGetModuleState(void)

005A87B9                 mov     esi, [eax+4]

005A87BC                 mov     eax, [esi+108h]

005A87C2                 test    eax, eax

005A87C4                 jz      short loc_5A87D7

005A87C6                 mov     ecx, esi

005A87C8                 call    top_level_key_check

005A87CD                 mov     eax, [esi+108h]

005A87D3                 test    eax, eax            << NOP

005A87D5                 jnz     short loc_5A87E0    << JMP


005A87D7 loc_5A87D7:                             ; CODE XREF: unknown_security_check+14j

005A87D7                 mov     eax, [edi]

005A87D9                 push    0

005A87DB                 mov     ecx, edi

005A87DD                 call    dword ptr [eax+64h]


005A87E0 loc_5A87E0:                             ; CODE XREF: unknown_security_check+25j

005A87E0                 mov     ecx, edi

005A87E2                 call    sub_63EA55

005A87E7                 pop     edi

005A87E8                 pop     esi

005A87E9                 retn

005A87E9 unknown_security_check endp ; sp = -4


How long should this take you?  Good question, it took overnight to dissassemble, then 5 nights

to fix the code, where most of the time was spent naming subroutines and finding error messages.


Ok what about the save, easy in the first menu just hit reinitialize key, it will bring the save

and saveas buttons back for one use until you hit the reinitialize key again.


The secret to this patience, and half a brain (+fravia).


Greetz go to :



+fravia for showing the way

crackz for putting it all together for me

CyberHeg for Ida Hasp plugin

killer_3k for Ida Sentinel SuperPro plugin

Amante4 for Ida string plugin

And all those fellow crackers who write tutorials