ICEWR讲解Ke制作.docx

上传人:b****8 文档编号:8998924 上传时间:2023-02-02 格式:DOCX 页数:8 大小:19.95KB
下载 相关 举报
ICEWR讲解Ke制作.docx_第1页
第1页 / 共8页
ICEWR讲解Ke制作.docx_第2页
第2页 / 共8页
ICEWR讲解Ke制作.docx_第3页
第3页 / 共8页
ICEWR讲解Ke制作.docx_第4页
第4页 / 共8页
ICEWR讲解Ke制作.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

ICEWR讲解Ke制作.docx

《ICEWR讲解Ke制作.docx》由会员分享,可在线阅读,更多相关《ICEWR讲解Ke制作.docx(8页珍藏版)》请在冰豆网上搜索。

ICEWR讲解Ke制作.docx

ICEWR讲解Ke制作

ICE-WR的perl与ke入门!

Kore第一讲:

Kore运行与编译byICE-WR

Kore是用perl来编写,目前WIN32系统比较流行的是ActivePerl,网站自行XX,而如果你需要把Kore编译为exe执行文件,那你需要安装PerlPDK,里面有perlapp用来把.pl文件转为.exe文件

已经安装了ActivePerl和perlPDK了,但为什么还不能运行Kore.pl呢?

请打开Kore.pl,你会看到类似这样的语句:

useTime:

:

HiResqw(timeusleep);

useIO:

:

Socket;

use语句用作调用模块,而你没有这些模块那就当然运行不了咯,PDK里包含一个叫VPM(VisualPackageManager)的模块管理软件,运行后会出现一个搜索网页,在搜索栏输入Time:

:

HiRes和IO:

:

Socket就会从网上把模块搜索出来并安装到你的电脑里,只要把模块都装好,那你就可以运行Kore.pl了

如何把.pl文件转为.exe文件呢?

这里需要用PDK里的perlapp,在这里用KE的编译来举例:

perlapp--xclude--iconKoreEasy.icoKoreEasy.pl

--xclude编译时不包含perl58.dll文件,这样会让编译出来的程序小点,但别的机器要运行时需要复制perl58.dll

--icon这个是指定图标文件

ActivePerl下载地址自行XX

PerlPDK下载地址自行XX

Kore第二讲:

Kore与PerlbyICE-WR

Kore是用perl语言来编写的,perl是一种简单而强大的脚本语言,.pl的文件就是perl脚本,需要解释器来运行,例如:

Windows平台下的ActivePerl。

要想了解Kore,不需要对perl非常精通,当你第一次看Kore.pl时估计会非常头痛,一些语句甚至无法理解,大部分都是一些匹配模式,例如:

       foreach(){

               nextif(/^#/);

               s/[\r\n]//g;

               s/\s+//g;

               s/\s+$//g;

               @args=split/\s/,$_;

       }

Kore第三讲:

Kore的程序结构byICE-WR

Kore的程序执行流程如下:

1)程序初始化:

调用模块,初始化变量

2)读入数据文件

3)建立控制台指令输入连接及与服务器连接

4)执行主程序,主程序是个循环,只要没有接收到quit指令就一直执行,包括如下功能:

       a)执行控制台指令

       b)分析接收到的封包,转化为Kore里的游戏信息,如HP/SP等

       c)根据信息执行AI

       d)检查连接情况

5)接收到quit指令后结束连接和程序

Kore原版有8000行代码,但实际上主程序只有20行代码!

了解主程序你就能知道整个运作原理了,以下位主程序代码的解释:

