<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hegemon+Skall</id>
	<title>Second Life Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hegemon+Skall"/>
	<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/wiki/Special:Contributions/Hegemon_Skall"/>
	<updated>2026-07-26T17:42:11Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7960</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7960"/>
		<updated>2007-01-31T05:57:16Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Step 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
The function to parse the message_template.msg file is in /linden/indrea/llmessage/message.cpp in the Second Life viewer source and the number just appears to be in the order they are in the file (seperate counters for how medium and low frequency messages.&lt;br /&gt;
&lt;br /&gt;
The code used to generate the checksum, around line 1000:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	snprintf(formatString, sizeof(formatString), &amp;quot;%%%ds&amp;quot;, MAX_MESSAGE_INTERNAL_NAME_SIZE);&lt;br /&gt;
	messagefilep = LLFile::fopen(filename, &amp;quot;r&amp;quot;);&lt;br /&gt;
	if (messagefilep) {&lt;br /&gt;
&lt;br /&gt;
		fseek(messagefilep, 0L, SEEK_SET );&lt;br /&gt;
		while(fscanf(messagefilep, formatString, token) != EOF)	{&lt;br /&gt;
			// skip comments&lt;br /&gt;
			if (token[0] == &#039;/&#039;) {&lt;br /&gt;
				// skip to end of line&lt;br /&gt;
				while (token[0] != 10)&lt;br /&gt;
					fscanf(messagefilep, &amp;quot;%c&amp;quot;, token);&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
	&lt;br /&gt;
			checkp = token;&lt;br /&gt;
			while (*checkp)	{&lt;br /&gt;
				mMessageFileChecksum += ((U32)*checkp++) &amp;lt;&amp;lt; checksum_offset;&lt;br /&gt;
				checksum_offset = (checksum_offset + 8) % 32;&lt;br /&gt;
			}&lt;br /&gt;
	// Code here to actually process the entries, see source for more info&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFA&amp;lt;/b&amp;gt; - Please ACK this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&amp;lt;br&amp;gt;&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFF&amp;lt;/b&amp;gt; No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The data bytes aren&#039;t in the same order as the template, and each one is reversed, the major version is 0x01 and the minor version id 0x0D (13). The checksum for this template version is 0x9D 0x95 0xE4 0xC4. I would gess that the flags are the 4 0x00 and the other patch information is the 02 and 00 but its speculative at this point.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB&amp;lt;/b&amp;gt; - NoFlags, I am acknowledging that i received 1 packet from you, packet number #1&amp;lt;br&amp;gt;&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ACK reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ACK is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end Wireshark lists as trailing bytes so they are probably padding required by the network protocols.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The server replied to the packet befoure it ACK it, its also possible to embed the ACK into other packets by setting the ACK flag and adding the number of ACKs to the end of the packet and then the sequence numbers.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - NoFlags, CloseCircuit&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Having received the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls. No extra data is needed.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Very simple C#  server===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 2=&lt;br /&gt;
Now that the client passes step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real encrypted password :)&lt;br /&gt;
&lt;br /&gt;
The libsecondlife [http://www.libsecondlife.org/wiki/Login login] page has more information about the valid responses, pasting one of those into netcat should yield some results, looks like you could use it to make custom messages pop up :)&lt;br /&gt;
&lt;br /&gt;
The next step is to take the request the client produced and attempt to send it to the login server and capture the reply from the server. The login servers use SSL encryption so we need to tunnel through the encryption, fortunately there is a tool similar to netcat called stunnel that supports SSL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
stunnel -c -r login.agni.lindenlab.com:443 &amp;gt; loginreply.xml&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can then paste the clients xml request into stunnel and recieve the reply from the server, by default the server sends gziped documents that aren&#039;t very human readable, by removing the &amp;quot;, gzip&amp;quot; from the Accept-Encoding in the heading we can get the server to send us plain text back.&lt;br /&gt;
&lt;br /&gt;
Note: When manually changing the xml files, its important to keep the Content-Length field in the header valid, otherwise it will be rejected and rerequested.&lt;br /&gt;
&lt;br /&gt;
The servers reply contains things like the inventory layout, gestures and some character details (check the libsecondlife wiki). This response also contains the sim_ip address, by changing this and sending it to the client, we can redirect the client again to connect to netcat. &lt;br /&gt;
&lt;br /&gt;
There is also a new field containing the url of the [https://wiki.secondlife.com/wiki/Capabilities capabilities] (its not shown on the libsecondlife page), once again we can redirect it and receive the xml requests. &amp;lt;pre&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;seed_capability&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;https://sim2049.agni.lindenlab.com:12043/cap/fa3c0b48-2db5-c73a-c8c8-9cf68be4edb2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Client request to sim_ip/sim_port (it was port 13005 in this case) UDP:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[FL]  [Seq Num] [Message Num]  [------------------------------Data, 2 LLUIDS and a 4 byte &#039;code&#039; = 36 bytes------------------------------]&lt;br /&gt;
 40   00 00 01   ff ff 00 03   ad 65 5e b6 5f f6 4b 67 af ee 6f da f1 f8 f1 65 38 ba 9a a4 7b 41 42 6e 90 c5 f4 76 3c 51 e8 37 e4 2a 1e 03                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here we encounter the first non-fixed message number FFFF0003. FFFF indicates that it is a low frequency message as seen in the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] page. We can then find out this message by getting the 3rd Low frequency message in the message_templates.msg file, in this case it seems to be UseCircitCode.&lt;br /&gt;
&lt;br /&gt;
The client also sends a request to the capabilities server of the simulator obtained for the XML-RPC response:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST /cap/cee88818-d777-ced4-af57-a3aa39757f4d HTTP/1.1&lt;br /&gt;
Host: localhost:12043&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: application/xml&lt;br /&gt;
Content-Length: 185&lt;br /&gt;
&lt;br /&gt;
&amp;lt;llsd&amp;gt;&amp;lt;array&amp;gt;&amp;lt;string&amp;gt;MapLayer&amp;lt;/string&amp;gt;&amp;lt;string&amp;gt;MapLayerGod&amp;lt;/string&amp;gt;&amp;lt;string&amp;gt;NewAgentInventory&amp;lt;/string&amp;gt;&amp;lt;string&amp;gt;EventQueueGet&amp;lt;/string&amp;gt;&amp;lt;string&amp;gt;RequestTextureDownload&amp;lt;/string&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/llsd&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=To be continued=&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7959</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7959"/>
		<updated>2007-01-31T05:54:50Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Step 2 */ - Some more info on step 2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
The function to parse the message_template.msg file is in /linden/indrea/llmessage/message.cpp in the Second Life viewer source and the number just appears to be in the order they are in the file (seperate counters for how medium and low frequency messages.&lt;br /&gt;
&lt;br /&gt;
The code used to generate the checksum, around line 1000:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	snprintf(formatString, sizeof(formatString), &amp;quot;%%%ds&amp;quot;, MAX_MESSAGE_INTERNAL_NAME_SIZE);&lt;br /&gt;
	messagefilep = LLFile::fopen(filename, &amp;quot;r&amp;quot;);&lt;br /&gt;
	if (messagefilep) {&lt;br /&gt;
&lt;br /&gt;
		fseek(messagefilep, 0L, SEEK_SET );&lt;br /&gt;
		while(fscanf(messagefilep, formatString, token) != EOF)	{&lt;br /&gt;
			// skip comments&lt;br /&gt;
			if (token[0] == &#039;/&#039;) {&lt;br /&gt;
				// skip to end of line&lt;br /&gt;
				while (token[0] != 10)&lt;br /&gt;
					fscanf(messagefilep, &amp;quot;%c&amp;quot;, token);&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
	&lt;br /&gt;
			checkp = token;&lt;br /&gt;
			while (*checkp)	{&lt;br /&gt;
				mMessageFileChecksum += ((U32)*checkp++) &amp;lt;&amp;lt; checksum_offset;&lt;br /&gt;
				checksum_offset = (checksum_offset + 8) % 32;&lt;br /&gt;
			}&lt;br /&gt;
	// Code here to actually process the entries, see source for more info&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFA&amp;lt;/b&amp;gt; - Please ACK this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&amp;lt;br&amp;gt;&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFF&amp;lt;/b&amp;gt; No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The data bytes aren&#039;t in the same order as the template, and each one is reversed, the major version is 0x01 and the minor version id 0x0D (13). The checksum for this template version is 0x9D 0x95 0xE4 0xC4. I would gess that the flags are the 4 0x00 and the other patch information is the 02 and 00 but its speculative at this point.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB&amp;lt;/b&amp;gt; - NoFlags, I am acknowledging that i received 1 packet from you, packet number #1&amp;lt;br&amp;gt;&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ACK reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ACK is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end Wireshark lists as trailing bytes so they are probably padding required by the network protocols.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The server replied to the packet befoure it ACK it, its also possible to embed the ACK into other packets by setting the ACK flag and adding the number of ACKs to the end of the packet and then the sequence numbers.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - NoFlags, CloseCircuit&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Having received the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls. No extra data is needed.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Very simple C#  server===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 2=&lt;br /&gt;
Now that the client passes step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real encrypted password :)&lt;br /&gt;
&lt;br /&gt;
The libsecondlife [http://www.libsecondlife.org/wiki/Login login] page has more information about the valid responses, pasting one of those into netcat should yield some results, looks like you could use it to make custom messages pop up :)&lt;br /&gt;
&lt;br /&gt;
The next step is to take the request the client produced and attempt to send it to the login server and capture the reply from the server. The login servers use SSL encryption so we need to tunnel through the encryption, fortunately there is a tool similar to netcat called stunnel that supports SSL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
stunnel -c -r login.agni.lindenlab.com:443 &amp;gt; loginreply.xml&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can then paste the clients xml request into stunnel and recieve the reply from the server, by default the server sends gziped documents that aren&#039;t very human readable, by removing the &amp;quot;, gzip&amp;quot; from the Accept-Encoding in the heading we can get the server to send us plain text back.&lt;br /&gt;
&lt;br /&gt;
The servers reply contains things like the inventory layout, gestures and some character details (check the libsecondlife wiki). This response also contains the sim_ip address, by changing this and sending it to the client, we can redirect the client again to connect to netcat. &lt;br /&gt;
&lt;br /&gt;
There is also a new field containing the url of the [https://wiki.secondlife.com/wiki/Capabilities capabilities] (its not shown on the libsecondlife page), once again we can redirect it and receive the xml requests. &amp;lt;pre&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;seed_capability&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;https://sim2049.agni.lindenlab.com:12043/cap/fa3c0b48-2db5-c73a-c8c8-9cf68be4edb2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Client request to sim_ip/sim_port (it was port 13005 in this case) UDP:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[FL]  [Seq Num] [Message Num]  [------------------------------Data, 2 LLUIDS and a 4 byte &#039;code&#039; = 36 bytes------------------------------]&lt;br /&gt;
 40   00 00 01   ff ff 00 03   ad 65 5e b6 5f f6 4b 67 af ee 6f da f1 f8 f1 65 38 ba 9a a4 7b 41 42 6e 90 c5 f4 76 3c 51 e8 37 e4 2a 1e 03                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here we encounter the first non-fixed message number FFFF0003. FFFF indicates that it is a low frequency message as seen in the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] page. We can then find out this message by getting the 3rd Low frequency message in the message_templates.msg file, in this case it seems to be UseCircitCode.&lt;br /&gt;
&lt;br /&gt;
The client also sends a request to the capabilities server of the simulator obtained for the XML-RPC response:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST /cap/cee88818-d777-ced4-af57-a3aa39757f4d HTTP/1.1&lt;br /&gt;
Host: localhost:12043&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: application/xml&lt;br /&gt;
Content-Length: 185&lt;br /&gt;
&lt;br /&gt;
&amp;lt;llsd&amp;gt;&amp;lt;array&amp;gt;&amp;lt;string&amp;gt;MapLayer&amp;lt;/string&amp;gt;&amp;lt;string&amp;gt;MapLayerGod&amp;lt;/string&amp;gt;&amp;lt;string&amp;gt;NewAgentInventory&amp;lt;/string&amp;gt;&amp;lt;string&amp;gt;EventQueueGet&amp;lt;/string&amp;gt;&amp;lt;string&amp;gt;RequestTextureDownload&amp;lt;/string&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/llsd&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=To be continued=&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7442</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7442"/>
		<updated>2007-01-28T07:33:03Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
The function to parse the message_template.msg file is in /linden/indrea/llmessage/message.cpp in the Second Life viewer source and the number just appears to be in the order they are in the file (seperate counters for how medium and low frequency messages.&lt;br /&gt;
&lt;br /&gt;
The code used to generate the checksum, around line 1000:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	snprintf(formatString, sizeof(formatString), &amp;quot;%%%ds&amp;quot;, MAX_MESSAGE_INTERNAL_NAME_SIZE);&lt;br /&gt;
	messagefilep = LLFile::fopen(filename, &amp;quot;r&amp;quot;);&lt;br /&gt;
	if (messagefilep) {&lt;br /&gt;
&lt;br /&gt;
		fseek(messagefilep, 0L, SEEK_SET );&lt;br /&gt;
		while(fscanf(messagefilep, formatString, token) != EOF)	{&lt;br /&gt;
			// skip comments&lt;br /&gt;
			if (token[0] == &#039;/&#039;) {&lt;br /&gt;
				// skip to end of line&lt;br /&gt;
				while (token[0] != 10)&lt;br /&gt;
					fscanf(messagefilep, &amp;quot;%c&amp;quot;, token);&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
	&lt;br /&gt;
			checkp = token;&lt;br /&gt;
			while (*checkp)	{&lt;br /&gt;
				mMessageFileChecksum += ((U32)*checkp++) &amp;lt;&amp;lt; checksum_offset;&lt;br /&gt;
				checksum_offset = (checksum_offset + 8) % 32;&lt;br /&gt;
			}&lt;br /&gt;
	// Code here to actually process the entries, see source for more info&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFA&amp;lt;/b&amp;gt; - Please ACK this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&amp;lt;br&amp;gt;&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFF&amp;lt;/b&amp;gt; No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The data bytes aren&#039;t in the same order as the template, and each one is reversed, the major version is 0x01 and the minor version id 0x0D (13). The checksum for this template version is 0x9D 0x95 0xE4 0xC4. I would gess that the flags are the 4 0x00 and the other patch information is the 02 and 00 but its speculative at this point.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB&amp;lt;/b&amp;gt; - NoFlags, I am acknowledging that i received 1 packet from you, packet number #1&amp;lt;br&amp;gt;&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ACK reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ACK is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end Wireshark lists as trailing bytes so they are probably padding required by the network protocols.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The server replied to the packet befoure it ACK it, its also possible to embed the ACK into other packets by setting the ACK flag and adding the number of ACKs to the end of the packet and then the sequence numbers.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - NoFlags, CloseCircuit&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Having received the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls. No extra data is needed.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Very simple C#  server===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 2=&lt;br /&gt;
Now that the client passes step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
The libsecondlife [http://www.libsecondlife.org/wiki/Login login] page has more information about the valid responses, pasting one of those into netcat should yield some results, looks like you could use it to make custom messages pop up :)&lt;br /&gt;
&lt;br /&gt;
=To be continued=&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Talk:Version_control_repository&amp;diff=7299</id>
		<title>Talk:Version control repository</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Talk:Version_control_repository&amp;diff=7299"/>
		<updated>2007-01-28T01:38:52Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Bazaar */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== SVN ==&lt;br /&gt;
&lt;br /&gt;
I&#039;m happy with a read only SVN.&lt;br /&gt;
&lt;br /&gt;
We are all developers.  We can set up our own local SVN if we want a sandbox. [[User:Gigs Taggart|Gigs Taggart]] 15:13, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Agreed.&lt;br /&gt;
I think our repo should have a struture like....&lt;br /&gt;
* /trunk/slviewer/      Root of what we are given.  You basically just need to check this one directory out to build the client.&lt;br /&gt;
* /tags/slviewer/slviewer-*/     tag of each revision that&#039;s distroed by LL as a set, perhaps with it&#039;s binaries, and the build outputs.  (map files and .asm files anyone?)&lt;br /&gt;
* /branches/slviewer/slviewer-*.1/    Branches to deal with bugs that happen once a tag has been made.  Any changes fixed on a branch should also be applied to the trunk too.&lt;br /&gt;
[[User:Kunnis Basiat|Kunnis Basiat]] 18:38, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
* [[User:Adam Zaius|Adam Zaius]] 06:38, 8 January 2007 (PST) votes for SVN&lt;br /&gt;
** Directory structure something like:&lt;br /&gt;
*** /trunk -- Only editable by Linden Lab&lt;br /&gt;
*** /branches/users/&amp;lt;username&amp;gt;/ -- unlimited permissions by owner/creator for third-party source&lt;br /&gt;
&lt;br /&gt;
Do we want to integrate the VCS with the Second Life authentication?  Pluggability of authentication scheme seems like an important axis to consider. --[[User:Which Linden|Which Linden]] 09:27, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Giving users branches in SVN without a degree of trust is dangerous - purging history in SVN is intentionally very difficult, so a single (malicious) user could conceivably use up all the space in the server or host not-so-legal content (even if you svn rm something, it&#039;s still in the history). However if the trunk is pure svn, normal users can use things like svk if they want their own branches. --[[User:Ginko Bayliss|Ginko Bayliss]] 13:33, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
: Very good idea to consider (VCS w/ SLA). I would highly recommend sourceforge due to its known ability to handle major traffic; however, we would not have the SLA. Despite that, there are many professional and mature tools that work directly with SVN, for example Subclipse.&lt;br /&gt;
: I suggest a tier level repository with modes for production, test, and development, and each with their own trunk, branches, and tags. Production is not distributed and is mainly read-only except for the few who update it.  Production is updated with, and only from, approved patches from test. Test tier is updated by an approved group of individuals with patches from development tier. Test is not distributed but is not read-only like the production tier. Test is where people go to get latest working patches. It is similar to Debian&#039;s mid-tier.  Development can be distributed (people can host their own local sandbox), and it is write-enabled by a larger group responsible to merge code. Once code has been basically approved as working in development, it moves to test, so several patches to development may result in only one patch to test, and that would be the same from test to production. [[User:Dzonatas Sol|Dzonatas Sol]] 10:04, 10 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[User:Eddy Stryker|Eddy Stryker]] 13:22, 9 January 2007 (PST) votes against SVN&lt;br /&gt;
* Branching/merging capabilities are hacked in, so instead of doing push or pull commands you are looking up revision numbers to figure out when you last backported and where the new merge should start&lt;br /&gt;
* No distributed version control like bitkeeper, git, mercurial, etc without using SVK which is a less than ideal solution&lt;br /&gt;
* Not designed for very large codebases like Second Life, where branching becomes unbearable&lt;br /&gt;
** To continue on this point, we had to repair the opensecondlife.org svn database over a dozen times while checking in the thousands of files that make up the full codebase. It&#039;s centralized atomic nature seems to start falling apart when you have very big commits or similar operations going on and multiple other people are trying to check out&lt;br /&gt;
* SVN is a centralized repository system, it&#039;s designed to allow a group of people work together on the same codebase. LL would either have to create two million svn accounts, or have someone take account requests and process them, including setting up permissions for each sandbox... it would become a nightmare very quickly. That&#039;s why large distributed projects like the Linux kernel used distributed version control. They use Git which is Linux only right now, but Mercurial is proving to be a very good competitor to Git with support for all major operating systems&lt;br /&gt;
&lt;br /&gt;
[[User:Kunnis Basiat|Kunnis Basiat]] 22:35, 14 January 2007 (PST)&lt;br /&gt;
* While I agree with the fact that branching and merging is a bit wierd in SVN, it was designed that way from the start, it was designed to get around several of the design flaws that were present in CVS, though I agree it&#039;s not as intunitive as it should be, it allows for really good tracking, but it&#039;s also a bit confusing.  LL has been using SVN for a while, so they should be familiar with how version control in SVN works.&lt;br /&gt;
* I Find SVN to be really stable.I&#039;ve never had a problem with SVN, and I&#039;ve used it for a couple years professionally, and I&#039;ve been helping my latest company migrate to SVN.  The only annoyance I have about SVN is it&#039;s lack of an &amp;quot;obliterate&amp;quot; command, which there is a workaround for, and the schedule of an addition of the command.  Other then that issue, SVN has been in use for several years, it&#039;s a well tested tool, and if any issues arise while using it, it&#039;s likley that you can find support for it.  I&#039;ve only had to break out svnadmin once (to deal with the lack of obliterate, and I found a step-by-step on how to do it.)&lt;br /&gt;
* SVN is used by KDE.  It has both binary and source files, which reflects what we would be checking into OpenSL, and I think that KDE would have more users editing it, and I&#039;m pretty sure it has a larger codebase.&lt;br /&gt;
* I don&#039;t know what problem you had with your repo. I am using the windows version of SVN, and I took my existing repo that I&#039;ve used for other projects and checked in all of the slviewer and libs in one big checkin, with no problems.  It copied all ~9000 files and 160megs in about 5 mins.&lt;br /&gt;
* I agree that LL creating account for every developer is very unreasonable.  I think LL should host a repo that only has &amp;quot;gold&amp;quot; code on it, ready for production, with tags for each build.  There should not be a sandbox for every developer.  I think that we should submit patches to LL that are diffs from the head version of the repo, then a LL employee can apply the patch, then check&amp;amp;verify it works and passes all tests, then finally commit the patch to the repo.  What would the process for a LL employee to recieve a change, validate it, and apply it to production be with Mercurial?  I don&#039;t know enough about it to say what it&#039;s like.&lt;br /&gt;
* I Agree the lack of a Distributed Version Control sucks, you&#039;ve got me curious, I want to play with SVK now.&lt;br /&gt;
&lt;br /&gt;
== Distributed version control ==&lt;br /&gt;
&lt;br /&gt;
One reason I really like the distributed version control systems is because it really reduces the need for Linden Lab to be in the business of giving people their own sandboxes.  Many of the newer systems are very easy to host, and merging from multiple repositories is much easier. -- [[User:Rob Linden|Rob Linden]] 07:25, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
=== Mercurial ===&lt;br /&gt;
Mercurial&#039;s claim: Mercurial is a fast, lightweight Source Control Management system designed for efficient handling of very large distributed projects.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Baba Yamamoto|Baba Yamamoto]] votes for this. &lt;br /&gt;
*No central repository. &lt;br /&gt;
*Easier branching and merging.&lt;br /&gt;
&lt;br /&gt;
=== Darcs ===&lt;br /&gt;
&lt;br /&gt;
Darcs is something you may want to investigate. I&#039;ve used it for other projects, and it was simple and effective enough that the less technical folks have actually started using it for their own projects, it is so simple and effective. A possible con would be that it IS written in Haskell.. but that&#039;s not that problematic. --[[User:Ky Aska|Ky Aska]] 15:59, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
We tried using darcs for a while in-house, and really &amp;lt;em&amp;gt;wanted&amp;lt;/em&amp;gt; it to work, but it would frequently never finish operations on windows because it would consume too much memory. [[User:Phoenix Linden|Phoenix Linden]] 09:25, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Out of curiosity, how long ago was darcs tried? It might&#039;ve gotten better since then - though I&#039;ve heard that performance during conflict resolution is still rather bad. --[[User:Ginko Bayliss|Ginko Bayliss]] 16:32, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
[[User:Don Linden|Don]] and [[User:Kelly Linden|Kelly]] Linden experimented with darcs between 2006.02 and 2006.03.  The version was 1.0.2 on linux.  The Win and Mac versions may have been different.  The conclusion was that darcs could not yet handle large repositories. -- [[User:Andrew Linden|Andrew Linden]] 2006.01.10 09:21 (PST)&lt;br /&gt;
&lt;br /&gt;
=== Bazaar ===&lt;br /&gt;
Bazaar seems to be the hot VCS of choice now days, might be worth considering. Not sure if the development model is applicable to SL or not. It&#039;s got quite a lot of buzz recently in the Linux/Ubuntu/Launchpad world, also seems to have Windows support. http://bazaar-vcs.org/ &lt;br /&gt;
&lt;br /&gt;
Might also be worth looking at using launchpad itself which includes the Bazaar VCS, bug tracking and other stuff, The back end is closed currently but Canonical might be quite happy to allow Linden labs to have a copy of it to host, Mark Shuttleworth recently post about SL http://www.markshuttleworth.com/archives/72 although it would probably be quite a lot of work to setup and the features like bug tracking might be duplicated with existing systems used by Linden (although it seems like it would be fairly easy to integrate them. --[[User:Hegemon Skall|Hegemon Skall]] 13:32, 26 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
=== Comparisons ===&lt;br /&gt;
Thought these might be useful, basically a list of features supported by each VCS:&lt;br /&gt;
&lt;br /&gt;
http://bazaar-vcs.org/RcsComparisons&lt;br /&gt;
http://en.wikipedia.org/wiki/Comparison_of_revision_control_software&lt;br /&gt;
--[[User:Hegemon Skall|Hegemon Skall]] 17:38, 27 January 2007 (PST)&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7209</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7209"/>
		<updated>2007-01-27T07:36:34Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: Checksum info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
The function to parse the message_template.msg file is in /linden/indrea/llmessage/message.cpp in the Second Life viewer source and the number just appears to be in the order they are in the file (seperate counters for how medium and low frequency messages.&lt;br /&gt;
&lt;br /&gt;
The code used to generate the checksum, around line 1000:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	snprintf(formatString, sizeof(formatString), &amp;quot;%%%ds&amp;quot;, MAX_MESSAGE_INTERNAL_NAME_SIZE);&lt;br /&gt;
	messagefilep = LLFile::fopen(filename, &amp;quot;r&amp;quot;);&lt;br /&gt;
	if (messagefilep) {&lt;br /&gt;
&lt;br /&gt;
		fseek(messagefilep, 0L, SEEK_SET );&lt;br /&gt;
		while(fscanf(messagefilep, formatString, token) != EOF)	{&lt;br /&gt;
			// skip comments&lt;br /&gt;
			if (token[0] == &#039;/&#039;) {&lt;br /&gt;
				// skip to end of line&lt;br /&gt;
				while (token[0] != 10)&lt;br /&gt;
					fscanf(messagefilep, &amp;quot;%c&amp;quot;, token);&lt;br /&gt;
				continue;&lt;br /&gt;
			}&lt;br /&gt;
	&lt;br /&gt;
			checkp = token;&lt;br /&gt;
			while (*checkp)	{&lt;br /&gt;
				mMessageFileChecksum += ((U32)*checkp++) &amp;lt;&amp;lt; checksum_offset;&lt;br /&gt;
				checksum_offset = (checksum_offset + 8) % 32;&lt;br /&gt;
			}&lt;br /&gt;
	// Code here to actually process the entries, see source for more info&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFA&amp;lt;/b&amp;gt; - Please ACK this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFF&amp;lt;/b&amp;gt; No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &lt;br /&gt;
&lt;br /&gt;
This is where my knowledge starts to get confuzzled as the bytes don&#039;t seem to be in order though as it seems to be the end bytes (not the very end, befoure the LLUID) that contain the actual version information 1 and 13, but no patch or server versions also the LLUUID is in its correct position at the end, its possible that the bytes are in reverse order. I also don&#039;t know what the flags are for.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB&amp;lt;/b&amp;gt; - NoFlags, I am acknowledging that i received 1 packet from you, packet number #1&lt;br /&gt;
&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ACK reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ACK is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end Wireshark lists as trailing bytes so they are probably padding required by the network protocols.&lt;br /&gt;
&lt;br /&gt;
The server replied to the packet befoure it ACK it, its also possible to embed the ack into other packets by setting the ack flag so sending a separate ACK which is made redundant by the fact it already replied is probably a small bandwidth waste but anyhow.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - NoFlags, CloseCircuit&amp;lt;/b&amp;gt;&lt;br /&gt;
Having received the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls. No extra data is needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Very simple C#  server===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 2=&lt;br /&gt;
Now that the client passes step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
The libsecondlife [http://www.libsecondlife.org/wiki/Login login] page has more information about the valid responses, pasting one of those into netcat should yield some results, looks like you could use it to make custom messages pop up :)&lt;br /&gt;
&lt;br /&gt;
=To be continued=&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Viewer_Architecture&amp;diff=7208</id>
		<title>Viewer Architecture</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Viewer_Architecture&amp;diff=7208"/>
		<updated>2007-01-27T06:19:09Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Learn by Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{OSWikiLearnBox}}&lt;br /&gt;
&lt;br /&gt;
The Second Life client (also known as the &amp;quot;viewer&amp;quot;) is a complex piece of software. It can be visualized as a streaming media client like RealPlayer, a game engine like Quake 3, or a web browser.&lt;br /&gt;
&lt;br /&gt;
First you&#039;ll need to learn some terminology like &amp;quot;agent&amp;quot;, &amp;quot;sim&amp;quot;, and &amp;quot;region&amp;quot; in the [[glossary]].&lt;br /&gt;
&lt;br /&gt;
== Learn by Example ==&lt;br /&gt;
* [[Adding a menu item]]&lt;br /&gt;
* [[Adding a dialog]]&lt;br /&gt;
* [[How movement works]]&lt;br /&gt;
* [[How the camera works]]&lt;br /&gt;
* [[How login works]]&lt;br /&gt;
* [[Hegemons Login Analysis]]&lt;br /&gt;
* [[How keyboard processing works]]&lt;br /&gt;
* [[How scripts work]]&lt;br /&gt;
* [[The lifetime of a session]]&lt;br /&gt;
* [[Adding a preference]]&lt;br /&gt;
&lt;br /&gt;
== Major Systems ==&lt;br /&gt;
* [[Message System]] - reliable and unreliable transport over UDP&lt;br /&gt;
* [[Image System]] - prioritizes and decodes JPEG2000 images into OpenGL textures&lt;br /&gt;
* [[Viewer Object System]] - objects in scene for rendering and editing&lt;br /&gt;
* [[Rendering System]] - from viewer object to drawable to face to vertices to graphics card&lt;br /&gt;
* [[Culling]] - octree and occlusion based culling to speed rendering&lt;br /&gt;
* [[UI Widgets]] - cross platform buttons, scroll bars, etc.&lt;br /&gt;
* [[UI Floaters]] - dialogs and windows built from XML files&lt;br /&gt;
* [[Asset System]] - transport for animations, sounds, notecards, scripts, etc.&lt;br /&gt;
* [[Inventory]] - server-side storage of assets for each user&lt;br /&gt;
* [[Sound System]] - cross platform audio based on FMOD&lt;br /&gt;
* [[Movie System]] - QuickTime-based video on object surfaces&lt;br /&gt;
* [[VFS]] - cached data is held in two &amp;quot;virtual file systems&amp;quot; in large files on the client&lt;br /&gt;
* [[Selection Manager]] - holds extended information for selected objects and allows editing&lt;br /&gt;
* [[Avatar Appearance]] - appearance is constructed from a mesh, parameters to deform the mesh, and textures to describe clothing&lt;br /&gt;
* [[Web Browser]] - the integration of the viewer with the web.&lt;br /&gt;
* [[Avatar Profiles]]&lt;br /&gt;
* [[Groups]]&lt;br /&gt;
* [[L$ System]]&lt;br /&gt;
* [[Tools]] - anything that takes effect when you click your mouse on the world view.&lt;br /&gt;
&lt;br /&gt;
== Threads ==&lt;br /&gt;
The viewer is a single process with a few threads:&lt;br /&gt;
* Main thread -- The input/output main program function (including rendering).&lt;br /&gt;
* VFS thread -- Thread responsible for reading/writing to the local virtual file system.&lt;br /&gt;
* LFS thread -- Thread responsible for some reading/writing to the local native file system.&lt;br /&gt;
** Used by the {{OSWiki|Threaded_Image_Pipeline}} project&lt;br /&gt;
* Image thread -- Thread responsible for requesting and decoding image data&lt;br /&gt;
** Used by the {{OSWiki|Threaded_Image_Pipeline}} project&lt;br /&gt;
* Worker Threads -- Threads designed to do cpu intensive background tasks&lt;br /&gt;
** These threads may be paused during rendering so as not to reduce performance (design in-progress)&lt;br /&gt;
&lt;br /&gt;
== Program Flow ==&lt;br /&gt;
# Initialize - newview/viewer.cpp :: main()&lt;br /&gt;
# Loop  - newview/viewer.cpp :: main_loop()&lt;br /&gt;
#* Gathers  keyboard and mouse input&lt;br /&gt;
#* Pumps the TCP i/o&lt;br /&gt;
#* idle()&lt;br /&gt;
#* Render the frame&lt;br /&gt;
#* let filesystem and worker threads process&lt;br /&gt;
# Shutdown&lt;br /&gt;
&lt;br /&gt;
== Sources of Input ==&lt;br /&gt;
* The [[Message System]].&lt;br /&gt;
** Assets through the [[Asset System]], transmitted using the [[Transfer Manager]], and extracted from the [[VFS]].&lt;br /&gt;
** Files through [[Xfer Manager]].&lt;br /&gt;
* Files copied out of a [[VFS]] into local file store and read through c/c++/ll file API.&lt;br /&gt;
* XMLRPC calls such as [[Authentication Flow|login]] and [[Buying Land and Currency]].&lt;br /&gt;
* HTTP GET/POST to the [[Backbone]]. This is not yet in use.&lt;br /&gt;
* Streaming music and videos.&lt;br /&gt;
** Quicktime.&lt;br /&gt;
** FMOD.&lt;br /&gt;
* The web browser.&lt;br /&gt;
&lt;br /&gt;
== User Guides ==&lt;br /&gt;
&lt;br /&gt;
* [[Viewer coordinate frames]].&lt;br /&gt;
* Known [[Client_parameters]]&lt;br /&gt;
* Known Client Parameters on [http://lslwiki.com/lslwiki/wakka.php?wakka=newview&amp;amp;show_comments=1 LSLwiki.com]&lt;br /&gt;
* Known [[defines]]&lt;br /&gt;
* [[Godmode]] - what Lindens can do&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7207</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7207"/>
		<updated>2007-01-27T05:52:48Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: Changed heading depth&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFA&amp;lt;/b&amp;gt; - Please ACK this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFF&amp;lt;/b&amp;gt; No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &lt;br /&gt;
&lt;br /&gt;
This is where my knowledge starts to get confuzzled as the bytes don&#039;t seem to be in order though as it seems to be the end bytes (not the very end, befoure the LLUID) that contain the actual version information 1 and 13, but no patch or server versions also the LLUUID is in its correct position at the end, its possible that the bytes are in reverse order. I also don&#039;t know what the flags are for.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB&amp;lt;/b&amp;gt; - NoFlags, I am acknowledging that i received 1 packet from you, packet number #1&lt;br /&gt;
&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ACK reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ACK is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end Wireshark lists as trailing bytes so they are probably padding required by the network protocols.&lt;br /&gt;
&lt;br /&gt;
The server replied to the packet befoure it ACK it, its also possible to embed the ack into other packets by setting the ack flag so sending a separate ACK which is made redundant by the fact it already replied is probably a small bandwidth waste but anyhow.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - NoFlags, CloseCircuit&amp;lt;/b&amp;gt;&lt;br /&gt;
Having received the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls. No extra data is needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Very simple C#  server===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 2=&lt;br /&gt;
Now that the client passes step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
The libsecondlife [http://www.libsecondlife.org/wiki/Login login] page has more information about the valid responses, pasting one of those into netcat should yield some results, looks like you could use it to make custom messages pop up :)&lt;br /&gt;
&lt;br /&gt;
=To be continued=&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7206</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7206"/>
		<updated>2007-01-27T05:51:00Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: Added info about libsecondlife XML-RPC login stuff&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFA&amp;lt;/b&amp;gt; - Please ACK this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFF&amp;lt;/b&amp;gt; No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &lt;br /&gt;
&lt;br /&gt;
This is where my knowledge starts to get confuzzled as the bytes don&#039;t seem to be in order though as it seems to be the end bytes (not the very end, befoure the LLUID) that contain the actual version information 1 and 13, but no patch or server versions also the LLUUID is in its correct position at the end, its possible that the bytes are in reverse order. I also don&#039;t know what the flags are for.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB&amp;lt;/b&amp;gt; - NoFlags, I am acknowledging that i received 1 packet from you, packet number #1&lt;br /&gt;
&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ACK reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ACK is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end Wireshark lists as trailing bytes so they are probably padding required by the network protocols.&lt;br /&gt;
&lt;br /&gt;
The server replied to the packet befoure it ACK it, its also possible to embed the ack into other packets by setting the ack flag so sending a separate ACK which is made redundant by the fact it already replied is probably a small bandwidth waste but anyhow.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - NoFlags, CloseCircuit&amp;lt;/b&amp;gt;&lt;br /&gt;
Having received the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls. No extra data is needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Very simple C#  server===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 2=&lt;br /&gt;
Now that the client passes step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
The libsecondlife [http://www.libsecondlife.org/wiki/Login login] page has more information about the valid responses, pasting one of those into netcat should yield some results, looks like you could use it to make custom messages pop up :)&lt;br /&gt;
&lt;br /&gt;
==To be continued==&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=SecuredTemplateChecksumRequest&amp;diff=7205</id>
		<title>SecuredTemplateChecksumRequest</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=SecuredTemplateChecksumRequest&amp;diff=7205"/>
		<updated>2007-01-27T05:34:33Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Usage and Notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ProtocolNav}}&lt;br /&gt;
==Message Layout==&lt;br /&gt;
&amp;lt;pre width=80&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	SecuredTemplateChecksumRequest Fixed 0xFFFFFFFA NotTrusted Unencoded&lt;br /&gt;
	{&lt;br /&gt;
		TokenBlock	Single&lt;br /&gt;
		{	Token	LLUUID	}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Usage and Notes==&lt;br /&gt;
[[Category:Messages]]&lt;br /&gt;
[[Category:Common Messages]]&lt;br /&gt;
This asks for a TemplateChecksumReply from the other node. It is used to ensure both nodes are using the same message template version.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7204</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7204"/>
		<updated>2007-01-27T05:02:14Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: Readded more nuked content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFA&amp;lt;/b&amp;gt; - Please ACK this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFF&amp;lt;/b&amp;gt; No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &lt;br /&gt;
&lt;br /&gt;
This is where my knowledge starts to get confuzzled as the bytes don&#039;t seem to be in order though as it seems to be the end bytes (not the very end, befoure the LLUID) that contain the actual version information 1 and 13, but no patch or server versions also the LLUUID is in its correct position at the end, its possible that the bytes are in reverse order. I also don&#039;t know what the flags are for.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB&amp;lt;/b&amp;gt; - NoFlags, I am acknowledging that i received 1 packet from you, packet number #1&lt;br /&gt;
&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ACK reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ACK is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end Wireshark lists as trailing bytes so they are probably padding required by the network protocols.&lt;br /&gt;
&lt;br /&gt;
The server replied to the packet befoure it ACK it, its also possible to embed the ack into other packets by setting the ack flag so sending a separate ACK which is made redundant by the fact it already replied is probably a small bandwidth waste but anyhow.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - NoFlags, CloseCircuit&amp;lt;/b&amp;gt;&lt;br /&gt;
Having received the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls. No extra data is needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Very simple C#  server===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 2=&lt;br /&gt;
Now that the client passes step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
==To be continued==&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7203</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7203"/>
		<updated>2007-01-27T04:58:22Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: Added some stuff the wiki killed :/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Very simple C#  server=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Step 2=&lt;br /&gt;
Now that the client passes step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
==To be continued==&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7202</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7202"/>
		<updated>2007-01-27T04:55:09Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: I Think the wiki is having problems with this much on one page, keeps duplicating and ereasing stuff&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Step 2==&lt;br /&gt;
Now that the client authenticates step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost -loginuri http://localhost/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7201</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7201"/>
		<updated>2007-01-27T04:53:54Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Valid Response */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
===Raw===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Step 2==&lt;br /&gt;
Now that the client authenticates step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost -loginuri http://localhost/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
==Step 2==&lt;br /&gt;
Now that the client authenticates step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can overload the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost -loginuri http://localhost/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7200</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7200"/>
		<updated>2007-01-27T04:53:23Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Step 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
===Raw===&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Step 2==&lt;br /&gt;
Now that the client authenticates step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can override the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost -loginuri http://localhost/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
==Step 2==&lt;br /&gt;
Now that the client authenticates step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can overload the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost -loginuri http://localhost/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7199</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7199"/>
		<updated>2007-01-27T04:52:59Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Step 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
===Raw===&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Step 2==&lt;br /&gt;
Now that the client authenticates step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can overload the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost -loginuri http://localhost/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7198</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7198"/>
		<updated>2007-01-27T04:43:50Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: Removed dupe server code, whoopse&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
===Raw===&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Very simple C#  server=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Step 2==&lt;br /&gt;
Now that the client authenticates step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can overload the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
==To be continued==&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7197</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7197"/>
		<updated>2007-01-27T04:42:38Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Very simple C#  server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
===Raw===&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Very simple C#  server=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Step 2==&lt;br /&gt;
Now that the client authenticates step 1, it will now attempt to access the login page using XML-RPC calls.&lt;br /&gt;
&lt;br /&gt;
We can overload the website with the -loginuri command. Normally the SL client will want to use encrypted TSL 1.0 but we can specify a nonencrypted url. &lt;br /&gt;
&lt;br /&gt;
./secondlife -user ender -loginuri http://ender/&lt;br /&gt;
&lt;br /&gt;
Then netcat can listen on port 80 and we see the following&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST / HTTP/1.1&lt;br /&gt;
Host: localhost&lt;br /&gt;
Pragma: no-cache&lt;br /&gt;
Accept: */*&lt;br /&gt;
Accept-Encoding: deflate, gzip&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
Content-Length: 1825&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;methodCall&amp;gt;&amp;lt;methodName&amp;gt;login_to_simulator&amp;lt;/methodName&amp;gt;&amp;lt;params&amp;gt;&amp;lt;param&amp;gt;&amp;lt;value&amp;gt;&amp;lt;struct&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;first&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Hegemon&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;last&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Skall&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;passwd&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;$1$4534d5a3257d801ba927ce39bca33aab&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;start&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;last&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;major&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;minor&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;13&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;patch&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;build&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;57209&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;platform&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;Win&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;mac&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;b5fcfb83e74517f2a8be6092995c51c7&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;id0&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string/&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;viewer_digest&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;2bd23799-b279-8665-500a-ce27025b315e&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;member&amp;gt;&amp;lt;name&amp;gt;options&amp;lt;/name&amp;gt;&amp;lt;value&amp;gt;&amp;lt;array&amp;gt;&amp;lt;data&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skeleton&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-root&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-lib-owner&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;inventory-skel-lib&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;initial-outfit&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;gestures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;event_notifications&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;classified_categories&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;buddy-list&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;ui-config&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;login-flags&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;value&amp;gt;&amp;lt;string&amp;gt;global-textures&amp;lt;/string&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/data&amp;gt;&amp;lt;/array&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/member&amp;gt;&amp;lt;/struct&amp;gt;&amp;lt;/value&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/params&amp;gt;&amp;lt;/methodCall&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No thats not my real password :)&lt;br /&gt;
&lt;br /&gt;
==To be continued==&lt;br /&gt;
How to get the checksum/non fixed messageIDs&lt;br /&gt;
&amp;lt;li&amp;gt; Find an appropriate response to the XML.&lt;br /&gt;
&amp;lt;li&amp;gt; Fix the server so it actually responds rather that parroting the packets it gets.&lt;br /&gt;
&amp;lt;li&amp;gt; Figure out how to incorporate the messages_template.msg file&lt;br /&gt;
&lt;br /&gt;
===Step 3===&lt;br /&gt;
This is a server&amp;gt;server bit, it basically checks the password is correct, initially it won&#039;t have any security and will just auto accept the client or lookup a hardcoded value. If i get things more advanced maybe a SQL database lookup.&lt;br /&gt;
&lt;br /&gt;
Another idea would be to use OpenID, the firstname would be the id and the last would be the OpenID server (the password could be anything). OpenID would be a good choice for 3rd party SL servers as it wouldn&#039;t be to hard to transfer the player from one server to another when the servers don&#039;t trust each other. &lt;br /&gt;
&lt;br /&gt;
===Step 4,5===&lt;br /&gt;
Another Server&amp;gt;Server, This is intended to find which sim in the grid to use and autorize, since this is just a basic self contained server it will be itself and this can just be skipped. It will need to tell the client that though.&lt;br /&gt;
&lt;br /&gt;
===Step 6===&lt;br /&gt;
Tell the client the sim info and other basic information.&lt;br /&gt;
&lt;br /&gt;
===Step 7,8===&lt;br /&gt;
Client sends server information, if possible skip most of it.&lt;br /&gt;
&lt;br /&gt;
=Very simple C#  server=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7196</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7196"/>
		<updated>2007-01-27T04:21:11Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Valid Response */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
===Raw===&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Info===&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98 &amp;lt;--- DATA is LLUID&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\  \-------------------------------------------/ &lt;br /&gt;
00 00 00 02 ff ff ff fd  \  \--------\  \--\--\--\--\      \                                     LLUUID-/&lt;br /&gt;
                          \      \             \            \-Version info at this end?&lt;br /&gt;
                           \      \-ACK_ID      \&lt;br /&gt;
                            \       (reversed)   \-5 Trailing Zeros, not actually part of data&lt;br /&gt;
                             \&lt;br /&gt;
                              \-Number of ACKs in message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Description===&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFA&amp;lt;/b&amp;gt; - Please ACK this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFF&amp;lt;/b&amp;gt; No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &lt;br /&gt;
&lt;br /&gt;
This is where my knowledge starts to get confuzzled as the bytes don&#039;t seem to be in order though as it seems to be the end bytes (not the very end, befoure the LLUID) that contain the actual version information 1 and 13, but no patch or server versions also the LLUUID is in its correct position at the end, its possible that the bytes are in reverse order. I also don&#039;t know what the flags are for.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB&amp;lt;/b&amp;gt; - NoFlags, I am acknowledging that i received 1 packet from you, packet number #1&lt;br /&gt;
&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ACK reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ACK is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end Wireshark lists as trailing bytes so they are probably padding required by the network protocols.&lt;br /&gt;
&lt;br /&gt;
The server replied to the packet befoure it ACK it, its also possible to embed the ack into other packets by setting the ack flag so sending a separate ACK which is made redundant by the fact it already replied is probably a small bandwidth waste but anyhow.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - NoFlags, CloseCircuit&amp;lt;/b&amp;gt;&lt;br /&gt;
Having received the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls. No extra data is needed.&lt;br /&gt;
&lt;br /&gt;
=Very simple C#  server=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This just listens on the port and sends back the packets to the client. It done some basic analysis of the packets&lt;br /&gt;
// Its very horrible code&lt;br /&gt;
&lt;br /&gt;
using System;&lt;br /&gt;
using System.Net;&lt;br /&gt;
using System.Net.Sockets;&lt;br /&gt;
&lt;br /&gt;
namespace SLLoginTest&lt;br /&gt;
{&lt;br /&gt;
	public class Slog&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		public Slog()&lt;br /&gt;
		{&lt;br /&gt;
				int recv;&lt;br /&gt;
				byte[] data = new byte[1024];&lt;br /&gt;
				&lt;br /&gt;
				// Create the listening server socket...&lt;br /&gt;
&lt;br /&gt;
				Socket socServer = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);		&lt;br /&gt;
&lt;br /&gt;
				IPEndPoint ipServer = new IPEndPoint(IPAddress.Any, 12036);&lt;br /&gt;
				&lt;br /&gt;
&lt;br /&gt;
				// Bind to local Address...&lt;br /&gt;
&lt;br /&gt;
				socServer.Bind(ipServer);&lt;br /&gt;
				&lt;br /&gt;
				IPEndPoint ipClient = new IPEndPoint(IPAddress.Any, 0);&lt;br /&gt;
				EndPoint Remote = (EndPoint)(ipClient);&lt;br /&gt;
							&lt;br /&gt;
				// FIXME: These should be defines or static finals or whatever C# has&lt;br /&gt;
				byte MASK_LL_ZERO_CODE_FLAG = 0x80;&lt;br /&gt;
				byte MASK_LL_RELIABLE_FLAG = 0x40;&lt;br /&gt;
				byte MASK_LL_RESENT_FLAG = 0x20;&lt;br /&gt;
				byte MASK_LL_ACK_FLAG = 0x10;&lt;br /&gt;
				&lt;br /&gt;
				&lt;br /&gt;
				while(true) {&lt;br /&gt;
					data = new byte[1024];&lt;br /&gt;
					Console.WriteLine(&amp;quot;Awaiting packets...&amp;quot;);&lt;br /&gt;
					recv = socServer.ReceiveFrom(data, ref Remote);&lt;br /&gt;
					Console.WriteLine(&amp;quot;{0} bytes recived...&amp;quot;, recv);&lt;br /&gt;
					&lt;br /&gt;
					&lt;br /&gt;
                                        int seek = 0;&lt;br /&gt;
					int i = 0;&lt;br /&gt;
&lt;br /&gt;
                                        // Dump the raw data&lt;br /&gt;
					Console.Write(&amp;quot;DATA:&amp;quot;);&lt;br /&gt;
					for(int j = 0; j&amp;lt;recv; j++) {&lt;br /&gt;
						Console.Write(&amp;quot; 0x{0:X2} &amp;quot;, data[j]);&lt;br /&gt;
					}&lt;br /&gt;
					Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
                                        // This bit checks the packet flags&lt;br /&gt;
					bool LL_ZERO_CODE_FLAG, LL_RELIABLE_FLAG, LL_RESENT_FLAG, LL_ACK_FLAG;&lt;br /&gt;
					&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ZERO_CODE_FLAG) != 0) {&lt;br /&gt;
						LL_ZERO_CODE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Zero encoded&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RELIABLE_FLAG) != 0) {&lt;br /&gt;
						LL_RELIABLE_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Reliable&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_RESENT_FLAG) != 0) {&lt;br /&gt;
						LL_RESENT_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;Resent&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					if((byte)(data[0] &amp;amp; MASK_LL_ACK_FLAG) != 0) {&lt;br /&gt;
						LL_ACK_FLAG = true;&lt;br /&gt;
						Console.WriteLine(&amp;quot;ACK&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
					seek++; // Move to the next byte&lt;br /&gt;
&lt;br /&gt;
                                        // Read the sequence number into a 3 byte array&lt;br /&gt;
					byte[] sequence = new byte[3];&lt;br /&gt;
					&lt;br /&gt;
					sequence[0] = data[seek++];&lt;br /&gt;
					sequence[1] = data[seek++];&lt;br /&gt;
					sequence[2] = data[seek++];&lt;br /&gt;
&lt;br /&gt;
					Console.WriteLine(&amp;quot;Sequence: 0x{0:X2}{1:X2}{2:X2}&amp;quot;, sequence[0], sequence[1], sequence[2]);&lt;br /&gt;
					&lt;br /&gt;
					byte[] frequency = new byte[4];&lt;br /&gt;
					byte freqByte = data[1];&lt;br /&gt;
					&lt;br /&gt;
					// Add each 0xFF byte  until we reach something thats not 0xFF&lt;br /&gt;
                                        // FIXME: Should stop at 4 bytes&lt;br /&gt;
					do {&lt;br /&gt;
						frequency[i] = data[seek];&lt;br /&gt;
						i++;&lt;br /&gt;
						seek++;&lt;br /&gt;
					} while(data[seek] == 0xFF);&lt;br /&gt;
&lt;br /&gt;
					// We add the final frequency byte, unless it was already added in the case of 0xFFFFFFFF&lt;br /&gt;
					if(i &amp;lt; 4) {&lt;br /&gt;
						frequency[i++] = data[seek++];&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				// Print the frequency&lt;br /&gt;
        			Console.Write(&amp;quot;Frequency: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; i; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, frequency[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
        			&lt;br /&gt;
				// These are the basic templaces (Theres 2 more not listed here)&lt;br /&gt;
        			byte[] SecureTemplateChecksumRequest = {0xFF, 0xFF, 0xFF, 0xFA};&lt;br /&gt;
        			byte[] TemplateChecksumReply = {0xFF, 0xFF, 0xFF, 0xFF};&lt;br /&gt;
        			byte[] Ack = {0xFF, 0xFF, 0xFF, 0xFB};&lt;br /&gt;
        			byte[] CloseCircuit = {0xFF, 0xFF, 0xFF, 0xFD};&lt;br /&gt;
        			&lt;br /&gt;
        			Console.Write(&amp;quot;ST: 0x&amp;quot;);&lt;br /&gt;
        			for(int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        				Console.Write(&amp;quot;{0:X2}&amp;quot;, SecureTemplateChecksumRequest[j]);&lt;br /&gt;
        			}&lt;br /&gt;
        			Console.WriteLine();&lt;br /&gt;
&lt;br /&gt;
				// Check to see which message was send&lt;br /&gt;
				// This isn&#039;t a good way to handle it, it assumes a 4byte frequency and may crash&lt;br /&gt;
				// I haven&#039;t bothered to check them all either&lt;br /&gt;
        			if(frequency[3] == SecureTemplateChecksumRequest[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;SecureTemplateChecksumRequest&amp;quot;);&lt;br /&gt;
        			} else if(frequency[3] == CloseCircuit[3]) {&lt;br /&gt;
        				Console.WriteLine(&amp;quot;CloseCircuit&amp;quot;);&lt;br /&gt;
        			}&lt;br /&gt;
        			&lt;br /&gt;
        			// By sending the packet back to the client we can fake the start of the login&lt;br /&gt;
        			//&lt;br /&gt;
        			// 1. V&amp;gt;S SecureTemplateChecksumRequest? - Viewer asks for the servers checksum&lt;br /&gt;
        			// 2. S&amp;gt;V SecureTemplateChecksumRequest? - Server asks for the viewers checksum&lt;br /&gt;
        			// 3. V&amp;gt;S TemplaceChecksumReply - Client replys to request 2&lt;br /&gt;
        			// 4. S&amp;gt;V TemplaceChecksumReply - Sending the clients on checksum back, answers request in 1&lt;br /&gt;
        			// 5. V&amp;gt;S CloseCircuit - The client has checked it matches the checksum and closes&lt;br /&gt;
        			// 6. S&amp;gt;V CloseCircuit - Parroted back (probably useless/ignored by client)&lt;br /&gt;
        			Console.WriteLine(&amp;quot;Sending parrot response.&amp;quot;);&lt;br /&gt;
				socServer.SendTo(data, recv, SocketFlags.None, Remote);&lt;br /&gt;
				}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7195</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7195"/>
		<updated>2007-01-27T03:57:47Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
=Step 1.=&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening or enough to make a server that does what is required, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
== Redirecting the client ==&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison later).&lt;br /&gt;
&lt;br /&gt;
==A timeout analysis==&lt;br /&gt;
===Raw Dump===&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Description===&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
===Packet info===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
==Valid Response==&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a slightly more readible form:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/-Flags&lt;br /&gt;
|&lt;br /&gt;
|     /-Sequence Number&lt;br /&gt;
|     |&lt;br /&gt;
|     |          /-Frequency&lt;br /&gt;
|     |          |&lt;br /&gt;
+- +--+---+ +----+----+ &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; DATA &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98&lt;br /&gt;
00 00 00 01 ff ff ff fb 01 01 00 00 00 00 00 00 00 00  \--\&lt;br /&gt;
00 00 00 02 ff ff ff fd                    \--\--\--\      \-Version info at this end?&lt;br /&gt;
                                               \&lt;br /&gt;
                                                \-Trailing Zeros, not actually part of data&lt;br /&gt;
&amp;lt;/pre&amp;gt;                                &lt;br /&gt;
&lt;br /&gt;
In english please?:&lt;br /&gt;
&amp;lt;li&amp;gt;[Client&amp;gt;Server] Please acknowledge you received this, Sequence #01, SecureTemplateChecksumRequest, LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
Here out client is requesting a checksum of the template file so it can check its version matches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;[Server&amp;gt;Client] No special flags, Sequence #01, TemplateChecksumReply, &amp;lt;This is the checksum and version info&amp;gt;, &lt;br /&gt;
LLUUID is [16-89-02-b0-75-38-50-f1-8f-41-fe-a7-6e-9a-f7-98]&lt;br /&gt;
This is the servers response, checking the correct [https://wiki.secondlife.com/wiki/TemplateChecksumReply template] shows that it has 32bits(4bytes) of checksum info, then 8bits (1byte) for each for major, minor, patch and server version information and then another 4 bytes for flags, it then has a LUUID. &lt;br /&gt;
&lt;br /&gt;
This is where my knowledge starts to get confuzzled as the bytes don&#039;t seem to be in order though as it seems to be the end bytes (not the very end, befoure the LLUID) that contain the actual version information 1 and 13, but no patch or server versions also the LLUUID is in its correct position at the end, its possible that the bytes are in reverse order. I also don&#039;t know what the flags are for.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;[Server&amp;gt;Client] 0xFFFFFFFB - I am acknowledging that i received 1 packet from you, packet number #1&lt;br /&gt;
One of the 01 bytes is the number of packets that are being acknowledged, its possible to acknowledge more than more packet in one ack reply. The other is the ID of the acknowledged packet. Looking at the [https://wiki.secondlife.com/wiki/PacketAck PacketAck template] you will notice there is just one unsigned 32 bit, no counting byte is listed, I believe that is because of the word &#039;variable&#039;, each ack is assigned 4 bytes but the 01 appears in the first byte so it would seem to be in reverse order (might be relevant for decoding the previous entry). The 4 zeros bytes at the end wireshark lists as trailing bytes so they are probably padding required by the network protocols.&lt;br /&gt;
&amp;lt;li&amp;gt;[Client&amp;gt;Server] 0xFFFFFFFD - CloseCircuit&lt;br /&gt;
Having recived the version info, the client closes this connection, it will now attempt to connect to the login server which is a TSL encrypted webserver, with XML-RPC calls.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7194</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7194"/>
		<updated>2007-01-27T03:14:30Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
Step 1.&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison).&lt;br /&gt;
&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time since it doesn&#039;t appear to be in the compiled client), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;br /&gt;
&lt;br /&gt;
Lets looks at a valid response by sniffing an actual connection to the server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 34 00 00 40 00 40 11 41 e0 c0 a8 01 03 42 96  .4..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 20 2f e6 40 00 00 01 ff ff  ...n/.. /.@.....&lt;br /&gt;
0030   ff fa 16 89 02 b0 75 38 50 f1 8f 41 fe a7 6e 9a  ......u8P..A..n.&lt;br /&gt;
0040   f7 98                                            ..&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 40 72 bf 40 00 2d 11 e2 14 42 96 f4 97 c0 a8  .@r.@.-...B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 2c 14 38 00 00 00 01 ff ff  ../..n.,.8......&lt;br /&gt;
0030   ff ff 00 02 c4 e4 95 9d 00 00 00 00 01 0d 16 89  ................&lt;br /&gt;
0040   02 b0 75 38 50 f1 8f 41 fe a7 6e 9a f7 98        ..u8P..A..n...&lt;br /&gt;
&lt;br /&gt;
Server:&lt;br /&gt;
0000   00 18 f3 04 90 4c 00 e0 a0 a6 66 70 08 00 45 00  .....L....fp..E.&lt;br /&gt;
0010   00 29 72 c3 40 00 2d 11 e2 27 42 96 f4 97 c0 a8  .)r.@.-..&#039;B.....&lt;br /&gt;
0020   01 03 2f 04 94 6e 00 15 42 79 00 00 00 02 ff ff  ../..n..By......&lt;br /&gt;
0030   ff fb 01 01 00 00 00 00 00 00 00 00              ............&lt;br /&gt;
&lt;br /&gt;
Client:&lt;br /&gt;
0000   00 e0 a0 a6 66 70 00 18 f3 04 90 4c 08 00 45 00  ....fp.....L..E.&lt;br /&gt;
0010   00 24 00 00 40 00 40 11 41 f0 c0 a8 01 03 42 96  .$..@.@.A.....B.&lt;br /&gt;
0020   f4 97 94 6e 2f 04 00 10 43 82 00 00 00 02 ff ff  ...n/...C.......&lt;br /&gt;
0030   ff fd                                            ..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Authentication_Flow&amp;diff=7193</id>
		<title>Authentication Flow</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Authentication_Flow&amp;diff=7193"/>
		<updated>2007-01-27T03:02:44Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Step 1 */ - Minor type&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{OSWikiLearnBox|parent=Protocol}}&lt;br /&gt;
&lt;br /&gt;
== Protocol Step-by-step ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1 ===&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
* Secure Message checksum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
* Port 12036&lt;br /&gt;
&lt;br /&gt;
=== Step 2 ===&lt;br /&gt;
Viewer -----------&amp;gt; Login Server&lt;br /&gt;
&lt;br /&gt;
* XML-RPC Func call - over HTTPS. to login. (Blocking) [[http://www.libsecondlife.org/wiki/Login#Client_XML-RPC_Request_.28Encapsulated_in_TLS_1.0.29][Login Info from libsecondlife]&lt;br /&gt;
* Mostly a web server (Apache) that talks to a SQL DB. Gets user info from DB (home. etc.) gets the info about which sim to connect to (IP address etc.) and drops the connection.&lt;br /&gt;
*  First name, last name, MD5(password), viewer version, requested location&lt;br /&gt;
&lt;br /&gt;
=== Step 3 ===&lt;br /&gt;
Login Server ------&amp;gt; Database&lt;br /&gt;
&lt;br /&gt;
Checks actual database for authentication credentials&lt;br /&gt;
&lt;br /&gt;
=== Step 4 ===&lt;br /&gt;
Login Server------&amp;gt; SIM in the Grid&lt;br /&gt;
&lt;br /&gt;
*  Login server decides which SIM to send the viewer to. talks to Grid  &lt;br /&gt;
*  Requests session start&lt;br /&gt;
&lt;br /&gt;
Grid (of Simulators):&lt;br /&gt;
*  inbound UDP port (for comm. with Viewer) 12035, 13000-13050&lt;br /&gt;
&lt;br /&gt;
=== Step 5 === &lt;br /&gt;
SIM ----&amp;gt;  Login server  (response)&lt;br /&gt;
*  Verification that user is allowed on the SIM&lt;br /&gt;
&lt;br /&gt;
=== Step 6 ===&lt;br /&gt;
Login server ------&amp;gt; Viewer (response)&lt;br /&gt;
&lt;br /&gt;
* Information returned:  agent id, session id, secure session id, sim ip, sim port, global location, some inventory info.&lt;br /&gt;
* Most IDs are UUIDs (agent id, session id, and secure session id, for example)&lt;br /&gt;
* Agent ID == User ID Unique and Persistent.&lt;br /&gt;
&lt;br /&gt;
=== Step 7 ===&lt;br /&gt;
Viewer -------&amp;gt;  Simulator (on Grid)&lt;br /&gt;
Handshake &lt;br /&gt;
*  Viewer sends user id and session id&lt;br /&gt;
&lt;br /&gt;
=== Step 8 ===&lt;br /&gt;
Viewer -------&amp;gt;   User server&lt;br /&gt;
User server handshake&lt;br /&gt;
*  Sent for presence information so Group IM works &lt;br /&gt;
*  Confers group rights to user&lt;br /&gt;
*  User server verifies the SIM session info via DB Presence-Agent table.(initially committed by the Login Server at the time of Sim-LoginSERVER negotiation) Step p3&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7192</id>
		<title>Hegemons Login Analysis</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Hegemons_Login_Analysis&amp;diff=7192"/>
		<updated>2007-01-27T03:02:07Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is intended to share/organize the information I learn while tinkering with the Second Life client now that its been GPLed.&lt;br /&gt;
&lt;br /&gt;
I am not a guru, developer etc... I&#039;m just playing around as a learning experience.&lt;br /&gt;
&lt;br /&gt;
I am attempting to create an extremely basic server that just allows the Client to login, hopefully to a empty null world and maybe send some very basic information such as the suns position, area name, amount of money, 1 or 2 prims, flat terrain etc... I want to create it from scratch without relying on the SL viewer code or the libsecondlife stuff to ensure i understand everything. I would also like the server to handle all the elements of the login, ie not using a web server for the login stuff.&lt;br /&gt;
&lt;br /&gt;
So far the server allows the completion of step 1 of the [https://wiki.secondlife.com/wiki/Authentication_Flow Authentication Flow]&lt;br /&gt;
&lt;br /&gt;
Its not very advanced or prwdy and works by parroting the clients requests back to it, this is enough of a hack to trick the client into continuing however incorrect sequence numbers etc are sent.&lt;br /&gt;
&lt;br /&gt;
Stuff used: netcat, wireshark(Ethereal), C#/Mono/Monodevelop&lt;br /&gt;
&lt;br /&gt;
I&#039;m doing this under Ubuntu but any form of Linux should be fine (theres also a port of SL on Solaris now apparently), netcat and wireshark have windows ports also. I have never actually learned C#, but i have done Java, C and C++ so with the help of Google its fairly easy to work it out as I go. I chose C# as I haven&#039;t used it much previously, its also being incorporate into SL for the scripting language and libsecondlife appears to be written in it.&lt;br /&gt;
&lt;br /&gt;
Step 1.&lt;br /&gt;
The Authentication Flow just describes this as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Viewer(client)---------&amp;gt;User Server&lt;br /&gt;
&lt;br /&gt;
    * Secure Message checkum request - Protocol Level Supported? Yes/No.&lt;br /&gt;
    * Port 12036 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which doesn&#039;t really give us an in depth description of everything thats happening, probably the quickest way is to analyses what the client does and try to emulate the servers responses.&lt;br /&gt;
&lt;br /&gt;
Firstly the client needs to be started with the correct command line parameter (found [https://wiki.secondlife.com/wiki/Test_Grid here]). This tells the client to send the initial UDP packets to the localhost.&lt;br /&gt;
&lt;br /&gt;
./secondlife -user localhost&lt;br /&gt;
&lt;br /&gt;
Then netcat need to be set to listen on UDP port 12036:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hegemon@ender:~$ sudo nc -u -l -p 12036 &lt;br /&gt;
@������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                        ����`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
        @������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               `������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                        �����+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                        ���`������+U_{q�Y)$�ͫ&lt;br /&gt;
&lt;br /&gt;
                                                                               �����+U_{q�Y)$�ͫ[[]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This successfully makes the client send its response to localhost, its then not receiving anything back and disconnecting. The outputted information isn&#039;t very usefull so the next step is to fireup wireshark, set it to listen on the loopback interface and find out whats being sent (Alternatively netcat has the ability to output a hexdump also with the -o flag, its also possible to pipe the output to the &#039;hexdump&#039; unix command however wireshark is probably nicer and can be used to analyze the client connecting to the actual server for comparison).&lt;br /&gt;
&lt;br /&gt;
Wireshark gives us:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Client&amp;gt;Server&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 01 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 60 00 00 01 ff ff   ..../..  ..`.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&lt;br /&gt;
0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.&lt;br /&gt;
0010  00 34 00 00 40 00 40 11  b7 62 c0 a8 01 03 c0 a8   .4..@.@. .b......&lt;br /&gt;
0020  01 03 94 ad 2f 04 00 20  83 88 40 00 00 02 ff ff   ..../..  ..@.....&lt;br /&gt;
0030  ff fa 2f c7 ac c1 79 ca  f6 24 2a bc 12 e6 36 48   ../...y. .$*...6H&lt;br /&gt;
0040  be 04                                              ..               &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
These are the 1st 3 packets, there where around 16 in total but its the same thing over and over.&lt;br /&gt;
&lt;br /&gt;
So now we begin the packet analysis. We are only interested in the Data part of the packets, the first 42 bytes contains information such as source and destination ports/addresses, protocol information etc... which is what routers use to determin where to push these things around the internet to get it to your computer. This is shown in wireshark, so just select the data which highlights the following data packets.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
40 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
60 00 00 01 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&lt;br /&gt;
40 00 00 02 ff ff ff fa 2f c7 ac c1 79 ca f6 24 2a bc 12 e6 36 48 be 04&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will notice there are only 2 bytes that are changing, the 1st and 4th, this is because there is no response so the client will keep resending the same data until there is one or it gives up.&lt;br /&gt;
&lt;br /&gt;
By looking at the [https://wiki.secondlife.com/wiki/Packet_Layout packet layout] we can start to see what is being sent. There is also the [http://www.libsecondlife.org/wiki/Protocol_%28network%29 libsecondlife] analysis.&lt;br /&gt;
&lt;br /&gt;
The first byte is the byte contains the bitmask flags, LL_ZERO_CODE_FLAG 0x80, LL_RELIABLE_FLAG 0x40, LL_RESENT_FLAG 0x20, LL_ACK_FLAG 0x10. To understand exactly whats happening in the first byte its best to look at it in binary. In the first packet we have 0x40, 4 in binary is 1000 and 0 is obviously 0000, which is 10000000, the first bit is 1 which means it wants an ack packet back so that it knows it was successfully received, if none is returned it will resend the packet, which is what packet 2 is. &lt;br /&gt;
&lt;br /&gt;
The first byte in packet 2 is 0x60, in binary 10100000, in this packet the first and 3rd bits are set, so it wants an ack and it is a packet that has been resent. The 2rd packet is 0x40 again so its a new packet. not a resent one.&lt;br /&gt;
&lt;br /&gt;
The next 3 bytes are marked as the sequence number, 000001, the first packet sent, then it is repeated in the resent packed and when the client decides to send a new packet rather then resend it increments it to 2. When an ack is sent back I believe it uses this sequence number for the ID, which tells the client it was received and doesn&#039;t need it to be resent.&lt;br /&gt;
&lt;br /&gt;
The next bytes are listed as the &#039;frequency&#039;, its really means the messageID so the system knows the difference between a request for the version information and a request to close the connection, they are defined in the message template file /linden/scripts/messages/message_template.msg in the viewers source code, they are also available from libsecondlife [http://www.libsecondlife.org/template/ here] and you can also find the individual ones on this wiki [http://wiki.secondlife.com/wiki/Category:Messages here], there are 6 &#039;fixed&#039; ones shown near the top, we are encountering 0xFFFFFFFA which is the RequestSecureChecksum, we can check the [https://wiki.secondlife.com/wiki/SecuredTemplateChecksumRequest template] which shows that the packet only contains a LLUUID, that is the next 16 bytes and is a unique number for our client which is the remaining bytes.&lt;br /&gt;
This is the client check to make sure the server is talking the same protocol version.&lt;br /&gt;
&lt;br /&gt;
A majority of the messages are not &#039;fixed&#039; ones. The number of bytes that makes the frequency is variable, so if a byte isn&#039;t 0xFF then that byte is the last byte in the frequency. Currently I&#039;m not sure how to convert the frequency number to the specific message, or workout the checksum as it appears the client loads the template file in (probably at compile time), and docs say it assigns the numbers at runtime, but the fixed ones are enough for the first login step and we can use what we know is a valid checksum number by asking the client for its checksum.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Talk:Version_control_repository&amp;diff=7085</id>
		<title>Talk:Version control repository</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Talk:Version_control_repository&amp;diff=7085"/>
		<updated>2007-01-26T21:32:05Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: /* Darcs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== SVN ==&lt;br /&gt;
&lt;br /&gt;
I&#039;m happy with a read only SVN.&lt;br /&gt;
&lt;br /&gt;
We are all developers.  We can set up our own local SVN if we want a sandbox. [[User:Gigs Taggart|Gigs Taggart]] 15:13, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Agreed.&lt;br /&gt;
I think our repo should have a struture like....&lt;br /&gt;
* /trunk/slviewer/      Root of what we are given.  You basically just need to check this one directory out to build the client.&lt;br /&gt;
* /tags/slviewer/slviewer-*/     tag of each revision that&#039;s distroed by LL as a set, perhaps with it&#039;s binaries, and the build outputs.  (map files and .asm files anyone?)&lt;br /&gt;
* /branches/slviewer/slviewer-*.1/    Branches to deal with bugs that happen once a tag has been made.  Any changes fixed on a branch should also be applied to the trunk too.&lt;br /&gt;
[[User:Kunnis Basiat|Kunnis Basiat]] 18:38, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
* [[User:Adam Zaius|Adam Zaius]] 06:38, 8 January 2007 (PST) votes for SVN&lt;br /&gt;
** Directory structure something like:&lt;br /&gt;
*** /trunk -- Only editable by Linden Lab&lt;br /&gt;
*** /branches/users/&amp;lt;username&amp;gt;/ -- unlimited permissions by owner/creator for third-party source&lt;br /&gt;
&lt;br /&gt;
Do we want to integrate the VCS with the Second Life authentication?  Pluggability of authentication scheme seems like an important axis to consider. --[[User:Which Linden|Which Linden]] 09:27, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Giving users branches in SVN without a degree of trust is dangerous - purging history in SVN is intentionally very difficult, so a single (malicious) user could conceivably use up all the space in the server or host not-so-legal content (even if you svn rm something, it&#039;s still in the history). However if the trunk is pure svn, normal users can use things like svk if they want their own branches. --[[User:Ginko Bayliss|Ginko Bayliss]] 13:33, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
: Very good idea to consider (VCS w/ SLA). I would highly recommend sourceforge due to its known ability to handle major traffic; however, we would not have the SLA. Despite that, there are many professional and mature tools that work directly with SVN, for example Subclipse.&lt;br /&gt;
: I suggest a tier level repository with modes for production, test, and development, and each with their own trunk, branches, and tags. Production is not distributed and is mainly read-only except for the few who update it.  Production is updated with, and only from, approved patches from test. Test tier is updated by an approved group of individuals with patches from development tier. Test is not distributed but is not read-only like the production tier. Test is where people go to get latest working patches. It is similar to Debian&#039;s mid-tier.  Development can be distributed (people can host their own local sandbox), and it is write-enabled by a larger group responsible to merge code. Once code has been basically approved as working in development, it moves to test, so several patches to development may result in only one patch to test, and that would be the same from test to production. [[User:Dzonatas Sol|Dzonatas Sol]] 10:04, 10 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[User:Eddy Stryker|Eddy Stryker]] 13:22, 9 January 2007 (PST) votes against SVN&lt;br /&gt;
* Branching/merging capabilities are hacked in, so instead of doing push or pull commands you are looking up revision numbers to figure out when you last backported and where the new merge should start&lt;br /&gt;
* No distributed version control like bitkeeper, git, mercurial, etc without using SVK which is a less than ideal solution&lt;br /&gt;
* Not designed for very large codebases like Second Life, where branching becomes unbearable&lt;br /&gt;
** To continue on this point, we had to repair the opensecondlife.org svn database over a dozen times while checking in the thousands of files that make up the full codebase. It&#039;s centralized atomic nature seems to start falling apart when you have very big commits or similar operations going on and multiple other people are trying to check out&lt;br /&gt;
* SVN is a centralized repository system, it&#039;s designed to allow a group of people work together on the same codebase. LL would either have to create two million svn accounts, or have someone take account requests and process them, including setting up permissions for each sandbox... it would become a nightmare very quickly. That&#039;s why large distributed projects like the Linux kernel used distributed version control. They use Git which is Linux only right now, but Mercurial is proving to be a very good competitor to Git with support for all major operating systems&lt;br /&gt;
&lt;br /&gt;
[[User:Kunnis Basiat|Kunnis Basiat]] 22:35, 14 January 2007 (PST)&lt;br /&gt;
* While I agree with the fact that branching and merging is a bit wierd in SVN, it was designed that way from the start, it was designed to get around several of the design flaws that were present in CVS, though I agree it&#039;s not as intunitive as it should be, it allows for really good tracking, but it&#039;s also a bit confusing.  LL has been using SVN for a while, so they should be familiar with how version control in SVN works.&lt;br /&gt;
* I Find SVN to be really stable.I&#039;ve never had a problem with SVN, and I&#039;ve used it for a couple years professionally, and I&#039;ve been helping my latest company migrate to SVN.  The only annoyance I have about SVN is it&#039;s lack of an &amp;quot;obliterate&amp;quot; command, which there is a workaround for, and the schedule of an addition of the command.  Other then that issue, SVN has been in use for several years, it&#039;s a well tested tool, and if any issues arise while using it, it&#039;s likley that you can find support for it.  I&#039;ve only had to break out svnadmin once (to deal with the lack of obliterate, and I found a step-by-step on how to do it.)&lt;br /&gt;
* SVN is used by KDE.  It has both binary and source files, which reflects what we would be checking into OpenSL, and I think that KDE would have more users editing it, and I&#039;m pretty sure it has a larger codebase.&lt;br /&gt;
* I don&#039;t know what problem you had with your repo. I am using the windows version of SVN, and I took my existing repo that I&#039;ve used for other projects and checked in all of the slviewer and libs in one big checkin, with no problems.  It copied all ~9000 files and 160megs in about 5 mins.&lt;br /&gt;
* I agree that LL creating account for every developer is very unreasonable.  I think LL should host a repo that only has &amp;quot;gold&amp;quot; code on it, ready for production, with tags for each build.  There should not be a sandbox for every developer.  I think that we should submit patches to LL that are diffs from the head version of the repo, then a LL employee can apply the patch, then check&amp;amp;verify it works and passes all tests, then finally commit the patch to the repo.  What would the process for a LL employee to recieve a change, validate it, and apply it to production be with Mercurial?  I don&#039;t know enough about it to say what it&#039;s like.&lt;br /&gt;
* I Agree the lack of a Distributed Version Control sucks, you&#039;ve got me curious, I want to play with SVK now.&lt;br /&gt;
&lt;br /&gt;
== Distributed version control ==&lt;br /&gt;
&lt;br /&gt;
One reason I really like the distributed version control systems is because it really reduces the need for Linden Lab to be in the business of giving people their own sandboxes.  Many of the newer systems are very easy to host, and merging from multiple repositories is much easier. -- [[User:Rob Linden|Rob Linden]] 07:25, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
=== Mercurial ===&lt;br /&gt;
Mercurial&#039;s claim: Mercurial is a fast, lightweight Source Control Management system designed for efficient handling of very large distributed projects.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Baba Yamamoto|Baba Yamamoto]] votes for this. &lt;br /&gt;
*No central repository. &lt;br /&gt;
*Easier branching and merging.&lt;br /&gt;
&lt;br /&gt;
=== Darcs ===&lt;br /&gt;
&lt;br /&gt;
Darcs is something you may want to investigate. I&#039;ve used it for other projects, and it was simple and effective enough that the less technical folks have actually started using it for their own projects, it is so simple and effective. A possible con would be that it IS written in Haskell.. but that&#039;s not that problematic. --[[User:Ky Aska|Ky Aska]] 15:59, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
We tried using darcs for a while in-house, and really &amp;lt;em&amp;gt;wanted&amp;lt;/em&amp;gt; it to work, but it would frequently never finish operations on windows because it would consume too much memory. [[User:Phoenix Linden|Phoenix Linden]] 09:25, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Out of curiosity, how long ago was darcs tried? It might&#039;ve gotten better since then - though I&#039;ve heard that performance during conflict resolution is still rather bad. --[[User:Ginko Bayliss|Ginko Bayliss]] 16:32, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
[[User:Don Linden|Don]] and [[User:Kelly Linden|Kelly]] Linden experimented with darcs between 2006.02 and 2006.03.  The version was 1.0.2 on linux.  The Win and Mac versions may have been different.  The conclusion was that darcs could not yet handle large repositories. -- [[User:Andrew Linden|Andrew Linden]] 2006.01.10 09:21 (PST)&lt;br /&gt;
&lt;br /&gt;
=== Bazaar ===&lt;br /&gt;
Bazaar seems to be the hot VCS of choice now days, might be worth considering. Not sure if the development model is applicable to SL or not. It&#039;s got quite a lot of buzz recently in the Linux/Ubuntu/Launchpad world, also seems to have Windows support. http://bazaar-vcs.org/ &lt;br /&gt;
&lt;br /&gt;
Might also be worth looking at using launchpad itself which includes the Bazaar VCS, bug tracking and other stuff, The back end is closed currently but Canonical might be quite happy to allow Linden labs to have a copy of it to host, Mark Shuttleworth recently post about SL http://www.markshuttleworth.com/archives/72 although it would probably be quite a lot of work to setup and the features like bug tracking might be duplicated with existing systems used by Linden (although it seems like it would be fairly easy to integrate them. --[[User:Hegemon Skall|Hegemon Skall]] 13:32, 26 January 2007 (PST)&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Talk:Version_control_repository&amp;diff=7074</id>
		<title>Talk:Version control repository</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Talk:Version_control_repository&amp;diff=7074"/>
		<updated>2007-01-26T21:16:18Z</updated>

		<summary type="html">&lt;p&gt;Hegemon Skall: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== SVN ==&lt;br /&gt;
&lt;br /&gt;
I&#039;m happy with a read only SVN.&lt;br /&gt;
&lt;br /&gt;
We are all developers.  We can set up our own local SVN if we want a sandbox. [[User:Gigs Taggart|Gigs Taggart]] 15:13, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Agreed.&lt;br /&gt;
I think our repo should have a struture like....&lt;br /&gt;
* /trunk/slviewer/      Root of what we are given.  You basically just need to check this one directory out to build the client.&lt;br /&gt;
* /tags/slviewer/slviewer-*/     tag of each revision that&#039;s distroed by LL as a set, perhaps with it&#039;s binaries, and the build outputs.  (map files and .asm files anyone?)&lt;br /&gt;
* /branches/slviewer/slviewer-*.1/    Branches to deal with bugs that happen once a tag has been made.  Any changes fixed on a branch should also be applied to the trunk too.&lt;br /&gt;
[[User:Kunnis Basiat|Kunnis Basiat]] 18:38, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
* [[User:Adam Zaius|Adam Zaius]] 06:38, 8 January 2007 (PST) votes for SVN&lt;br /&gt;
** Directory structure something like:&lt;br /&gt;
*** /trunk -- Only editable by Linden Lab&lt;br /&gt;
*** /branches/users/&amp;lt;username&amp;gt;/ -- unlimited permissions by owner/creator for third-party source&lt;br /&gt;
&lt;br /&gt;
Do we want to integrate the VCS with the Second Life authentication?  Pluggability of authentication scheme seems like an important axis to consider. --[[User:Which Linden|Which Linden]] 09:27, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Giving users branches in SVN without a degree of trust is dangerous - purging history in SVN is intentionally very difficult, so a single (malicious) user could conceivably use up all the space in the server or host not-so-legal content (even if you svn rm something, it&#039;s still in the history). However if the trunk is pure svn, normal users can use things like svk if they want their own branches. --[[User:Ginko Bayliss|Ginko Bayliss]] 13:33, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
: Very good idea to consider (VCS w/ SLA). I would highly recommend sourceforge due to its known ability to handle major traffic; however, we would not have the SLA. Despite that, there are many professional and mature tools that work directly with SVN, for example Subclipse.&lt;br /&gt;
: I suggest a tier level repository with modes for production, test, and development, and each with their own trunk, branches, and tags. Production is not distributed and is mainly read-only except for the few who update it.  Production is updated with, and only from, approved patches from test. Test tier is updated by an approved group of individuals with patches from development tier. Test is not distributed but is not read-only like the production tier. Test is where people go to get latest working patches. It is similar to Debian&#039;s mid-tier.  Development can be distributed (people can host their own local sandbox), and it is write-enabled by a larger group responsible to merge code. Once code has been basically approved as working in development, it moves to test, so several patches to development may result in only one patch to test, and that would be the same from test to production. [[User:Dzonatas Sol|Dzonatas Sol]] 10:04, 10 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[User:Eddy Stryker|Eddy Stryker]] 13:22, 9 January 2007 (PST) votes against SVN&lt;br /&gt;
* Branching/merging capabilities are hacked in, so instead of doing push or pull commands you are looking up revision numbers to figure out when you last backported and where the new merge should start&lt;br /&gt;
* No distributed version control like bitkeeper, git, mercurial, etc without using SVK which is a less than ideal solution&lt;br /&gt;
* Not designed for very large codebases like Second Life, where branching becomes unbearable&lt;br /&gt;
** To continue on this point, we had to repair the opensecondlife.org svn database over a dozen times while checking in the thousands of files that make up the full codebase. It&#039;s centralized atomic nature seems to start falling apart when you have very big commits or similar operations going on and multiple other people are trying to check out&lt;br /&gt;
* SVN is a centralized repository system, it&#039;s designed to allow a group of people work together on the same codebase. LL would either have to create two million svn accounts, or have someone take account requests and process them, including setting up permissions for each sandbox... it would become a nightmare very quickly. That&#039;s why large distributed projects like the Linux kernel used distributed version control. They use Git which is Linux only right now, but Mercurial is proving to be a very good competitor to Git with support for all major operating systems&lt;br /&gt;
&lt;br /&gt;
[[User:Kunnis Basiat|Kunnis Basiat]] 22:35, 14 January 2007 (PST)&lt;br /&gt;
* While I agree with the fact that branching and merging is a bit wierd in SVN, it was designed that way from the start, it was designed to get around several of the design flaws that were present in CVS, though I agree it&#039;s not as intunitive as it should be, it allows for really good tracking, but it&#039;s also a bit confusing.  LL has been using SVN for a while, so they should be familiar with how version control in SVN works.&lt;br /&gt;
* I Find SVN to be really stable.I&#039;ve never had a problem with SVN, and I&#039;ve used it for a couple years professionally, and I&#039;ve been helping my latest company migrate to SVN.  The only annoyance I have about SVN is it&#039;s lack of an &amp;quot;obliterate&amp;quot; command, which there is a workaround for, and the schedule of an addition of the command.  Other then that issue, SVN has been in use for several years, it&#039;s a well tested tool, and if any issues arise while using it, it&#039;s likley that you can find support for it.  I&#039;ve only had to break out svnadmin once (to deal with the lack of obliterate, and I found a step-by-step on how to do it.)&lt;br /&gt;
* SVN is used by KDE.  It has both binary and source files, which reflects what we would be checking into OpenSL, and I think that KDE would have more users editing it, and I&#039;m pretty sure it has a larger codebase.&lt;br /&gt;
* I don&#039;t know what problem you had with your repo. I am using the windows version of SVN, and I took my existing repo that I&#039;ve used for other projects and checked in all of the slviewer and libs in one big checkin, with no problems.  It copied all ~9000 files and 160megs in about 5 mins.&lt;br /&gt;
* I agree that LL creating account for every developer is very unreasonable.  I think LL should host a repo that only has &amp;quot;gold&amp;quot; code on it, ready for production, with tags for each build.  There should not be a sandbox for every developer.  I think that we should submit patches to LL that are diffs from the head version of the repo, then a LL employee can apply the patch, then check&amp;amp;verify it works and passes all tests, then finally commit the patch to the repo.  What would the process for a LL employee to recieve a change, validate it, and apply it to production be with Mercurial?  I don&#039;t know enough about it to say what it&#039;s like.&lt;br /&gt;
* I Agree the lack of a Distributed Version Control sucks, you&#039;ve got me curious, I want to play with SVK now.&lt;br /&gt;
&lt;br /&gt;
== Distributed version control ==&lt;br /&gt;
&lt;br /&gt;
One reason I really like the distributed version control systems is because it really reduces the need for Linden Lab to be in the business of giving people their own sandboxes.  Many of the newer systems are very easy to host, and merging from multiple repositories is much easier. -- [[User:Rob Linden|Rob Linden]] 07:25, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
=== Mercurial ===&lt;br /&gt;
Mercurial&#039;s claim: Mercurial is a fast, lightweight Source Control Management system designed for efficient handling of very large distributed projects.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Baba Yamamoto|Baba Yamamoto]] votes for this. &lt;br /&gt;
*No central repository. &lt;br /&gt;
*Easier branching and merging.&lt;br /&gt;
&lt;br /&gt;
=== Darcs ===&lt;br /&gt;
&lt;br /&gt;
Darcs is something you may want to investigate. I&#039;ve used it for other projects, and it was simple and effective enough that the less technical folks have actually started using it for their own projects, it is so simple and effective. A possible con would be that it IS written in Haskell.. but that&#039;s not that problematic. --[[User:Ky Aska|Ky Aska]] 15:59, 8 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
We tried using darcs for a while in-house, and really &amp;lt;em&amp;gt;wanted&amp;lt;/em&amp;gt; it to work, but it would frequently never finish operations on windows because it would consume too much memory. [[User:Phoenix Linden|Phoenix Linden]] 09:25, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
Out of curiosity, how long ago was darcs tried? It might&#039;ve gotten better since then - though I&#039;ve heard that performance during conflict resolution is still rather bad. --[[User:Ginko Bayliss|Ginko Bayliss]] 16:32, 9 January 2007 (PST)&lt;br /&gt;
&lt;br /&gt;
[[User:Don Linden|Don]] and [[User:Kelly Linden|Kelly]] Linden experimented with darcs between 2006.02 and 2006.03.  The version was 1.0.2 on linux.  The Win and Mac versions may have been different.  The conclusion was that darcs could not yet handle large repositories. -- [[User:Andrew Linden|Andrew Linden]] 2006.01.10 09:21 (PST)&lt;br /&gt;
&lt;br /&gt;
Bazaar seems to be the hot repository of choice now days, might be worth considering. Not sure if the development model is applicable to SL or not.&lt;/div&gt;</summary>
		<author><name>Hegemon Skall</name></author>
	</entry>
</feed>