<html>
<head>
  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
  <META NAME="Author" CONTENT="NiXe">
  <META NAME="Classification" CONTENT="Reverse Code Engineering">
  <META NAME="Description" CONTENT="Step by step guide to cracking Linkbot Pro 4.0 Beta 1">
  <META NAME="KeyWords" CONTENT="How to crack Linkbot Pro 4.0 Beta 1">
  <TITLE>Linkbot Pro 4.0 Beta 1</TITLE>
  <style> <!-- A:HOVER {font-weight:bold;color:#3399FF} --> </style>
</head>

<body leftmargin="30" bgcolor="#000000" text="#e0e0e0" link="#d0d0ff" vlink="#ffd0d0">
<font face="Arial,Helvetica">

<center>
<table border="1" bordercolor="#AAAAAA" cellspacing="0" width="100%">
<TR BGCOLOR="#102030" align=center>
  <TD WIDTH="15%">
  <B><font color="#0B7FC1"><br>January 1999<br>&nbsp;</font></B>
  </TD>
  <TD WIDTH="70%" height="60">
  <FONT SIZE=+2 color="#0B7FC1">"Linkbot Pro 4.0 Beta 1"</FONT><br>'memory echo/patching'
  </TD>
  <TD WIDTH="15%">
  <B><font color="#0B7FC1">W32 PROGRAM</font></B><br>Code Reversing
  </TD>
</TR>

<TR BGCOLOR="#000000" align=center>
  <TD WIDTH="15%">
  </TD>
  <TD bgcolor="#102030" WIDTH="15%" height="55">
  by &nbsp;
  <FONT SIZE=+3>
  <font color="#F2F2FF">N</font>
  <font color="#E4E4FF">i</font>
  <font color="#D7D7FF">X</font>
  <font color="#C9C9FF">e</font>
  </font>
  </TD>
  <TD WIDTH="15%"></TD>
</TR>

<TR BGCOLOR="#000000" align=center>
  <TD WIDTH="15%"></TD>
  <TD bgcolor="#102030" height="40">Code Reversing For Beginners</TD>
  <TD WIDTH="15%"></TD>
</TR>

<TR bgcolor="#000000" align=center>
  <TD WIDTH="15%"></TD>
  <TD bgcolor="#102030"><br>
  <B>Program Details</B><br>
  <B>Program Name:</B> linkbot4.exe<br>
  <B>Program Type:</B> Web utility<br>
  <B>Program Location:</B> <A HREF="http://www.tetranetsoftware.com/download">Here</A><br>
  <B>Program Size: </B> 4.33 Mb<br>
  <br>
  </TD>
  <TD WIDTH="15%"></TD>
</TR>

<TR bgcolor="#000000" align=center>
  <TD WIDTH="15%"></TD>
  <TD bgcolor="#102030">
  <br><B>Tools Used:</B><br>
  Softice - Win'95 Debugger<br>
  W32Dasm - Win'95 Disassembler<br><br>
  </TD>
  <TD WIDTH="15%"></TD>
</TR>

<TR bgcolor="#102030" align=center>
  <TD>
  <font color="#0B7FC1"><B>Rating</B></font>
  </TD>
  <TD>
  <B><FONT SIZE=-1 color="#0B7FC1"><br>
  Easy ( X )&nbsp; Medium (  )&nbsp; Hard (  )&nbsp; Pro (  )</FONT></B><br>&nbsp;
  </TD>
  <TD><B><FONT SIZE=-1 color="#0B7FC1">Solving the puzzle</FONT></B></TD>
</TR>
</TABLE>
<br>
<br>
<br>
</center>


<!---------------------------------------------------------------------------->


<table border="1" bordercolor="#AAAAAA" cellpadding="2" cellspacing="0" bgcolor="#102030" width="100%">
  <tr><td width="100%" align=center>
  <font color="#0B7FC1" size=+2>Introduction</font></td></tr>
</table><br><br>
LINKBOT PRO: YOUR WEBRAGE CONTROL SYSTEM<br>
<br>
Linkbot Pro is a complete Website testing solution that can automatically scan a 
Website for more than fifty potential problems, generate graphical reports detailing 
what errors need to be fixed, and provide all the tools Web development teams need 
to ensure the accessibility, functionality and usability of their Websites.<br>
<br>
<br>

<table border="1" bordercolor="#AAAAAA" cellpadding="2" cellspacing="0" bgcolor="#102030" width="100%">
  <tr><td width="100%">
  <center><FONT color="#0B7FC1" SIZE=+2>About this protection system</FONT></center>
  </td></tr>
</table><br><br>

The beta 1 is a trial version and will expire the 16th of february.<br>
Even though this program is a trial version the registering function still works... so this
is a kind of <i>double crack me</i> ;-)<br> 
This main focus of this tutorial is on the registration function.<br>
<br>