while($quit!

=1){

#当不是$quit=1时,一直执行以下程序,假如你在Kore里输入quit,那就会退出Kore啦

       usleep($config{'sleepTime'});

       #usleep就是要睡眠多少微秒,作用是等待封包接收及减低CPU占用率

       if(dataWaiting(\$input_socket)){

       #$input_socket用来读取控制台指令,如果有指令输入,则执行以下代码

               $input_socket->recv($input,$MAX_READ);

               #从$input_socket读取数据并储存在$input,例如我们输入"i"指令,那$input就等于"i"

               parseInput($input);

               #parseInput是个子程序,用来执行控制台指令

       }elsif(dataWaiting(\$remote_socket)){

       #$remote_socket用来接收封包,加入服务器发送了封包过来,则执行以下代码

               $remote_socket->recv($new,$MAX_READ);

               #从$remote_socket读取服务器发送过来的数据,$MAX_READ是用来限制一次读入的数据量

               $msg.=$new;

               #由于服务器每次发送的封包不一定是完整的数据,所以Kore会把封包连接起来并储存在$msg

               $msg_length=length($msg);

               #这里是计算解释封包前的长度

               while($msgne""){

               #当有封包数据时,一直执行下面的代码

                       $msg=parseMsg($msg);

                       #parseMsg是封包解释子程序,负责把封包转换为各种数据,例如HP/SP等,运行时读取$msg,运行后把已经解释完毕的封包去掉,并返回给$msg,这个过程就是,读完一段就删除一段

                       lastif($msg_length==length($msg));

                       #因为封包解释子程序是解释完一段就删除一段的,所以这里比较解释前和解释后的$msg长度,来判断是否仍然有未解释的封包,假如解释前和解释后的$msg长度一样,那就代表已经没有要解释的封包,终止执行这个封包解释循环

                       $msg_length=length($msg);

                       #记录下解释后的封包长度,用作下一次比较

               }

       }

       #上面的循环是用作接收指令和解释封包,执行后会运行以下子程序“AI”

       $ai_cmdQue_shift=0;

       #$ai_cmdQue是用作远程控制(聊天指令控制)

       do{

               AI(\%{$ai_cmdQue[$ai_cmdQue_shift]})if($conState==5&&timeOut(\%{$timeout{'ai'}})&&$remote_socket&&$remote_socket->connected());

               #$conState5代表已经完成登陆过程,并开始游戏;因为进入游戏后会收到大量信息,所以等待timeout.txt里AI指定的秒数后才执行AI;后面两个判断是代表连接正常

               undef%{$ai_cmdQue[$ai_cmdQue_shift++]};

               $ai_cmdQue--if($ai_cmdQue>0);

               #以上两句是用作执行远程控制

       }while($ai_cmdQue>0);

       checkConnection();

       #管理数据通讯连接状况的子程序,例如:

登陆和断线等功能

}

Kore第四讲:

RO封包简要说明byICE-WR

RO客户端与服务器间通过TCP协议连接,并互相传递信息,封包内容类似

B0000500E0100000

#00b0wl

RO的封包头包含2个字节,数值从0064到01FF,上面的封包头为00B0,每种封包分别代表不同类型的信息。

RO封包有2种,一种是固定长度,一种是非固定长度,类型和各封包长度在ragexe.exe里记录,KARASU把RAGEXE.EXE破解后翻译出全部封包长度。

例如00B0是固定长度8字节,但如果一个封包并不是固定长度,那服务器需要告知RO客户端封包的长度,对非固定长度的封包,在封包的第三和第四个字节用来表示封包长度

把类似“B0000500E0100000”这种16进制形式的代码转换为数值,在perl里通常用substr和unpack函数从封包里转换为具体数值(perl函数请参考Kore第二讲里的perl教学文件)

例如Kore的封包分析子程序里对B0000500E0100000的解释执行如下:

       }elsif($switcheq"00B0"){

               #$switch在Kore里代表封包头,当封包头为00B0时执行下面代码

               $type=unpack("S1",substr($msg,2,2));

               #这里代表截取封包里0500并翻译为无符号短整数,赋值给$type,这时$type=5

               $val=unpack("L1",substr($msg,4,4));

               #截取E0100000并翻译为无符号长整数,赋值给$val,这时$val=4320

               if($type==0){

                       print"Something1:

$val\n"if$config{'debug'};

               }elsif($type==3){

                       print"Something2:

$val\n"if$config{'debug'};

               }elsif($type==5){

                       #当$type等于5时执行

                       $chars[$config{'char'}]{'hp'}=$val;

                       #把$val赋值给$chars[$config{'char'}]{'hp'}

                       print"Hp:

$val\n"if($config{'debug'}>=2);

               }...

以上的封包分析后,这个封包的内容就是告知客户端当前人物HP=4320

Kore第五讲:

封包分析子程序运作详解byICE-WR

从前面的介绍我们知道当收到RO服务器封包时,会执行子程序parseMsg()来进行封包分析,那parseMsg()是怎么运作的呢?

首先从Kore主程序结构里得知,Kore采用阻塞的方式进行封包接收,就是每隔一段时间收一次,这个循环时间大概是AI执行时间加上config.txt里sleepTime的微妙数。

收回来的封包会放在$msg里,然后把$msg交给parseMsg()来进行分析,parseMsg()的执行过程如下:

1)取$msg前两个字节,解释为封包头

2)根据封包头来选择分析代码

3)把分析了的封包信息删除,并把还没分析的返回给主程序

主程序根据$msg在执行parseMsg()分析前和分析后的长度是否相等,来判断是否还需要进行分析,假如分析前与分析后长度一样,代表分析完毕,假如不等,则继续循环(请参照第三节内容)

目前封包信息已知头信息均为0064~01FF,另外还有一个种只包含ACCOUNTID,以下为KE内的分析代码,采用MODKORE的计算方式

在主程序阶段执行了$msg=parseMsg($msg);后,运行以下代码

