Skip to content

Instantly share code, notes, and snippets.

@667bdrm
Created April 30, 2015 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 667bdrm/4242b77f1ad4f9580719 to your computer and use it in GitHub Desktop.
Save 667bdrm/4242b77f1ad4f9580719 to your computer and use it in GitHub Desktop.
CityGuide jam service updates downloader (incomplete)
#!/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