To register go to the <b><u>H</u>elp</b> menu and choose 
<b><u>P</u>urchase...</b><br>
The instructions here says: <i>When you purchase Linkbot, Tetranet will provide
you with a serial and PIN numbre that will unlock the software.</i><br>
<br>
I used the following registering information:
<li>User Name: NiXe NiXe</li>
<li>Company: NiXe</li>
<li>Serial#: 8888</li>
<li>PIN: 999999</li>
<br>
<br>
I don't think this this information is saved at all...<br>
<br>
<br>
<br>

<table border="1" bordercolor="#AAAAAA" cellpadding="2" cellspacing="0" bgcolor="#102030" width="100%">
  <tr><td width="100%">
  <center><FONT color="#0B7FC1" SIZE=+2>The Essay</FONT></center>
  </td></tr>
</table><br><br>

<h2>PART 1 - The Registration Screen</h2><br>

Try to run Linkbot Pro 4.0 and enter something in the Linkbot Registration screen.<br>
If you get the message <i>"Please enter an integer between 1 and 100000000"</i> then do just that;-)<br>
Notice the text in the messagebox that pops up: <i>"Sorry, your PIN number is not valid for the
given serial number. Please try again"</i>. This gives us a clue about how the PIN number is
generated - it's probably calculated from the serial! Write down the bad guy message.<br>
<br>
Create a deadlisting in W32Dasm. Among the imported dll (Dynamic Link Library) files you will
find MFC42.DLL. This tell us that the program is written in Microsoft Visual C++ using Microsoft
Foundation Classes (MFC). We better include this MFC42.DLL in the SoftIce.Ini file! Include MSVCRT.DLL too.<br>
Now find the <i>"Sorry, your PIN number is not valid for the
given serial number. Please try again"</i> message. Study the surrounding code. Try to search
for the bad guy string again. Hey, the bad guy string appears many different places! This makes analysing
the deadlisting a bit more difficult because we don't know which bad guy string we got when
entering our invalid registration information.<br>
I think it's a very good idea to disassemble, analyse and print the interesting places of a 
program before starting to debug with SoftIce. But in this case we need to do a little bit of debugging 
in SoftIce to find serial/PIN check.<br>
<br>
Load Linkbot into SoftIce and go to the registration screen. Enter some registration information
and press <b>Ctrl+d</b> to enter SoftIce. Set a breakpoint at hmemcpy (<b>bpx hmemcpy</b>). Press
<b>Ctrl+d</b> to continue and press the OK button.<br>
Now SoftIce breaks just before <b>hmemcpy</b>. Step into the <b>hmemcpy</b> with <b>F10</b> until
you have excuted two <b>repz movsb</b> instructions (that's about 31 F10's). Now ds:esi points to 
just after where the string was being copied from and es:edi points just after where the string was copied to. 
In order to see what was copied simply do a <b>d es:edi-4</b> where 4 is the number of characters 
you'll see - if you only get the last part of your string you can increase 4 to the length 
of your string.<br>
The first data we see is our serial. Lets us follow the serial and monitor where it is read. Clear old breakpoints 
(<b>bc *</b>) and set a new breakpoint at read/write access to our serial (<b>bpr es:edi-4 es:edi rw</b>). 
If you do not remember the last 'rw' SoftIce only breaks on writes.<br>
Press <b>Ctrl+d</b> and SoftIce will break in MFC42!ORD_08f1+0074. Step with <b>F10</b> past MSVCRT!strtol. Now
EAX contains our serial as a number! A few lines below eax is moved to a new memory location 'MOV [ECX],EAX'.
Execute the 'MOV [ECX],EAX and clear old breakpoints (<b>bc *</b>) and set a new breakpoint at this new memory 
location of our serial (<b>bpr ecx ecx+3 rw</b>) and press <b>Ctrl+d</b> again. Now we break here:<br>
<br>