subparseMsg{

       my$msg=shift;

       #my为定义局部变量,shift为传递第一个子程序参数,并删除参数,perl里的子程序参数都以数组形式传递,这里是把主程序里的$msg引用到子程序中

       my$msg_size;

       #定义局部变量$msg_size,看字面解释就很清楚:

“封包长度”

       if(length($msg)<2){

       #length()函数是用来计算字符串长度,假如封包长度小于2,那就执行下面语句

               return$msg;

               #结束子程序,并返回$msg给主程序

       }

       #以上代码表示,最短可分析的封包长度是2,假如长度小于2,那就不分析

       $switch=uc(unpack("H2",substr($msg,1,1))).uc(unpack("H2",substr($msg,0,1)));

       #这里把封包前两位截取出来并赋值给$switch,$switch在子程序内代表封包头

       if(length($msg)>=4&&substr($msg,0,4)ne$accountID&&$conState>=4&&$lastswitchne$switch&&length($msg)>=unpack("S1",substr($msg,0,2))){

               decrypt(\$msg,$msg);

       }

       #这里是执行封包解密,有些服务器是封包加密形式的,对CRO没用

       $switch=uc(unpack("H2",substr($msg,1,1))).uc(unpack("H2",substr($msg,0,1)));

       #封包解密后从新计算封包头,对CRO没用

       if($lastswitcheq$switch&&length($msg)>$lastMsgLength){

               $errorCount++;

       }else{

               $errorCount=0;

       }

       if($errorCount>3){

               dumpData($msg);

               $errorCount=0;

               $msg_size=length($msg);

               print"封包解释错误:

$last_know_switch>$switch($msg_size)\n";

       }

       #以上是效验封包完整性,假如一个封包经过三次接收都还没被分析,会被认为是封包错误,把已经接收到的封包全部去掉。

造成封包错误的主要原因是封包长度错误,例如00B0长度8,假如我设置了00B0为长度6,经过一次封包解释后,删除了前面6个字节,得到后面的封包头为0000,不在0064~01FF这个范围,那就不能进行分析,Kore必须丢弃这些这些封包才能确保封包分析能继续执行下去。

       $lastswitch=$switch;

       #计算前记录下上一次分析前的封包头(用作完整性判断)

       if(substr($msg,0,4)ne$accountID||($conState!

=2&&$conState!

=4)){

       #RO封包里有个特殊的封包只返回AccountID,假如不是这个封包则进行下面的封包长度计算,$rpackets{$switch}代表从rpackets.txt里读取出来的封包长度,例如$rpackets{'00B0'}=8。

$switch范围为0064~01FF,超出这个范围的封包头肯定代表封包接收有问题!

               if($rpackets{$switch}eq"-"){

               #这种封包会把整个封包截取出来分析(实际上RO并没有这这种封包,只是在KARASU未解析出全部封包长度前,所遗留下来的问题--b)

                       $msg_size=length($msg);

               }elsif($rpackets{$switch}eq"0"){

               #判断是否非固定长度类封包,封包头为前2字节,封包长度保存在封包的第3-4字节里

                       if(length($msg)<4){

                               return$msg;

                       }

                       #由于这种封包前4位分别记录封包头和封包长度,所以小于4字节时代表封包还没接收完整,因此返回到主程序

                       $msg_size=unpack("S1",substr($msg,2,2));

                       #这里是从第3~4字节里计算出封包长度

                       if(length($msg)<$msg_size){

                               return$msg;

                       }

                       #假如收到的$msg还没到这个长度,代表封包还没接收完整,返回到主程序

               }elsif($rpackets{$switch}>1){

               #判断是否固定长度封包

                       if(length($msg)<$rpackets{$switch}){

                               return$msg;

                       }

                       #假如接收到的封包小于该封包的长度,代表封包还没接收完整,返回主程序

                       $msg_size=$rpackets{$switch};

                       #计算封包长度

               }else{

                       dumpData($last_know_msg.$msg);

                       #假如封包头不是在0064~01FF之间,代表封包接收或分析有问题,dumpDate会记录下目前已经收到的封包,并记录在dump.txt里

               }

               $last_know_msg=substr($msg,0,$msg_size);

               $last_know_switch=$switch;

               #以上用作效验封包完整性

       }

       $lastMsgLength=length($msg);

       #以上用作计算封包完整性

       接着会是一大堆if($switcheq"xxxx")...elsif...elsif...elsif,这些就是具体到每种封包的分析...

        完成分析后,在parseMsg()的最后会从$msg删除已经分析过的封包,如下:

        $msg=(length($msg)>=$msg_size)?

substr($msg,$msg_size,length($msg)-$msg_size):

"";

       return$msg;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1