Introduction

The objective of this project is to create an GPL client to Lively.com (Dead project)

As the protocol is not available, the work is based on different techniques like reverse engineering, sniffers and common sense.

Protocol

After running a protocol analyzer (wireshark), I found that the Lively client uses XMPP (Jabber) protocol for authentication and messaging.

After checking the files on Google/Lively/Flex is obviuos that some of the code was made using Adobe Flex technology. The good new is that Sothink SWF Decompiler is able to dissamble the SWF file like Login.swf, so I expect to be able to analyze how to login to the server.

Using API Monitor I was able to determine that the library used to encrypt the XMPP messages is secur32.dll, so I’ve made a dll proxy to be able to read the data before to get encrypted and when it comes back, after been decrypted.

Also using HxD I was able to read the memory of the application that seems to be made with Visual C++ for 3D (DirectX) and Adobe Flash for windows and forms, I could check the strings before be encrypted and send to the server. The messages are in some kind of XML encrypted inside a XMPP message.

Login.SWF Decompiled

After decompiling and analyzing the code of \Google\Lively\flex\Login.SWF I’ve found:
file: \LoginController.as:

public function doLogin() : void
{
	username = login.username.text;
	if (useStoredPassword)
	{
	}// end if
	Antenna.instance.sendCommand("_l", login.remember.selected,
		!passwordChanged, login.username.text, login.password.text);
	return;
}// end function

file: \Action\com\google\g3dweb\common\Antenna.as:

public function sendCommand(... args) : Object
{
	if (!debugMode)
	{
		return ExternalInterface.call.apply(null, args);
	}// end if
	log("ANTENNA: sendCommand(" + args.join(", ") + ")");
	return {};
}// end function

So in this way the Visual C++ client interact with the SWF files.

Secur32.dll Proxy

To been able to read the data that is send and received, I’ve done a dll proxy. More information about how to do it, can be found here:
http://www.codeproject.com/KB/DLL/CreateYourProxyDLLs.aspx

The source code of the dll proxy is here: secur32.zip and the compiled library is here: secur32.dll

To use it, you need to create a directory in c:\logs and copy the proxy secur32.dll to the Lively directory.
After doing that, rename it to secur31.dll and copy the original secur32.dll (system32) to the Lively directory.
Rename the original secur32.dll in the Lively directory to secur32_.dll
After that, you need to edit the client.exe and replace the string: “secur32.dll” to “secur31.dll” (using an hex editor).
Now you’re done. So execute the client.exe and watch the log files in c:\logs\

Here you can see an example of how looks the dump:

= Init =
[EncryptMessage] 0 START
cBuffers: 4
[EncryptMessage] 0 buffer[1] size: 130
[EncryptMessage] 0 buffer[1] data:
<stream:stream to="gmail.com" xml:lang="en" version="1.0"
xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">

[EncryptMessage] 0 END
[DecryptMessage] 0 START
cBuffers: 4
[DecryptMessage] 0 buffer[1] size: 176
[DecryptMessage] 0 buffer[1] data:
<?xml version="1.0" encoding="UTF-8"?>&lt
;stream:stream from="gmail.com" id="2352CC46DE11B711"
version="1.0"xmlns:stream="http://etherx.jabber.org/streams"
 xmlns="jabber:client">
[DecryptMessage] 0 END
[DecryptMessage] 0 START
cBuffers: 4
[DecryptMessage] 0 buffer[1] size: 166
[DecryptMessage] 0 buffer[1] data:
<stream:features><mechanisms
xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism>
<mechanism>X-GOOGLE-TOKEN</mechanism></mechanisms>
</stream:features>
[DecryptMessage] 0 END
[EncryptMessage] 0 START
cBuffers: 4
[EncryptMessage] 0 buffer[1] size: 385
[EncryptMessage] 0 buffer[1] data:
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl"
mechanism="X-GOOGLE-TOKEN">XXXXXXXXXXXXXXXXXXXXXXX</auth>
[EncryptMessage] 0 END
[DecryptMessage] 0 START
cBuffers: 4
[DecryptMessage] 0 buffer[1] size: 51
[DecryptMessage] 0 buffer[1] data:
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
[DecryptMessage] 0 END
[EncryptMessage] 0 START
cBuffers: 4
[EncryptMessage] 0 buffer[1] size: 130
[EncryptMessage] 0 buffer[1] data:
<stream:stream to="gmail.com" xml:lang="en" version="1.0" xmlns:stream="
http://etherx.jabber.org/streams" xmlns="jabber:client">

[EncryptMessage] 0 END
[DecryptMessage] 0 START
cBuffers: 4
[DecryptMessage] 0 buffer[1] size: 176
[DecryptMessage] 0 buffer[1] data:
<?xml version="1.0" encoding="UTF-8"?><stream:stream
from="gmail.com" id="92A4B029617BC47C" version="
1.0" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">
[DecryptMessage] 0 END
[DecryptMessage] 0 START
cBuffers: 4
[DecryptMessage] 0 buffer[1] size: 137
[DecryptMessage] 0 buffer[1] data:
<stream:features><bind xmlns="
urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns=quot
urn:ietf:params:xml:ns:xmpp-session"/></stream:features>
[DecryptMessage] 0 END
[EncryptMessage] 0 START
cBuffers: 4
[EncryptMessage] 0 buffer[1] size: 115
[EncryptMessage] 0 buffer[1] data:
<iq type="set" id="0"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><resource>
libjingleplus</resource></bind></iq>
[EncryptMessage] 0 END
[DecryptMessage] 0 START
cBuffers: 4
[DecryptMessage] 0 buffer[1] size: 135
[DecryptMessage] 0 buffer[1] data:
<iq id="0" type="result"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>
spamfelipe2@gmail.com/libjinglep59B75216</jid></bind></iq>
[DecryptMessage] 0 END

