- 论坛徽章:
- 0
|
本帖最后由 coolend 于 2010-12-01 20:01 编辑
花生壳相比大家都知道吧,在国内的用户群非常广泛,其协议已经公开了(似乎有段时间了)
相关协议说明可以参考:http://open.oray.com/wiki/doku.p ... 1%E9%83%A8%E5%88%86
有位 “笑行天下” 的仁兄已经开发出C写的客户端,其博客地址为 http://blog.a1983.com.cn/?page_id=483
源代码下载地址:http://blog.a1983.com.cn/software/ddns-r257-src.tar.gz
闲着没事,想研究下用Perl来实现,呵呵~~ 能力有限,对C不懂哦,所以先抛个砖,希望感兴趣的兄弟指点指点或一起来参与
验证过程如下:
客户机发出AUTH authtype指令,authtype为一种验证类型,我们这里使用AUTH ROUTER6(CRAM-MD5扩展)验证。
服务器回应一个挑战串,该串使用客户机的IP地址、服务器的当前时间等不可重复不可预测的参数生成,服务器使用BASE64方式将该串返回客户机,回应码为334
客户机将挑战串作为key使用CRAM-MD5的单向加密方式加密自己的密码形成加密串,
将账号和加密串作为回应,其格式为:
账号名+一个空格+加密嵌入认证码+客户端信息+加密串
其中,加密嵌入认证码共4个字节,为嵌入认证码与服务器当前时间运算得到,服务
器时间是挑战串的第六字节后的4个字节,算法是嵌入认证码与该时间的取反进行或
运算后循环右移一定位数;该右移位数是用服务器时间整除30;
客户端信息也是4个字节,前两位为嵌入式的客户号,后两位为客户端版本号;
客户机使用base64方式对回应进行编码返回服务器。- #!/usr/bin/perl
- use strict;
- use IO::Socket::INET;
- use MIME::Base64 qw(encode_base64 decode_base64);
- use Digest::HMAC_MD5 qw(hmac_md5);
- my $serverip = "ph051.oray.net";
- my $port = '6060';
- ### 登录用户名和密码
- my $user = 'songgongzi';
- my $pass = 'QrhxS25V';
- my $sock = IO::Socket::INET->new(
- PeerAddr => $serverip,
- PeerPort => $port,
- Proto => 'tcp',
- ) or die "ERR: unable to connect to server $! \n";
- my $msg;
- $sock->recv($msg,128);
- die "ERR: server not response ! \n" if (! $msg);
- print $msg;
- ## 发送验证请求
- print $sock "auth router6\n";
- $sock->recv($msg,128);
- print $msg;
- ## BASE64 解码
- $msg =~ s/^\d+\s+//;
- my $reply = decode_base64($msg);
- print "Reply message content is: ",unpack("H*",$reply),"\n";
- ## 服务器时间是挑战串的第六字节后的4个字节
- my $stime = substr($reply,6,4);
- my $tm_stime = unpack("H*",$stime);
- $tm_stime =~ s/^(\w{2})(\w{2})(\w{2})(\w{2})$/$4$3$2$1/;
- $tm_stime = hex($tm_stime);
- ## 打印下服务器的时间,便于调试
- print "Server time is $tm_stime, ",&timenow($tm_stime),"\n";
- ### 以下信息从 “笑行天下” 的 DDNS代码中借用的
- my $client_ID = "0x26A0"; # 客户端ID
- my $client_VER = "0x9899"; # 客户端版本
- my $auth_KEY = "0x1E0808B7"; # 嵌入认证密码
- ### 客户端信息为客户端ID+版本号,共4字节
- my $client_info = ((hex($client_ID) & 0xFFFF) << 16) | (hex($client_VER) & 0xFFFF);
- ## 转换为16进制
- $client_info = sprintf ("%x",$client_info);
- $client_info =~ s/^(\w{2})(\w{2})(\w{2})(\w{2})$/$4$3$2$1/;
- print "Client INFO: $client_info\n";
- my $auth_key = hex($auth_KEY);
- ## 嵌入认证码与时间的取反进行或运算后循环右移
- $tm_stime = $tm_stime | (~$auth_key);
- print "DBG1: $tm_stime\n";
- ### 右移位数是用服务器时间整除30后的余数
- my $mv = $tm_stime % 30;
- print "Move count is $mv\n";
- ### 加密嵌入认证码
- my $auth_enc = $tm_stime << ((32 - $mv) & 0x0000001F);
- $auth_enc |= ($tm_stime) >> ($mv & 0x0000001F);
- $auth_enc = sprintf ("%x",$auth_enc);
- $auth_enc =~ s/^(\w{2})(\w{2})(\w{2})(\w{2})$/$2$1$4$3/;
- print "AUTH_ENC: $auth_enc\n";
- ## 加密串
- my $enc_str = unpack("H*",hmac_md5($pass, $reply));
- print "ENC STR: $enc_str\n";
- my $header = pack("H*","$auth_enc$client_info$enc_str");
- print "HEADER: " . unpack("H*",$header) , " LEN: " , length($header),"\n";
- ## 生成回应串用BASE64编码
- my $lines = join('',$user,' ',$header);
- my $base64 = encode_base64 $lines;
- print "Send BASE64: $base64\n";
- ### 发送给服务端
- print $sock "$base64\n";
- $sock->recv($msg,128);
- print $msg;
- ### 注册域名
- print $sock "regi a songgongzi.gicp.net\n";
- $sock->recv($msg,128);
- print $msg;
- ## 退出
- print $sock "quit\n";
- $sock->shutdown(1);
- $sock->close();
- sub timenow {
- my $tm = time();
- my ($sec,$min,$hur,$day,$mon,$year) = (localtime($tm))[0,1,2,3,4,5];
- $year += 1900; ++ $mon ;
- $mon = "0$mon" if (length($mon) < 2);
- $day = "0$day" if (length($day) < 2);
- $hur = "0$hur" if (length($hur) < 2);
- $min = "0$min" if (length($min) < 2);
- $sec = "0$sec" if (length($sec) < 2);
- return "$year-$mon-$day $hur:$min:$sec";
- }
复制代码 运行时,有时候可以成功,有时候验证失败,经反复测试,发现是加密嵌入认证码计算的问题,还有待进一步研究。
** 2010/12/01日更新
失败时的输出信息:
220 oray.cn DDNS ServerX6 Ready.
334 O6/XGgm6Kpn1TCvpouKvog==
Reply message content is: 3bafd71a09ba2a99f54c2be9a2e2afa2
Server time is 1291163946, 2010-12-01 08:41:12
Client INFO: 9998a026
DBG1: 3992452970
Move count is 20
AUTH_ENC: f67fdfae
ENC STR: ce08450f2eac389b3e7207acc9d852b3
HEADER: f67fdfae9998a026ce08450f2eac389b3e7207acc9d852b3 LEN: 24
Send BASE64: c29uZ2dvbmd6aSD2f9+umZigJs4IRQ8urDibPnIHrMnYUrM=
535 Authentication failure
500 Command unrecognized
成功时的输出信息:
220 oray.cn DDNS ServerX6 Ready.
334 O64u4vKL7Dj2TP8NEF1ZwQ==
Reply message content is: 3bae2ee2f28bec38f64cff0d105d59c1
Server time is 1291204844, 2010-12-01 20:02:05
Client INFO: 9998a026
DBG1: 3992453100
Move count is 0
AUTH_ENC: f7edecff
ENC STR: f1caf2faa67d45a46de09ed330567568
HEADER: f7edecff9998a026f1caf2faa67d45a46de09ed330567568 LEN: 24
Send BASE64: c29uZ2dvbmd6aSD37ez/mZigJvHK8vqmfUWkbeCe0zBWdWg=
250 Auth passed at level <0>
songgongzi.gicp.net
.
250 Register successfully
原来昨天晚上调试到后来花生壳的服务连接不上,是因为遭到了攻击,汗!树大招风阿
http://www.oray.com/news/420.html |
|