ICEWR讲解Ke制作Word格式文档下载.docx
- 文档编号:22135057
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:8
- 大小:19.95KB
ICEWR讲解Ke制作Word格式文档下载.docx
《ICEWR讲解Ke制作Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《ICEWR讲解Ke制作Word格式文档下载.docx(8页珍藏版)》请在冰豆网上搜索。
Windows平台下的ActivePerl。
要想了解Kore,不需要对perl非常精通,当你第一次看Kore.pl时估计会非常头痛,一些语句甚至无法理解,大部分都是一些匹配模式,例如:
foreach(<
FILE>
){
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就等于"
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长度一样,那就代表已经没有要解释的封包,终止执行这个封包解释循环
#记录下解释后的封包长度,用作下一次比较
#上面的循环是用作接收指令和解释封包,执行后会运行以下子程序“AI”
$ai_cmdQue_shift=0;
#$ai_cmdQue是用作远程控制(聊天指令控制)
do{
AI(\%{$ai_cmdQue[$ai_cmdQue_shift]})if($conState==5&
&
timeOut(\%{$timeout{'
ai'
}})&
$remote_socket&
connected());
#$conState5代表已经完成登陆过程,并开始游戏;
因为进入游戏后会收到大量信息,所以等待timeout.txt里AI指定的秒数后才执行AI;
后面两个判断是代表连接正常
undef%{$ai_cmdQue[$ai_cmdQue_shift++]};
$ai_cmdQue--if($ai_cmdQue>
0);
#以上两句是用作执行远程控制
}while($ai_cmdQue>
checkConnection();
#管理数据通讯连接状况的子程序,例如:
登陆和断线等功能
}
Kore第四讲:
RO封包简要说明byICE-WR
RO客户端与服务器间通过TCP协议连接,并互相传递信息,封包内容类似
B0000500E0100000
#00b0<
type>
w<
val>
l
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){
Something2:
}elsif($type==5){
#当$type等于5时执行
$chars[$config{'
char'
}]{'
hp'
}=$val;
#把$val赋值给$chars[$config{'
Hp:
if($config{'
}>
=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("
substr($msg,0,1)));
#这里把封包前两位截取出来并赋值给$switch,$switch在子程序内代表封包头
if(length($msg)>
=4&
substr($msg,0,4)ne$accountID&
$conState>
$lastswitchne$switch&
length($msg)>
=unpack("
substr($msg,0,2))){
decrypt(\$msg,$msg);
#这里是执行封包解密,有些服务器是封包加密形式的,对CRO没用
#封包解密后从新计算封包头,对CRO没用
if($lastswitcheq$switch&
$lastMsgLength){
$errorCount++;
}else{
$errorCount=0;
if($errorCount>
3){
dumpData($msg);
$msg_size=length($msg);
封包解释错误:
$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)
}elsif($rpackets{$switch}eq"
0"
#判断是否非固定长度类封包,封包头为前2字节,封包长度保存在封包的第3-4字节里
4){
#由于这种封包前4位分别记录封包头和封包长度,所以小于4字节时代表封包还没接收完整,因此返回到主程序
$msg_size=unpack("
substr($msg,2,2));
#这里是从第3~4字节里计算出封包长度
$msg_size){
#假如收到的$msg还没到这个长度,代表封包还没接收完整,返回到主程序
}elsif($rpackets{$switch}>
1){
#判断是否固定长度封包
$rpackets{$switch}){
#假如接收到的封包小于该封包的长度,代表封包还没接收完整,返回主程序
$msg_size=$rpackets{$switch};
#计算封包长度
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):
"
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ICEWR 讲解 Ke 制作