I don't know if this should be post in this section or not.
Legend of Silkroad was released August 27, 2014. I downloaded the client downloader and was wondering what they were using.
Code: Select all
LOS_FullClient_Downloader.exe
md5 : F03B629D8DB6AAF12F57D1B6893B7F36
sha1 :EE17AFF29C24A52EA3C6FC69BCFBB9D6D9FC255A
Original Filename : SteamerWinClient.exe
The first thing this client do his downloading configuration for the desired game. In our case:
Code: Select all
http://p2p.jcplanet.com:8080/Admin/Interface/GetConfigureationInfo.aspx?serviceId=LOS_FullClient
Inside this file configuration we can see a MetaInfoFileURL:
Code: Select all
Steamer/MetaInfoFileURL = http://p2p.jcplanet.com:8080/admin/MetaFile/LOS_FullClient_LOS_SetupEN_V1.1.81.exe.steamer
This type of file looks like a .torrent file.
Here are the spec (data stored in little endian):
Code: Select all
STEAMER:
+ 0x00 : Nb_files [DWORD]
+ 0x04 : File_Entry [FILE_ENTRY] * Nb_files
FILE_ENTRY:
+ 0x00 : STR_W_LENGTH [WORD]
+ 0x02 : STR_W [BYTE] * STR_W_LENGTH
+ 0xXX : FILE_SIZE [DWORD64]
+ 0xXX + 8 : NB_BLOCK [DWORD]
+ 0xXX + 0xC : SIZE_BLOCK [DWORD]
+ 0xXX + 0x10: SHA_1_BLOCKS [BYTE] * 0x14 * NB_BLOCK // Array of sha1 for each block
+ 0xXX : SHA_1 [BYTE] * 0x14 // sha1 of SHA_1_BLOCKS
Here a python script to convert .steamer file to .torrent file using python construct module (https://pypi.python.org/pypi/construct/2.5.2):
Code: Select all
import construct
FILE_NAME = "LOS_FullClient_LOS_SetupEN_v1.0.354.exe.steamer"
TRACKER_URL = "http://p2p.jcplanet.com:8080/tracker/announce.aspx"
HTTP_SEED_URL = "http://p2pseedclient-1.cloudapp.net:8080/los/fullclient/LOS_SetupEN_V1.0.354.exe"
Fentry = construct.Struct("Fentry",
construct.ULInt16("length"),
construct.Bytes("data", lambda ctx: ctx.length + 2),
construct.ULInt64("size"),
construct.ULInt32("nb_block"),
construct.ULInt32("size_block"),
construct.Array(lambda ctx: ctx.nb_block, construct.Bytes("sha1", 20)))
Steamer = construct.Struct("Steamer",
construct.ULInt32("nb_files"),
construct.Array(lambda ctx: ctx.nb_files, Fentry))
fd_in = open(FILE_NAME, "rb")
data = fd_in.read()
fd_in.close()
f = Steamer.parse(data)
file_name = f['Fentry'][0]['data'].replace('\x00', '')
size_file = f['Fentry'][0]['size']
nb_block = f['Fentry'][0]['nb_block']
size_block = f['Fentry'][0]['size_block']
print "[+] filename = %s" % file_name
print "[+] size_file = 0x%X" % (size_file)
print "[+] nb_block = 0x%X" % nb_block
print "[+] size_block = 0x%X" % size_block
# http://en.wikipedia.org/wiki/Bencode
fd_out = open(file_name + ".torrent", "wb")
fd_out.write("d8:announce%d:%s" % (len(TRACKER_URL), TRACKER_URL))
fd_out.write("8:encoding5:UTF-84:infod6:lengthi%de" % size_file)
fd_out.write("4:name%d:%s" % (len(file_name), file_name))
fd_out.write("12:piece lengthi%de" % size_block)
fd_out.write("6:pieces%d:" % (nb_block * 20))
for i in f['Fentry'][0]['sha1']:
fd_out.write(i)
fd_out.write("e8:url-listl%d:%see" % (len(HTTP_SEED_URL), HTTP_SEED_URL))
fd_out.close()