最近在研究一款全中国目前最火flash游戏。大大们都说flash游戏不能找Call 找基址的。。看到别人的游戏辅助。。可以读取人物品等级这些关键信息的。。不是用找图找字这方式的。应该是读取内存里面的数据的。。请问他们是如何实现的呢?我反汇编了一下这个Main.SWF 是加过密的。还混淆过的。几经周折。最终从IE的内存中提取出来的。AS3的代码很多页,这里只贴出发包代码:
package socket2
{
import flash.net.Socket;
import flash.utils.ByteArray;
import flash.events.Event;
import view.Logview;
import flash.events.ProgressEvent;
import flash.utils.getTimer;
import mirFcc._mirFcc_readSocketData_;
import flash.errors.IOError;
import mirFcc._mirFcc_doSend_;
import mirFcc._mirFcc_doSend2_;
import mirFcc._mirFcc_doSend3_;
import mirFcc._mirFcc_transform_;
import mirFcc._mirFcc_doSend4_;
public class CustomSocket extends Socket
{
private static var SEVEN_BIT_MASK2:int = 127;
private static var SYMBOL_BIT_MASK2:int = ~SEVEN_BIT_MASK2;
public static var code_index:int = 0;
public static var code_Key:int = 0;
public static var buffMessages:Array = [];
public static var messageArray:Vector.<Array> = new Vector.<Array>();
private static var MESSAGE_HEAD:int = 5120;
private static var BUFFER_MAX_LENGTH:int = 20000000;
private static var PACKAGE_HEAD_LEN:uint = 4;
private var _host:String;
private var _port:int;
private var bufferByteArray:ByteArray;
private var time:int;
public var receivedHandler:Function;
public var receivedHandler2:Function;
public var closeFunc:Function;
private var sendTime:int;
public function CustomSocket(param1:String = null, param2:int = 0)
{
bufferByteArray = new ByteArray();
super(param1,param2);
addEventListener("socketData",socketDataHandler);
addEventListener("close",_closeFunc_);
}
protected function _closeFunc_(param1:Event) : void
{
Logview.log(CustomSocket,"socket連接已斷開---->");
if(closeFunc != null)
{
closeFunc(param1);
}
}
public function get host() : String
{
return _host;
}
public function get port() : int
{
return _port;
}
override public function connect(param1:String, param2:int) : void
{
this._host = param1;
this._port = param2;
if(param1)
{
super.connect(param1,param2);
}
}
protected function socketDataHandler(param1:ProgressEvent) : void
{
var _loc2_:* = null;
time = getTimer();
readBytes(bufferByteArray,bufferByteArray.length,bytesAvailable);
if(bufferByteArray.length > BUFFER_MAX_LENGTH)
{
_loc2_ = new ByteArray();
bufferByteArray.readBytes(_loc2_,0,bufferByteArray.bytesAvailable);
bufferByteArray.position = 0;
bufferByteArray.length = 0;
_loc2_.readBytes(bufferByteArray,0,_loc2_.bytesAvailable);
}
readSocketData();
}
private function readSocketData() : void
{
var _loc2_:* = null;
var _loc1_:* = null;
if(bufferByteArray.bytesAvailable < 3)
{
return;
}
_loc2_ = new ByteArray();
_loc1_ = {
"resule":0,
"msgLen":0,
"msgID":0
};
_mirFcc_readSocketData_(bufferByteArray,SEVEN_BIT_MASK2,SYMBOL_BIT_MASK2,_loc2_,_loc1_);
if(_loc1_.resule > 0)
{
messageArray.push([_loc1_.msgID,_loc2_,_loc1_.msgID]);
if(receivedHandler2 != null)
{
receivedHandler2();
}
return;
}
if(_loc1_.resule == -1)
{
throw new Error("非法协议,消息体过小msgID:" + _loc1_.msgID + " msgLen:" + _loc1_.msgLen);
}
else if(_loc1_.resule == -2)
{
throw new Error("非法协议,消息体过长msgID:" + _loc1_.msgID + " msgLen:" + _loc1_.msgLen);
}
else
{
return;
}
}
public function doSend(param1:int, param2:ByteArray) : void
{
var _loc4_:* = 0;
var _loc6_:* = null;
var _loc3_:* = 0;
if(param1 == 0)
{
throw new Error("请求消息号不能为0");
}
else
{
sendTime = getTimer();
var _loc5_:ByteArray = new ByteArray();
_mirFcc_doSend_(param1,param2,code_Key,_loc5_);
if(code_Key > 0)
{
CustomSocket.code_index = CustomSocket.code_index + 1;
if(CustomSocket.code_index > 32767)
{
CustomSocket.code_index = 1;
}
_loc4_ = MIR_CRC.CRC.genSNO(CustomSocket.code_index,code_Key);
_loc6_ = new ByteArray();
_mirFcc_doSend2_(param2,_loc4_,_loc6_);
MIR_CRC.CRC.reset();
MIR_CRC.CRC.update(_loc6_);
_loc3_ = MIR_CRC.CRC.getValue();
_mirFcc_doSend3_(_loc5_,_loc3_,_loc4_);
param2.position = 0;
_mirFcc_transform_(param2,code_Key);
param2.position = 0;
}
_mirFcc_doSend4_(_loc5_,param2,CustomSocket.code_index);
try
{
this.writeBytes(_loc5_);
this.flush();
}
catch(e:IOError)
{
trace("发包失败:---》",param1);
}
return;
}
}
}
}
封包加密方式看上去还是很复杂的。加入了时间计算,加了CRC校验。加了封包序列号。等。
有几个关键的function 反汇编不出来。最终放弃了。
然后用OD调试。结果越调头越大,我是新手。百度。google搜索了一大堆。如何找flash基址,没有答案,折腾了半个月了。。实在不甘心呀。如果说没有基址,可是别人做出的辅助。可以改关键跳。去检测。达到游戏加速,写入内存实现暗杀,远程捡物,等变态功能呢?有时我在想是不是真的没有基址,还是我们还没有掌握这门新的技术呢。如果你也和我一样有这样的困境,可以私信我,加好友。。我们一起研究。如果你知道方法,希望还不吝赐教。谢谢
[课程]Linux pwn 探索篇!