Created
April 30, 2015 17:53
-
-
Save 667bdrm/4242b77f1ad4f9580719 to your computer and use it in GitHub Desktop.
CityGuide jam service updates downloader (incomplete)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
$CG_HOST = 'service.probki.net'; | |
$CG_PORT = 1961; | |
# DK01 - 2.2 PC | |
# DK03 - 3.x-3.4 PPC | |
# DK04 - Dispatcher 1.1.35, 3.5 PPC | |
# DK05 - Licensing service, Dispatcher | |
my $PROG_PROTO = "DK03"; | |
# 0x4C - CarPC Lite | |
# 0x4E - CarPC Full, 3.5 PPC | |
# 0x42 - Dispatcher 1.1.35 | |
my $PROG_SIGNATURE = 0x4C; | |
# 0x09 = CarPC Lite | |
# 0x55 = Dispatcher 1.1.35 | |
# 0x01 = 3.5 PPC, 3.4 PPC | |
# 0x1a = 3.4 PPC | |
# 0x04 = 2.2 PC | |
my $PROG_SIGNATURE2 = 0x09; | |
#$PROG_SIGNATURE = 0x4E; | |
my $CG_LOGIN = '********'; | |
my $CG_PASS = '*******'; | |
my $CG_MAPFILE = '47Len.dcm'; | |
#disp | |
$CG_LOGIN = '*******'; | |
$CG_PASS = '*******'; | |
$PROG_PROTO = "DK04"; | |
$PROG_SIGNATURE = 0x42; | |
$PROG_SIGNATURE2 = 0x55; | |
#pna | |
#$CG_LOGIN = '******'; | |
#$CG_PASS = '******'; | |
#$PROG_PROTO = "DK03"; | |
#$PROG_SIGNATURE = 0x4C; | |
#$PROG_SIGNATURE2 = 0x09; | |
$CG_MAPFILE = '78Spb.dcm'; | |
$CG_MAPVER = 22; #required for DK04 | |
use IO::Socket; | |
use IO::Socket::INET; | |
use Time::Local; | |
my $sock = IO::Socket::INET->new(PeerAddr => $CG_HOST, | |
PeerPort => $CG_PORT, | |
Proto => 'tcp', | |
Timeout => 10000, Type => SOCK_STREAM, Blocking => 1 ) or die "Error at line " . __LINE__. ": $!\n"; | |
my $savePath = '/tmp'; | |
my ($data,$head); | |
$sock->send($PROG_PROTO); | |
$sock->recv($data,1); | |
#auth crypto key | |
my $R = ord($data); | |
#my $R = 0xD6; | |
print "crypto key: " . $R . " (0x" . sprintf("%x",$R) . ")\n"; | |
$head= pack('i',$PROG_SIGNATURE); | |
$sock->send($head) or die "Socket send error at line " . __LINE__. ": $!\n"; | |
my $logpack = pack('ccc',$R^0xFF,$R^0xFF^0x01,$R^0xFF); | |
my @login = split(//,$CG_LOGIN); | |
my @pass = split(//,$CG_PASS); | |
my @mapfile = split(//,$CG_MAPFILE); | |
print "login length = " . length($CG_LOGIN) . "\n"; | |
$logpack .= pack('c',length($CG_LOGIN)^$R); | |
foreach my $c (@login) { | |
$logpack.=pack('cc',$R^ord($c),$R); | |
} | |
$logpack .= pack('ccc',$R^0xFF,$R^0xFF^0x01,$R^0xFF); | |
my $passpack = pack('c',length($CG_PASS)^$R); | |
foreach my $c (@pass) { | |
$passpack.=pack('cc',$R^ord($c),$R); | |
} | |
my $logend = pack('cccc',$R^0x1F,$R^$PROG_SIGNATURE2,$R,$R); | |
$sock->send($logpack.$passpack.$logend) or die "Socket send error at line " . __LINE__. ": $!\n"; | |
$sock->recv($data,2); | |
my $mappack = ''; | |
foreach my $c (@mapfile) { | |
$mappack.=pack('cc',ord($c),0x0); | |
} | |
my $authreply = unpack('S',$data); | |
if ($authreply eq 0x1) { | |
print "Authentication successful\n"; | |
if ($PROG_PROTO eq "DK04") { | |
$mappack .= pack('S',$CG_MAPVER); | |
} | |
$sock->send(pack('ic',0x01,length($CG_MAPFILE)) . $mappack) or die "Socket send error at line " . __LINE__. ": $!\n"; | |
while (1) { | |
$sock->recv($data,2); | |
my $updatereply = unpack('S',$data); | |
# roads and jams updates found | |
if ($updatereply eq 0x3) { | |
print "Update for " . $CG_MAPFILE . " available\n"; | |
$sock->send(pack('S',0x2)) or die "Socket send error at line " . __LINE__. ": $!\n"; | |
$sock->recv($data,4); | |
my $datasize = unpack('i',$data); | |
#summary data length (all update files) | |
print "summary data size = $datasize\n"; | |
#name size | |
$sock->recv($data,1); | |
my $jfnamelen = unpack('c',$data); | |
# update filename | |
$sock->recv($data,$jfnamelen); | |
my $jfname = unpack('a*',$data); | |
print "update filename = '$jfname'\n"; | |
# unknown 12 byte data | |
# unknown 4 byte data | |
$sock->recv($data,4); | |
my $unknowndata1 = $data; | |
print "unknown 4-byte data 1 = " .unpack('H*',$unknowndata1) ." (usually 0a000080)\n"; | |
# update timestamp | |
$sock->recv($data,4); | |
my $updatetime = unpack("i",$data); | |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($updatetime); | |
print "update timestamp = " .sprintf("%02d.%02d.%4d %02d:%02d:%02d",$mday,$mon+1,$year+1900,$hour,$min,$sec) . " GMT ($updatetime)\n"; | |
my $locupdatetime = timegm($sec,$min,$hour,$mday,$mon,$year); | |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($locupdatetime); | |
print "update local timestamp = " .sprintf("%02d.%02d.%4d %02d:%02d:%02d",$mday,$mon+1,$year+1900,$hour,$min,$sec) . " ($locupdatetime)\n"; | |
# unknown 4 byte data | |
$sock->recv($data,4); | |
my $unknowndata2 = $data; | |
print "unknown 4-byte data 2 = " .unpack('H*',$unknowndata2) ." (usually 00000000)\n"; | |
# file length | |
$sock->recv($data,4); | |
my $jfilesize = unpack('i',$data); | |
print "update filesize = $jfilesize\n"; | |
my $outfile; | |
if ($jfname) { | |
$outfile = $jfname; | |
} else { | |
die "Error at line " . __LINE__.": Update filename undefined.\n"; | |
} | |
my($s,$m,$h,$M,$d,$y)=(localtime(time()))[0,1,2,3,4,5]; | |
my $outprefix = sprintf("%02d-%02d-%02d-%02d-%02d-%02d",$M,$d,$y+1900,$h,$m,$s); | |
open(OUT,">$savePath/$outprefix-$outfile"); | |
my $out; | |
for (my $downloaded=0 ; $downloaded < $jfilesize ; $downloaded++) { | |
$sock->recv($data,1); | |
print OUT pack("C",unpack("C",$data)); | |
} | |
close(OUT); | |
$sock->send(pack('S',0x1)) or die "Socket send error at line " . __LINE__. ": $!\n"; # we are done, you can delete these updates on server | |
# incoming messages found | |
} elsif ($updatereply eq 0x4) { | |
print "Incoming messages found\n"; | |
$sock->send(pack('S',0x2)) or die "Socket send error at line " . __LINE__. ": $!\n"; | |
$sock->recv($data,4); | |
my $datasize = unpack('i',$data); | |
print "datasize = $datasize\n"; | |
open(OUT,">$savePath/out.msg"); | |
$sock->recv($data,1); | |
my $len = unpack('C',$data); #map name length | |
print "len = $len\n"; | |
$sock->recv($data,$len); #map name | |
my $mapname = $data; #map name | |
print "Map = $mapname:\n"; | |
my $msglen = $datasize-$len; | |
print "Msg length = $msglen\n"; | |
$sock->recv($data,$msglen); | |
my @tmp = unpack('S*',$data); | |
foreach my $t (@tmp) | |
{ | |
$t = 0x0021 if ($t < 0x1); | |
print OUT chr($t) ; | |
} | |
close(OUT); | |
$sock->send(pack('S',0x1)) or die "Socket send error at line " . __LINE__. ": $!\n"; # we are done, you can delete these updates on server | |
# no updates found | |
} else { | |
die "No updates found. updatereply=$updatereply\n"; | |
} | |
} | |
} else { | |
die "Authentication Failed. Auth code=$authreply\n"; | |
} | |
$sock->close; | |
1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment