¿ Existe alguna función que partiendo de los dos bytes de un CRC16 decodifique el string dado ?
...y ya puestos la que genera CRC16 y obtiene los dos bytes del CRC.
Gracias.
Antonio Linares wrote:Salvo que me equivoque, no existe forma de obtener la cadena original a partir de su CRC
http://topic.csdn.net/u/20110316/02/eab0b8c6-9b21-4b7d-9bab-06a9ae556638.html
Perl code
#!/usr/bin/perl -w
#
# TCP Proxy Server for reverse engineering the Kinetic SBS-1e receiver
# Mark Street <marksmanuk@gmail.com>
#
use strict;
use Getopt::Std;
use IO::Socket;
use IO::Handle;
my $local_port = 10001;
my $target_ip = "141.22.13.108";
my $target_port = 10001;
my $MSG_LOGIN1 = "\x01\xE9\x5D\xC5\x53\xB1\xD7\xB7\x4E"; # Type 0x17
# Connect to SBS-1 as a TCP client:
#print "$0 Version 0.9.1 <marksmanuk\@gmail.com>\n";
#print "Connecting to SBS-1 on $target_ip:$target_port\n";
my $remote = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => "$target_ip",
PeerPort => "$target_port" )
|| die "Cannot connect to $target_ip:$target_port";
# Local decode mode
local_decode();
# ----------------------------------------------------------------------------
# Communicate with SBS-1 directly
# ----------------------------------------------------------------------------
sub local_decode
{
# Send Login1 string to SBS-1 and await reply.
# Reply will contain keys to be used to decode next reply.
# Magic keys: 0x4857 = "HW"
# Magic keys: 0x5958 = "YX"
# Magic keys: 0x4431 = "D1"
# Magic keys: 0x474A = "GJ"
#print "Sending Login 1 message...\n";
send_sbs(0x17, $MSG_LOGIN1, 0x4857, 0x5958);
my $rx = recv_sbs(0x27, 0x4431, 0x474A);
# Subsequent keys are returned in reply to login message:
# Tx Key = 5DE9 / 53C5
# Rx Key = 5D0D / 61FE
my @msg = split //,$rx->{msg};
my $tx_key1 = (ord ($msg[2]) << 8) + ord $msg[1];
my $tx_key2 = (ord ($msg[4]) << 8) + ord $msg[3];
my $rx_key1 = (ord ($msg[10]) << 8) + ord $msg[9];
my $rx_key2 = (ord ($msg[12]) << 8) + ord $msg[11];
# Send Login2 message and await reply. Encoding will be:
# 02 - Key1, Key 2 - Key3, Key 4
#print "Sending Login 2 message...\n";
my $MSG_LOGIN2 = "\x02".substr($rx->{msg}, 9, 8);
send_sbs(0x18, $MSG_LOGIN2, $tx_key1, $tx_key2);
# Reply will contain inventory details.
$rx = recv_sbs(0x28, $rx_key1, $rx_key2);
my ($serial, $firmware, $build, $fpga1, $fpga2, $decoder1, $decoder2, $user1, $user2) =
unpack "xA8A16SCCCCCC", $rx->{msg};
print "\tSerial Number: $serial\n";
print "\tFirmware: $firmware\n";
print "\tBuild: $build\n";
printf "\tFPGA: %d.%02d\n", $fpga1, $fpga2;
printf "\tDecoder: %d.%02d\n", $decoder1, $decoder2;
printf "\tUser F/W: %d.%02d\n", $user1, $user2;
# We're logged in. Wait for unsolicted events to come in.
print "Awaiting events...\n";
while(1)
{
#print "-"x78,"\n" if $args{v};
$rx = recv_sbs(undef, $rx_key1, $rx_key2);
# next unless $rx->{type} == 0x01;
# printf "Received Event: 0x%02X\n", $rx->{type};
Dump($rx->{msg});
}
exit;
}
# ----------------------------------------------------------------------------
# Local Receive Functions
# ----------------------------------------------------------------------------
my $rx_buffer = "";
sub recv_sbs
{
my $expected = shift;
my $key1 = shift;
my $key2 = shift;
# SBS-1 can send bursts of messages that can arrive in a single
# concatenated packet from the socket. We receive a fixed amount of data
# from the socket to a buffer then return complete messages to the caller.
my $buffer;
my $msg_type;
my $rx_msg;
while(1)
{
#printf "Waiting for Message Type 0x%02X...\n", $expected
# if defined $expected && $args{v};
recv($remote, $buffer, 1500, 0);
$rx_buffer .= $buffer;
die "Disconnected!" if length($buffer) == 0;
# Find end of message: Remember 0x10 is escaped
next unless $rx_buffer =~ m/(?<!\x10)\x10\x03/g;
# This is hack to extract a complete un-escaped message including CRC.
my @val = split //,$rx_buffer;
my ($flag, $idx);
my $at_crc = 0;
$rx_msg = "";
for ($idx=0; $idx<length($rx_buffer); $idx++)
{
if ($val[$idx] eq "\x10" && $flag)
{
$flag = 0;
next;
}
$at_crc++ if $at_crc; # 2 & 3
last if $at_crc == 4;
if ($val[$idx] eq "\x03" && $flag)
{
$at_crc = 1;
}
if ($val[$idx] eq "\x10") {
$flag = 1;
} else {
$flag = 0;
}
$rx_msg .= $val[$idx];
}
# Chop message from buffer;
$rx_buffer = substr($rx_buffer, $idx, length($rx_buffer)-$idx);
$rx_buffer = "" if (length($rx_buffer) > 10000);
$msg_type = ord substr($rx_msg, 2, 1);
# Block until we receive specified message type:
last unless defined $expected;
last if defined $expected && $msg_type == $expected;
}
# Got it. Strip the header and footer and separate into various parts:
my @msg = split //,$rx_msg;
my $rx_crc16 = (ord($msg[-2]) << 8) + ord($msg[-1]);
shift @msg; shift @msg; shift @msg;
pop @msg; pop @msg; pop @msg; pop @msg;
$rx_msg = join "",@msg;
# Descramble received message:
my $rx_clr = rx_decode($rx_msg, $key1, $key2);
# Verify received checksum:
my $crc16 = crc16(0x0000, 0x1021, $msg_type);
foreach my $byte (split //,$rx_clr)
{
$crc16 = crc16($crc16, 0x1021, ord $byte);
}
return { msg => $rx_clr, crc => $crc16, type => $msg_type };
}
sub rx_decode
{
my $rx_msg = shift;
my $key1 = shift;
my $key2 = shift;
die "Undefined Message Bytes" unless defined $rx_msg;
# Descramble payload bytes. This is perfomed in a similar way to the
# encoder by calling the CRC routine initially with magic values
# then doing some bit shifts and logic.
my $enc1 = 0; # Defaults to 0
my $rx_clr;
# Take each message byte in turn and descramble:
foreach my $byte (split //,$rx_msg)
{
$byte = ord $byte;
# Starting with the magic init values, use the returned
# CRC16 as the init values for the next round.
$key1 = crc16($key1, 0x1021, 0xFF);
$key2 = crc16($key2, 0x8005, 0xFF);
# Now some bit shifting weirdness:
my $enc2 = ($enc1 >> 3) | ($enc1 << 5);
# And some XORing for good measure:
my $enc3 = ($byte ^ $enc2) & 0xFF;
my $enc4 = ($enc3 ^ $key1) & 0xFF;
my $enc5 = ($enc4 ^ $key2) & 0xFF;
$enc1 = ($enc2 ^ $enc5) & 0xFF;
$rx_clr .= chr $enc5;
}
return $rx_clr;
}
# ----------------------------------------------------------------------------
# Local Send Functions
# ----------------------------------------------------------------------------
sub send_sbs
{
my $msg_type = shift;
my $msg = shift;
my $key1 = shift;
my $key2 = shift;
# Scramble payload
#printf "Using key1=0x%04X and key2=0x%04X\n", $key1, $key2 if $args{v};
my $enc_login1 = tx_encode($msg_type, $msg, $key1, $key2);
# 16 bit message checksum works like this:
# CRC16 Poly 0x1021 Init 0x0000 - Message Type + Msg Payload aginst
# the cleartext bytes.
my $crc16 = crc16(0x0000, 0x1021, $msg_type);
foreach my $byte (split //,$msg)
{
$crc16 = crc16($crc16, 0x1021, ord $byte);
}
#printf "CRC16 after msg payload = 0x%04X\n", $crc16 if $args{v};
# Add the header and footer bytes and
my $buffer = "\x10\x02".(chr $msg_type)."$enc_login1\x10\x03".
chr($crc16 >> 8).chr($crc16 & 0xFF);
print $remote $buffer;
}
sub tx_encode
{
my $msg_type = shift;
my $msg = shift;
my $key1 = shift;
my $key2 = shift;
die "Undefined Message Type ID" unless defined $msg_type;
die "Undefined Message Bytes" unless defined $msg;
my $len = length($msg);
# The message payload, but not the Message Type ID, are now scrambled
# by calling the usual CRC routine with various initialisation words and
# by performing a series of bit shifts.
my $enc1 = 0; # Defaults to 0
my $output;
# Take each message byte in turn and scramble:
foreach my $byte (split //,$msg)
{
$byte = ord $byte;
#printf "Scrambling 0x%02X\n", $byte if $args{v};
# Starting with the magic init values, use the returned
# CRC16 as the init values for the next round.
$key1 = crc16($key1, 0x1021, 0xFF);
$key2 = crc16($key2, 0x8005, 0xFF);
# Now some bit shifting weirdness:
my $enc2 = ($enc1 >> 3) | ($enc1 << 5);
# And some XORing for good measure:
$enc1 = ($byte ^ $enc2) & 0xFF;
my $enc3 = ($enc1 ^ $key1) & 0xFF;
my $enc4 = ($enc3 ^ $key2) & 0xFF;
# printf "\tScrambled 0x%02X = 0x%02X\n", $byte, $enc4 & 0xFF if $args{v};
$output .= chr $enc4;
}
return $output;
}
# ----------------------------------------------------------------------------
# Helpers
# ----------------------------------------------------------------------------
sub crc16
{
my $init = shift;
my $poly = shift;
my $val = shift;
die "Undefined CRC value"
unless defined $val && defined $poly && defined $init;
my $var;
for (my $i=0; $i<8; $i++)
{
$var = $val << 8;
$var ^= $init;
$init += $init;
$val <<= 1;
if ($var & 0x8000)
{
$init ^= $poly;
}
}
return $init & 0xFFFF;
}
sub Dump
{
my $buffer = shift;
my $header = shift;
die "Undefined buffer" unless defined $buffer;
die "References not supported" unless ref $buffer eq "";
my @vals = unpack("C*", $buffer);
print "$header\n" if defined $header;
my $rowChars = 18;
my $pos = 0;
while ($pos < @vals)
{
#printf "%04X: ", $pos;
for (my $i=0; $i<$rowChars; $i++)
{
(($pos+$i) < @vals) ?
printf "%02X,", $vals[$pos+$i] : print " ";
}
$pos += $rowChars;
print "\n";
}
}
Return to FiveWin para Harbour/xHarbour
Users browsing this forum: Google [Bot] and 48 guests