* I’ve replaced my Google Token for security reason. The token is a base64 string that contains my email (username) and a big string (I think that is the token).

The full log dump can be found here: sniff_secur32_A12207.txt

HxD Dump of Lively Client

The complete file is here: Lively Memory Dump. I don’t know if the strings are correct, maybe they can be a little corrupt.

I have indented the file so is easier to read it, an extract of the file look like this:
Whose room is this?

<message to="spamfelipe2@gmail.com/libjinglep8F9CEED3"
 type="groupchat" id="73" from="lively 108@3dconf.google.com/-5578858927619228622_2541031">
	<body>Whose room is this?</body>
</message>

<presence to="spamfelipe2@gmail.com/libjinglep568823DE"
id="369" from="lively-108@3dconf.google.com/2912906431397233772_24952671">
	<show>away</show>
	<status/>
	<priority>0</priority>
	<x stamp="20080711T23:40:39" xmlns="jabber:x:delay"/>
	<nick:nick xmlns:nick="http://jabber.org/protocol/nick">
		lucas3088
	</nick:nick>
	<plugin xmlns="google:plugin">
		<capability>
			3dweb
		</capability>
		<data>
			CxXj3mXEHWy7qEMlwmSCwgwtAZGsPTABSt0BCJelqfr54P+XBBolCMH+w9
WF09OpNBCVn8HzwfON8H8Yl6Wp+vng/5cEINC9k/jkEBonCIC8j6fDzLPXjwEQ
vZ/26/KaiZmgARiXpan6+eD/lwQg0L2T+OQQGioImv+w89Sd6
K/lARDb3fWBzJif2rcBGJelqfr54P+XBCDsiIib9Z6utigaKQitwOyX8r+5p+cBENn0p4
jNi4XxbhiXpan6+eD/lwQg7IiIm/WerrYoGioIy92Nyqf5hcXBARD/s++qqLbP2LsBGJel
qfr54P+XBCDsiIib9Z6utig=
		</data>
	</plugin>
	<x xmlns="vcard-temp:x:update">
		<photo/>
	</x>
	<user:x xmlns:user="http://jabber.org/protocol/muc#user">
		<user:item affiliation="none" role="participant"/>
	</user:x>
</presence>

<message type="groupchat" from="lively-108@3dconf.google.com/2912906431397233772_24952671"
 to="spamfelipe2@gmail.com/libjinglep568823DE">
	<plugin xmlns="google:plugin">
		<capability>
			3dweb
		</capability>
		<data>
			CAmLApAC7IiIm/WerrYomAIBjAI=
		</data>
	</plugin>
</message>

File Format

After comparing the data on the memory of Lively and the data retrieved using the dll proxy, they match. So the format is basically using XMPP protocol with some extension.

The binary data is send inside tags and following the XMPP standard, they are coded in Base64.

I think that the data containing the coordinates of the user is sended in a binary format, in the tag. As this method is not efficient, the big files are downloaded using an external url. The data is compressed with gzip and samples can be found in the Temporary Internet Files. Those files are compressed with gzip:

user@computer:$ file gp\[8\]
gp[8]: gzip compressed data, max compression

It also appear that some of the 3D files are in Gamebryo format:

user@computer:$ gzip -d < gp\[8\] > gp_8.dump
less gp_8.dump

And the file contains this string: Gamebryo File Format, Version 20.2.0.8

Others interesting strings:

NIF Creation Information >> P:/Google/3DWeb/Project/Assets/01_normals_logan/Export/NIF
 & Texture Sources/geo/01_normals_logan_export-07.09.27-v01.mb >>
Platform = Generic >> Gamebryo Version:2.2.2.0
Exporter Plugin Version:7.3
>> NiMultiShader Version:7.0
>> Maya Unlimited 7.0

eyebrows.NIF
eyebrows_NiMultiShader
headShape:1
skin.NIF
skin_NiMultiShader
eyer
eyerShape
right_eye.NIF
right_eye_NiMultiShader

NIF Creation Information >> P:/Google/3DWeb/Project/Assets/01_normals_logan/Export/NIF
& Texture Sources/geo/01_normals_logan_export-07.10.17-v02.mb >>
 Platform = Generic >> Gamebryo Version:2.2.2.0
Exporter Plugin Version:7.3
>> NiMultiShader Version:7.0
>> Maya Unlimited 7.0

http://ns.adobe.com/xap/1.0/

So to me this seems to be a container file, with a great mix of file formats. Here are two files if you want to look at: 1.zip 2.zip

I got the files from (as the windows cache says):

* You need to be logged in and send an special header with an AUTH cookie to be able to get the files

The problem is that Gamebryo doesn’t have a demonstration/trial kit and the format seems to be proprietary. There is a project to open Gamebryo files (NifTools) but it doesn’t work for me. Anyone want to decode it ?

Useful Links