<font color="#0B7FC1">
<pre>
:004596E3 E854BA0300              Call 0049513C
:004596E8 8B03                    mov eax, dword ptr [ebx] </font>; WE BREAK HERE <font color="#0B7FC1">
:004596EA 6800E1F505              push 05F5E100		</font>; 100000000 <font color="#0B7FC1">
:004596EF 6A01                    push 00000001		</font>; 1 <font color="#0B7FC1">
:004596F1 50                      push eax		</font>; save serial on stack<font color="#0B7FC1">
:004596F2 56                      push esi
:004596F3 E862BA0300              Call 0049515A		</font>; This must be the function that checks <font color="#0B7FC1">
							</font>; if our serial is between 1 and 100000000!<font color="#0B7FC1">
</pre>
</font>
<br>
Here we have some values being pushed before a call. To see the decimal value of the numbers in SoftIce just write 
<b>? number</b>.<br> 
<b>? 05F5E100</b> show the decimal value 100000000. Hex 1 is decimal 1. This must be the check to
see if the serial is between 1 and 100000000.  Remember the message "<i>Please enter an integer between 1 and 100000000</i>"? <br>
This is not really of interest so press Ctrl+d again. Now we break here:<br>
<br>
<br>
<font color="#0B7FC1">
<pre>
:00459786 8B4E64                  mov ecx, dword ptr [esi+64] </font>; 99999999 - our pin <font color="#0B7FC1">
:00459789 8B5660                  mov edx, dword ptr [esi+60] </font>; 88888888 - our serial - WE BREAK HERE<font color="#0B7FC1">
:0045978C 51                      push ecx		</font>; save pin on stack <font color="#0B7FC1">
:0045978D 52                      push edx		</font>; save serial on stack <font color="#0B7FC1">
:0045978E 8D8818010000            lea ecx, dword ptr [eax+00000118] </font>; 5295176 <font color="#0B7FC1">
:00459794 E89743FCFF              call 0041DB30 	</font>; call to interesting routine  <font color="#0B7FC1">
:00459799 83F80A                  cmp eax, 0000000A 	</font>; compare on eax <font color="#0B7FC1">
:0045979C 7510                    jne 004597AE
* Possible Reference to String Resource ID=00255: "<USES>"
:0045979E 6AFF                    push FFFFFFFF
:004597A0 6A00                    push 00000000
* Possible Reference to String Resource ID=00140: "Sorry, your PIN number is not valid for the given serial num"
:004597A2 688C000000              push 0000008C
* Reference To: MFC42.Ordinal:04AF, Ord:04AFh
:004597A7 E8E4B00300              Call 00494890
:004597AC 5E                      pop esi
:004597AD C3                      ret
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 0045979C(C)
:004597AE 83F80E                  cmp eax, 0000000E
:004597B1 7510                    jne 004597C3
:004597B3 6AFF                    push FFFFFFFF
:004597B5 6A00                    push 00000000
* Possible Reference to String Resource ID=00272: "The serial number and PIN combination you are using is from "
:004597B7 6810010000              push 00000110
:004597BC E8CFB00300              Call 00494890
:004597C1 5E                      pop esi
:004597C2 C3                      ret
* Referenced by a (U)nconditional or (C)onditional Jump at Address:004597B1(C)
:004597C3 83F80B                  cmp eax, 0000000B
:004597C6 7510                    jne 004597D8
</pre>
</font>
<br>
This pice of code is much more interesting. Here we have a call which has our entered serial and pin as parameters!<br>
After the calls we have a lot of compares on eax and some bad guy messages! We better debug this call to 0041DB30.<br>
<br>
Here is the complete routine at 0041DB30 with the comments I added while tracing in SoftIce with F10:<br>
<br>
<br>

<font color="#0B7FC1">
<pre>
* Referenced by a CALL at Addresses: 0041D66F ,00459794   
:0041DB30 53                      push ebx
:0041DB31 8B5C2408                mov ebx, dword ptr [esp+08] 	</font>; 8888 - our serial <font color="#0B7FC1">
:0041DB35 55                      push ebp
:0041DB36 56                      push esi
:0041DB37 57                      push edi
:0041DB38 8BF9                    mov edi, ecx
:0041DB3A 53                      push ebx			</font>; save serial on stack<font color="#0B7FC1">			
:0041DB3B E860030000              call 0041DEA0			</font>; check to see if serial is 1997, 1998,
								; 2353, 13579 or 131313	<font color="#0B7FC1">
:0041DB40 84C0                    test al, al
:0041DB42 740C                    je 0041DB50
:0041DB44 B80B000000              mov eax, 0000000B		</font>; B = old serial return code <font color="#0B7FC1">
:0041DB49 5F                      pop edi
:0041DB4A 5E                      pop esi
:0041DB4B 5D                      pop ebp
:0041DB4C 5B                      pop ebx
:0041DB4D C20800                  ret 0008
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 0041DB42(C)
:0041DB50 53                      push ebx
:0041DB51 8BCF                    mov ecx, edi
:0041DB53 E8480A0000              call 0041E5A0			</font>; is serial 1900? <font color="#0B7FC1">
:0041DB58 84C0                    test al, al
:0041DB5A 740C                    je 0041DB68
:0041DB5C B80E000000              mov eax, 0000000E		</font>; return code = E <font color="#0B7FC1">
:0041DB61 5F                      pop edi
:0041DB62 5E                      pop esi
:0041DB63 5D                      pop ebp
:0041DB64 5B                      pop ebx
:0041DB65 C20800                  ret 0008
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 0041DB5A(C)
:0041DB68 8B6C2418                mov ebp, dword ptr [esp+18]	</font>; our PIN <font color="#0B7FC1">
:0041DB6C 81FB40080000            cmp ebx, 00000840		</font>; is our serial = 2112 <font color="#0B7FC1">
:0041DB72 7514                    jne 0041DB88
:0041DB74 81FD8E150B00            cmp ebp, 000B158E		</font>; is our PIN 726414 <font color="#0B7FC1">
:0041DB7A 750C                    jne 0041DB88
:0041DB7C B80D000000              mov eax, 0000000D		</font>; return code = D <font color="#0B7FC1">
:0041DB81 5F                      pop edi
:0041DB82 5E                      pop esi
:0041DB83 5D                      pop ebp
:0041DB84 5B                      pop ebx
:0041DB85 C20800                  ret 0008
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:0041DB72(C), 0041DB7A(C)
:0041DB88 8BC5                    mov eax, ebp			</font>; PIN <font color="#0B7FC1">
:0041DB8A 53                      push ebx			</font>; push serial <font color="#0B7FC1">
:0041DB8B 99                      cdq
:0041DB8C 33C2                    xor eax, edx			</font>; some calcualtions on PIN <font color="#0B7FC1">
:0041DB8E 8BCF                    mov ecx, edi
:0041DB90 2BC2                    sub eax, edx
:0041DB92 83E001                  and eax, 00000001
:0041DB95 33C2                    xor eax, edx
:0041DB97 8BF0                    mov esi, eax
:0041DB99 2BF2                    sub esi, edx
:0041DB9B F7DE                    neg esi
:0041DB9D 1BF6                    sbb esi, esi
:0041DB9F 46                      inc esi
:0041DBA0 E84B020000              call 0041DDF0			</font>; Generate real PIN <font color="#0B7FC1">
:0041DBA5 8BC8                    mov ecx, eax
:0041DBA7 85F6                    test esi, esi
:0041DBA9 99                      cdq
:0041DBAA 7427                    je 0041DBD3
:0041DBAC 33C2                    xor eax, edx
:0041DBAE 2BC2                    sub eax, edx
:0041DBB0 83E001                  and eax, 00000001
:0041DBB3 33C2                    xor eax, edx
:0041DBB5 2BC2                    sub eax, edx
:0041DBB7 7440                    je 0041DBF9			</font>; if PIN is a non-equal number jump to PIN compare<font color="#0B7FC1">
:0041DBB9 51                      push ecx
:0041DBBA 8BCF                    mov ecx, edi
:0041DBBC E82F020000              call 0041DDF0
:0041DBC1 8BC8                    mov ecx, eax
:0041DBC3 99                      cdq
:0041DBC4 33C2                    xor eax, edx
:0041DBC6 2BC2                    sub eax, edx
:0041DBC8 83E001                  and eax, 00000001
:0041DBCB 33C2                    xor eax, edx
:0041DBCD 2BC2                    sub eax, edx
:0041DBCF 7428                    je 0041DBF9
:0041DBD1 EB25                    jmp 0041DBF8
* Referenced by a (U)nconditional or (C)onditional Jump at Address:0041DBAA(C)
:0041DBD3 33C2                    xor eax, edx
:0041DBD5 2BC2                    sub eax, edx
:0041DBD7 83E001                  and eax, 00000001
:0041DBDA 33C2                    xor eax, edx
:0041DBDC 2BC2                    sub eax, edx
:0041DBDE 7519                    jne 0041DBF9
:0041DBE0 51                      push ecx
:0041DBE1 8BCF                    mov ecx, edi
:0041DBE3 E808020000              call 0041DDF0			</font>; Generate real PIN again<font color="#0B7FC1">
:0041DBE8 8BC8                    mov ecx, eax
:0041DBEA 99                      cdq
:0041DBEB 33C2                    xor eax, edx
:0041DBED 2BC2                    sub eax, edx
:0041DBEF 83E001                  and eax, 00000001
:0041DBF2 33C2                    xor eax, edx
:0041DBF4 2BC2                    sub eax, edx
:0041DBF6 7501                    jne 0041DBF9			</font>; if not PIN is an equal number jump to PIN compare<font color="#0B7FC1">
* Referenced by a (U)nconditional or (C)onditional Jump at Address:0041DBD1(U)
:0041DBF8 41                      inc ecx			</font>; Add 1 to real PIN<font color="#0B7FC1">
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
:0041DBB7(C), :0041DBCF(C), :0041DBDE(C), :0041DBF6(C)		</font>; PIN compare<font color="#0B7FC1">
:0041DBF9 3BCD                    cmp ecx, ebp			</font>; Compare REAL PIN with our fake PIN<font color="#0B7FC1">
:0041DBFB 7503                    jne 0041DC00
:0041DBFD 89771C                  mov dword ptr [edi+1C], esi
* Referenced by a (U)nconditional or (C)onditional Jump at Address:0041DBFB(C)
:0041DC00 8BC1                    mov eax, ecx
:0041DC02 5F                      pop edi
:0041DC03 2BC5                    sub eax, ebp
:0041DC05 5E                      pop esi
:0041DC06 F7D8                    neg eax
:0041DC08 1BC0                    sbb eax, eax
:0041DC0A 5D                      pop ebp
:0041DC0B 24FE                    and al, FE
:0041DC0D 5B                      pop ebx
:0041DC0E 83C00C                  add eax, 0000000C
:0041DC11 C20800                  ret 0008
</pre>
</font>
<br>
Now just exchange your fake PIN with the real PIN and press the OK button again!<br>
<br>
Ehh.. hmmn. When you rerun the program you are not registered:-( I hope this is due to fact 
that this is a trial version which expires the 16th february...?<br>
<br>
<br>
<br>

<h2>PART 2 - The Expiration Check</h2><br>

The real protection of this program is the expiration. When the program expires you get the message 
<i>"This copy of Linkbot 4.0 Beta 1 has expired..."</i> in a messagebox!<br> 
Set the computer's date to anything afthe the 16th february and fire up SoftIce again.
Set a breakpoint at <b>MessageBoxA</b>. Now SoftIce break just before
the expired messagebox appears. Press <b>F12</b> until you are back into LINKBOT. Here I stepped
with <b>F10</b> until I met a <b>ret</b> instruction. Two <b>F10</b>s later I saw this:<br>
<font color="#0B7FC1">
<pre>
:0041F093 8BCE                    mov ecx, esi
:0041F095 E8E61E0000              call 00420F80		</font>; Display expired messagebox<font color="#0B7FC1">
:0041F09A 85C0                    test eax, eax
:0041F09C 7526                    jne 0041F0C4
</pre>
</font>
<br>
<br>
After the call eax is zero. I tried to reverse the result of test eax,eax (<b>r fl z</b>). Hey, 
now the program continues insted of quitting back to windows - but we still get the expired 
messagebox. Now I sat the clock back to a date before the 16th 
february and debugged the above code again. This time the call returned with eax=1.<br>
How can we allways return with eax=1 and avoid the expired messagebox? I have an idea to a patch:<br>
<br>
<font color="#0B7FC1">
<pre>
:0041F093 8BCE                    mov ecx, esi		</font>; before the fix<font color="#0B7FC1">
:0041F095 E8E61E0000              call 00420F80		
:0041F09A 85C0                    test eax, eax
:0041F09C 7526                    jne 0041F0C4

:0041F093 8BCE                    mov ecx, esi		</font>; after this fix<font color="#C17F7F">
:0041F095 B801000000              mov eax,1</font><font color="#0B7FC1">
:0041F09A 85C0                    test eax, eax
:0041F09C 7526                    jne 0041F0C4
</pre>
</font>
He he, it works. We do not call the function the display the expiration messagebox. Eax is
allways 1 when the test eax,eax executes so the program allways continues as a non expired version.<br>
<br>
<br>
<table border="1" bordercolor="#AAAAAA" cellpadding="2" cellspacing="0" bgcolor="#102030" width="100%">
  <tr><td width="100%">
  <center><FONT color="#0B7FC1" SIZE=+2>Final Notes</FONT></center>
  </td></tr>
</table><br><br>

I used the W32Dasm deadlisting very little for this crack. <br>
Including MFC42.DLL in the winice.dat was not very useful either as the functions in MFC42 is called 
something like MFC42!ORD_08f1...<br>
<br>
To crack this program you must spend quite some time in SoftIce... but hey, that's fun!<br>
<br>
This program compares the PINs unencrypted (as numeric values, not as strings). If the PINs had been
encrypted the program would have been harder to crack.<br>
<br>
<br>

<small>Greetings/thanks to The Sandman, Razzia, Volatility, Eternal Bliss, and all other tutorial writers!</small><br>
<br>
<br>
<table border="1" bordercolor="#AAAAAA" cellpadding="2" cellspacing="0" bgcolor="#102030" width="100%">
  <tr><td width="100%">
  <center><FONT color="#0B7FC1" SIZE=+2>Ob Duh</FONT></center>
  </td></tr>
</table><br><br
<I>I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. </I>

</font>
</body>
</html>