jcestruct是鹅厂自研的一个协议,本篇文章相对于全面的进行分析下实现过程及其分析的心得,本文仅以技术角度分析下某鹅浏览器采用该协议的优良性,希望更多的人能认识到除了json,protobuf外还有个藏在我们眼皮子底下的技术。
⊙一. 什么是jcestruct
⊙二. jcestruct在某浏览器的应用
⊙三. 010editor手动还原jcestruct协议
⊙四. js实现的jcestruct
⊙总结
一.什么是jcestruct
jcestruct顾名思义是一个二进制传输协议,能够把传输的字段抽象为某种结构的一种传输协议。
有些形似protobuf协议,但是与protobuf协议存在数据组包的一些差异。
1.1节省传输空间
客户端和服务器端要通讯,如果正常的json请求,客户端发送的是 {"客户端小杜":我要下单3070显卡},服务端回复的{"老黄的回复": 早卖给矿老板了},这时完成了一次请求的发送。
但是我们看这次发送有什么问题呢,首先发送数据的长度为整个json字符串的长度,读者读到这里有可能说这么短能占用多少流量呢,其实不然,如果在京东/天猫双11抢购的时候,发送的报文远远超过这个长度,同时服务器要发送大量的相应报文给客户端,这样同时1000w人下单对于服务器的压力就比较大了,jcestruct相对于json请求有什么区别呢?
下面是客户端和服务端发送信息时类结构体的封装
struct 小杜{
String message;
}
小杜.message = "我要下单3070显卡"
struct 老黄{
String message;
}
老黄.message = "早卖给矿老板了"
这时候 客户端发送给服务器的为bin("我要下单3070显卡"),服务器则直接返回bin("早卖给矿老板了") ,这时其实已经节省了传输中很大的占用空间了。
1.2可扩展空间强
在电商平台我们要是购买东西的时候发往后台的数据包括一些价格(整数型),商品名称(字符串型),风控时手机的一些信息(map型),上传图片识别地址(字节集型),针对那么多的类型在json里面不是那么好处理,但是jcestruct从设计上面包括以下的类型。
类型值 | 数据类型 |
0 | byte或者bool |
1 | short |
2 | int |
3 | long |
4 | float |
5 | double |
6 |
string:先存一字节长度 后续存字符 |
7 |
string:先存4字节长度 后续 存字符 |
8 | map |
9 |
list |
10 |
STRUCT_BEGIN |
11 |
STRUCT_END |
12 |
ZERO_TAG |
13 |
TYPE_SIMPLE_LIST |
这些类型足够可以满足复杂通信过程中所必须的数据类型。
有了类型我们探讨下一个问题,这些类型到底组合拼接后发送到服务器的呢?
jce的编码及其结构:
//在文本存储中的结构
keyvaluekeyvaluekeyvalue
读者朋友们这时又说了 你骗人,前面不是说不用传key的吗?
当然了这里的key是抽象结构体的key。key也就是头的一种抽象描述,等同于下面的
结构体为:
node HeadData {
int tag;
unsigned char type;
}
key的数据解析的规则是:低4位为类型,高四位为tag 如果 tag 为0xF 则下一个字节为tag.
key由tag和type组成。Key为1个字节或两个字节.两个字节时第二个字节为tag否则第一个字节的高4位为tag.type始终为第一个字节的低4位。type最多有16种类型,tag最大为256(2的八次方)。
key为了描述后方的value,key中的type为上方表中的数据类型中的一种,其中key中的tag为了表示序列(0,1,2,3,4.....255)
这个时候可能有认真的读者就说了,我用json字段可以超过255个,jcestruct听你介绍这意思就是不行呗,果然我大json才是最牛的?
其实不然 255个序列确实是线性排布的,但是TYPE_SIMPLE_LIST类型存储的是字节数组,而且jcestruct这个序列传输的时候确实是字节数组,那么在这种情况下,就可以把A的jcestruct转为字节集的结构存放在B的结构体中,可以形象的称谓套娃,通过这种操作其实jcestruct可以结构可以存储的数据容量是非常大的(我也不知道有多大 很大就是了)
1.3 多语言可实现兼容多种客户端
jcestruct广泛运用于多个产品(多是腾旭的),在腾讯qq 的内部传输实现,包括马总其他app也是广泛运用这个协议,目前作者已知的在c语言、c#、go、python、java、js、易语言中均已经有实现的api调用。那么在这种情况下,在使用该语言的服务端上面和使用如上语言实现的客户端上面均可建立通信,只要遵从这个协议就可非常完美的进行通信了。
1.4 安全性
jce本身这种协议的解码对于不懂这个协议的人来说就是一个不小的挑战,明明数据就在那,替换了也没法伪造;当然对于了解此协议比较熟悉的大佬,看见这个协议利用010editor即可还原其协议本来的面目,那么如果我们身为一个开发者如果不从加密算法上下功夫,如何保护我们的数据不被攻击方所获取呢,有一个很容易的操作就是对jcestruct进行魔改,这时有读者说了,我再怎么魔改也是13个数据类型呀,的确是这样,但是我们可以在开发过程中把数据类型标志换为其他的数据类型,例如0在上方表示的byte但是通过我们偷换为1位byte剩下的随机切换,这样一进行修改,对于逆向分析的人来说,首先要找到每个标号所对应的数据类型,其次再去修改jcestruct的实现,已经实现了保护的目的;另一种我们可以在jcestruct里面嵌入protobuf协议,因为jcestruct可以涵盖字节,广而推之不止protobuf协议可以集成进去,只要可以被转为二进制的协议我们都可以放入;这只是从协议层进行防护,同样的,可以从传输时gzip+对称加密算法,基本上可以拦截大多数的人了,大佬就是你,你除外。
二.jcestruct在某浏览器的应用
app逆向分析加密过程写出来可能会侵犯厂商的利益,所以用以下几句概括下,从浏览器旧版本升级到新版本之后,原有的java层代码实现的jcestruct协议已经不再走(通过hook验证确实没走),之后经过读者分析,浏览器换了种更优雅的方式,即通过js实现jcestruct协议然后在webview这个里面实现自己的逻辑,这种实现方法方便以后更新主页的显示的时候直接通过改动index的js文件即可替换逻辑,方只从jcestruct协议的实现和使用上面来写。
在这个app当时进行分析的目的是看一下广告包存在于那个请求内,经过了抓包分析定位之后定位到了广告包。
从charles里面保存响应包的二进制数据。
然后进行解密,代码如下:
def decode_content(key = "3B73D4C094BB98234508E97E1037FD1C", iv = "706c65b5016ccb24"):
key = bytes.fromhex(key)
f = open(r"C:UsersAdministratorDesktop浏览器pac", "rb").read()
aes_decrpyt_data = utils().aesDecrypt(key, iv, f)
uncompress_data = utils().zlibDeCompress(aes_decrpyt_data)
with open("encodedata","wb") as f:
f.write(bytes.fromhex(uncompress_data.hex()[8:]))
print(result)
这时候就会得出经过aes解密和gzip解压之后的jce二进制文件,然后下一个章节我们介绍,如何根据以上的内容手动解析一下jcestruct。
jcestruct被加密后
jcestruct被解密后
三.010editor手动还原jcestruct协议
10 :高位为1,低位为0,那么tag=1,0代表后面有一个字节 为 02
2C:高位为2,低位为C,那么tag=2,C代表的为zero,所以后面没有任何值
3C,4C和上面的解释相同
56:tag=5 类型为6,字符串后加一个字符串的长度(0A),之后跟的是数据(红色方块中的AdsGateWay)
66:tag=6 类型为6,长度(0F),getBatchAdsData
simelist一直到
7D:tag=7 类型为D,相当于是个字节字节数组 ,00为死数没有含义,01表示数组的类型为short,0x6e3=1763;那么 0x6e3+0x26 =0x709
8c: tag =8,类型为c zero
98:tag=9 ,类型为map 长度为0
a8:tag=10,类型为map 长度为0
大体上已经手动解析完了,但是tag =7的时候包含的为TYPE_SIMPLE_LIST,其实也是jcestruct结构被转为二进制之后的数据,想分析的读者,也可按照上方的方法来进行推算。
很多读者其实看到这里会说,你怎么知道每个类型后面跟的是长度还是数据,当然了 我也是看了源码后才知道的
首先看几个函数
0 byte bool
如果是0 直接走的是type12类型(ZERO_TAG) 写一个头就完事了,其他的情况下还得写入一个头 后面直接存储一个字节的内容
public void write(byte b, int i) {
reserve(3);
if (b == (byte) 0) {
writeHead((byte) 12, i);
return;
}
writeHead((byte) 0, i);
this.bs.put(b);
}
我们看到存取bool类型的操作也跑到上面的函数里面去了
public void write(boolean z, int i) {
write((byte) (z ? 1 : 0), i);
}
1 short
超过一个字节的会以short的类型进行存储,如果一个字节的情况下直接转为 0的方式存储了 这样可以节省内存空间
public void write(short s, int i) {
reserve(4);
if (s < (short) -128 || s > (short) 127) {
writeHead((byte) 1, i);
this.bs.putShort(s);
return;
}
write((byte) s, i);
}
2 int
数据长度如果超过二个字节存储不下就会存int,如果否则就走short的存储方式
public void write(int i, int i2) {
reserve(6);
if (i < -32768 || i > 32767) {
writeHead((byte) 2, i2);
this.bs.putInt(i);
return;
}
write((short) i, i2);
}
3 long
数据所能容纳的最大的长度为超过四个字节的时候就会使用long类型,如果没超过就使用int'
public void write(long j, int i) {
reserve(10);
if (j < -2147483648L || j > 2147483647L) {
writeHead((byte) 3, i);
this.bs.putLong(j);
return;
}
write((int) j, i);
}
对 0 1 2 3 的归纳
byte short int long这四种发现jcestruct对他们的处理是能省则省,就是能用小的存储空间代替就不用大的,特别是byte 表示零的情况下直接用zerotag来表示。
4 float
float不会向前面那四个类型一样进行节省空间而转换为其他的类型, float占用四个字节
public void write(float f, int i) {
reserve(6);
writeHead((byte) 4, i);
this.bs.putFloat(f);
}
5 double
double也不会像前面那四个类型一样进行节省空间而转换为其他的类型 double 占用的也为 8个字节
public void write(double d, int i) {
reserve(10);
writeHead((byte) 5, i);
this.bs.putDouble(d);
}
6.7 string
都是存储的字符串
type6存储额短符串如果字符串的长度小于等于255(这个255正好是一个字节 2^8)
type7存储长字符串 当字符串长度大于255(一个字节装不下的时候)就用四个字节来装长度了,然后再押入字符串
public void write(String str, int i) {
byte[] bytes;
try {
bytes = str.getBytes(this.sServerEncoding);
} catch (UnsupportedEncodingException e) {
bytes = str.getBytes();
}
reserve(bytes.length + 10);
if (bytes.length > 255) {
writeHead((byte) 7, i);
this.bs.putInt(bytes.length);
this.bs.put(bytes);
return;
}
writeHead((byte) 6, i);
this.bs.put((byte) bytes.length);
this.bs.put(bytes);
}
8 map
maptype +maptag +(lenghtype + tag0),然后将键值依次排列后面 key的tag统一为0 value的tag统一为1
public <K, V> void write(Map<K, V> map, int i) {
reserve(8);
writeHead((byte) 8, i);
write(map == null ? 0 : map.size(), 0);
if (map != null) {
for (Entry entry : map.entrySet()) {
write(entry.getKey(), 0);
write(entry.getValue(), 1);
}
}
}
9 list
list顾名思义可以存放任意类型的,同样用 byte short int long 来表示长度,同时list每个元素的tag都为0 ,从这套代码的设计来看,都可以进行循环嵌套进行赋值
public <T> void write(Collection<T> collection, int i) {
reserve(8);
writeHead((byte) 9, i);
write(collection == null ? 0 : collection.size(), 0);
if (collection != null) {
for (T write : collection) {
write((Object) write, 0);
}
}
}
public void write(Object obj, int i) {
if (obj instanceof Byte) {
write(((Byte) obj).byteValue(), i);
} else if (obj instanceof Boolean) {
write(((Boolean) obj).booleanValue(), i);
} else if (obj instanceof Short) {
write(((Short) obj).shortValue(), i);
} else if (obj instanceof Integer) {
write(((Integer) obj).intValue(), i);
} else if (obj instanceof Long) {
write(((Long) obj).longValue(), i);
} else if (obj instanceof Float) {
write(((Float) obj).floatValue(), i);
} else if (obj instanceof Double) {
write(((Double) obj).doubleValue(), i);
} else if (obj instanceof String) {
write((String) obj, i);
} else if (obj instanceof Map) {
write((Map) obj, i);
} else if (obj instanceof List) {
write((List) obj, i);
} else if (obj instanceof JceStruct) {
write((JceStruct) obj, i);
} else if (obj instanceof byte[]) {
write((byte[]) obj, i);
} else if (obj instanceof boolean[]) {
write((boolean[]) obj, i);
} else if (obj instanceof short[]) {
write((short[]) obj, i);
} else if (obj instanceof int[]) {
write((int[]) obj, i);
} else if (obj instanceof long[]) {
write((long[]) obj, i);
} else if (obj instanceof float[]) {
write((float[]) obj, i);
} else if (obj instanceof double[]) {
write((double[]) obj, i);
} else if (obj.getClass().isArray()) {
writeArray((Object[]) obj, i);
} else if (obj instanceof Collection) {
write((Collection) obj, i);
} else {
throw new JceEncodeException("write object error: unsupport type. " + obj.getClass());
}
}
10 ,11 STRUCT_BEGIN STRUCT_END
这个主要运用于一个类里面的成员还有其他jcestruct的子类的实现的时候就会使用这种方法
public void write(JceStruct jceStruct, int i) {
reserve(2);
writeHead((byte) 10, i);
jceStruct.writeTo(this);
reserve(2);
writeHead((byte) 11, 0);
}
12 zero_tag
一般表示空的直接一个空的头占领了位置
writeHead((byte) 12, i);
13TYPE_SIMPLE_LIST
后来加的一个结构,就是个bytes数组,不知道为什么要有这个结构,先接一个byte表示长度类型,
public void write(byte[] bArr, int i) {
reserve(bArr.length + 8);
writeHead((byte) 13, i);
writeHead((byte) 0, 0);
write(bArr.length, 0);
this.bs.put(bArr);
}
四.js实现的jcestruct
这里放一份可以组包的js作为彩蛋
python调用端代码
import execjs
def get_js():
f = open(r"jcestruct.js", 'r', encoding="utf-8")
line = f.readline()
htmlstr = ''
while line:
htmlstr = htmlstr + line
line = f.readline()
ctx = execjs.compile(htmlstr)
content = bytes.fromhex(ctx.call('main'))
print(content)
return ctx.call('main')
print(get_js())
js组包代码
const Taf = {};
Taf.INT8 = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeInt8(e, i)
}
this._read = function (t, e, i) {
return t.readInt8(e, true, i)
}
this._className = function () {
return Taf.CHAR
}
}
Taf.INT16 = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeInt16(e, i)
}
this._read = function (t, e, i) {
return t.readInt16(e, true, i)
}
this._className = function () {
return Taf.SHORT
}
}
Taf.INT32 = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeInt32(e, i)
}
this._read = function (t, e, i) {
return t.readInt32(e, true, i)
}
this._className = function () {
return Taf.INT32
}
}
Taf.INT64 = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeInt64(e, i)
}
this._read = function (t, e, i) {
return t.readInt64(e, true, i)
}
this._className = function () {
return Taf.INT64
}
}
Taf.UINT8 = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeInt16(e, i)
}
this._read = function (t, e, i) {
return t.readInt16(e, true, i)
}
this._className = function () {
return Taf.SHORT
}
}
Taf.UInt16 = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeInt32(e, i)
}
this._read = function (t, e, i) {
return t.readInt32(e, true, i)
}
this._className = function () {
return Taf.INT32
}
}
Taf.UInt32 = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeInt64(e, i)
}
this._read = function (t, e, i) {
return t.readInt64(e, true, i)
}
this._className = function () {
return Taf.INT64
}
}
Taf.Float = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeFloat(e, i)
}
this._read = function (t, e, i) {
return t.readFloat(e, true, i)
}
this._className = function () {
return Taf.FLOAT
}
}
Taf.Double = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeDouble(e, i)
}
this._read = function (t, e, i) {
return t.readDouble(e, true, i)
}
this._className = function () {
return Taf.DOUBLE
}
}
Taf.STRING = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeString(e, i)
}
this._read = function (t, e, i) {
return t.readString(e, true, i)
}
this._className = function () {
return Taf.STRING
}
}
Taf.BOOLEAN = function () {
this._clone = function () {
return false
}
this._write = function (t, e, i) {
return t.writeBoolean(e, i)
}
this._read = function (t, e, i) {
return t.readBoolean(e, true, i)
}
this._className = function () {
return Taf.BOOLEAN
}
}
Taf.ENUM = function () {
this._clone = function () {
return 0
}
this._write = function (t, e, i) {
return t.writeInt32(e, i)
}
this._read = function (t, e, i) {
return t.readInt32(e, true, i)
}
}
Taf.Vector = function (t) {
this.proto = t
this.value = new Array
}
Taf.Vector.prototype._clone = function () {
return new Taf.Vector(this.proto)
}
Taf.Vector.prototype._write = function (t, e, i) {
return t.writeVector(e, i)
}
Taf.Vector.prototype._read = function (t, e, i) {
return t.readVector(e, true, i)
}
Taf.Vector.prototype._className = function () {
return Taf.TypeHelp.VECTOR.replace("$t", this.proto._className())
}
Taf.Map = function (t, e) {
this.kproto = t
this.vproto = e
this.value = new Object
}
Taf.Map.prototype._clone = function () {
return new Taf.Map(this.kproto, this.vproto)
}
Taf.Map.prototype._write = function (t, e, i) {
return t.writeMap(e, i)
}
Taf.Map.prototype._read = function (t, e, i) {
return t.readMap(e, true, i)
}
Taf.Map.prototype.put = function (t, e) {
this.value[t] = e
}
Taf.Map.prototype.get = function (t) {
return this.value[t]
}
Taf.Map.prototype.remove = function (t) {
delete this.value[t]
}
Taf.Map.prototype.clear = function () {
this.value = new Object
}
Taf.Map.prototype.size = function () {
var t = 0
for (var e in this.value) {
t++
}
return t
}
Taf.Vector.prototype._className = function () {
return Taf.TypeHelp.Map.replace("$k", this.kproto._className()).replace("$v", this.vproto._className())
}
Taf.DataHelp = {
EN_INT8: 0,
EN_INT16: 1,
EN_INT32: 2,
EN_INT64: 3,
EN_FLOAT: 4,
EN_DOUBLE: 5,
EN_STRING1: 6,
EN_STRING4: 7,
EN_MAP: 8,
EN_LIST: 9,
EN_STRUCTBEGIN: 10,
EN_STRUCTEND: 11,
EN_ZERO: 12,
EN_SIMPLELIST: 13
}
Taf.TypeHelp = {
BOOLEAN: "bool",
CHAR: "char",
SHORT: "short",
INT32: "int32",
INT64: "int64",
FLOAT: "float",
DOUBLE: "double",
STRING: "string",
VECTOR: "list<$t>",
MAP: "map<$k, $v>"
}
Taf.BinBuffer = function (t) {
this.buf = null
this.vew = null
this.len = 0
this.position = 0
if (t != null && t != undefined && t instanceof Taf.BinBuffer) {
this.buf = t.buf
this.vew = new DataView(this.buf)
this.len = t.length
this.position = t.position
}
if (t != null && t != undefined && t instanceof ArrayBuffer) {
this.buf = t
this.vew = new DataView(this.buf)
this.len = this.vew.byteLength
this.position = 0
}
this.__defineGetter__("length", function () {
return this.len
})
this.__defineGetter__("buffer", function () {
return this.buf
})
}
Taf.BinBuffer.prototype._write = function (t, e, i) {
return t.writeBytes(e, i)
}
Taf.BinBuffer.prototype._read = function (t, e, i) {
return t.readBytes(e, true, i)
}
Taf.BinBuffer.prototype._clone = function () {
return new Taf.BinBuffer
}
Taf.BinBuffer.prototype.allocate = function (t) {
t = this.position + t
if (this.buf != null && this.buf.length > t) {
return
}
var e = new ArrayBuffer(Math.max(256, t * 2))
if (this.buf != null) {
new Uint8Array(e).set(new Uint8Array(this.buf))
this.buf = undefined
}
this.buf = e
this.vew = undefined
this.vew = new DataView(this.buf)
}
Taf.BinBuffer.prototype.getBuffer = function () {
var t = new ArrayBuffer(this.len)
new Uint8Array(t).set(new Uint8Array(this.buf, 0, this.len))
return t
}
Taf.BinBuffer.prototype.memset = function (t, e, i) {
this.allocate(i)
new Uint8Array(this.buf).set(new Uint8Array(t, e, i), this.position)
}
Taf.BinBuffer.prototype.writeInt8 = function (t) {
this.allocate(1)
this.vew.setInt8(this.position, t)
this.position += 1
this.len = this.position
}
Taf.BinBuffer.prototype.writeUInt8 = function (t) {
this.allocate(1)
this.vew.setUint8(this.position++, t)
this.len = this.position
}
Taf.BinBuffer.prototype.writeInt16 = function (t) {
this.allocate(2)
this.vew.setInt16(this.position, t)
this.position += 2
this.len = this.position
}
Taf.BinBuffer.prototype.writeUInt16 = function (t) {
this.allocate(2)
this.vew.setUint16(this.position, t)
this.position += 2
this.len = this.position
}
Taf.BinBuffer.prototype.writeInt32 = function (t) {
this.allocate(4)
this.vew.setInt32(this.position, t)
this.position += 4
this.len = this.position
}
Taf.BinBuffer.prototype.writeUInt32 = function (t) {
this.allocate(4)
this.vew.setUint32(this.position, t)
this.position += 4
this.len = this.position
}
Taf.BinBuffer.prototype.writeInt64 = function (t) {
this.allocate(8)
this.vew.setUint32(this.position, parseInt(t / 4294967296))
this.vew.setUint32(this.position + 4, t % 4294967296)
this.position += 8
this.len = this.position
}
Taf.BinBuffer.prototype.writeFloat = function (t) {
this.allocate(4)
this.vew.setFloat32(this.position, t)
this.position += 4
this.len = this.position
}
Taf.BinBuffer.prototype.writeDouble = function (t) {
this.allocate(8)
this.vew.setFloat64(this.position, t)
this.position += 8
this.len = this.position
}
Taf.BinBuffer.prototype.writeString = function (t) {
for (var e = [], i = 0; i < t.length; i++) {
e.push(t.charCodeAt(i) & 255)
}
this.allocate(e.length)
new Uint8Array(this.buf).set(new Uint8Array(e), this.position)
this.position += e.length
this.len = this.position
}
Taf.BinBuffer.prototype.writeBytes = function (t) {
if (t.length == 0 || t.buf == null)
return
this.allocate(t.length)
new Uint8Array(this.buf).set(new Uint8Array(t.buf, 0, t.length), this.position)
this.position += t.length
this.len = this.position
}
Taf.BinBuffer.prototype.readInt8 = function () {
return this.vew.getInt8(this.position++)
}
Taf.BinBuffer.prototype.readInt16 = function () {
this.position += 2
return this.vew.getInt16(this.position - 2)
}
Taf.BinBuffer.prototype.readInt32 = function () {
this.position += 4
return this.vew.getInt32(this.position - 4)
}
Taf.BinBuffer.prototype.readUInt8 = function () {
this.position += 1
return this.vew.getUint8(this.position - 1)
}
Taf.BinBuffer.prototype.readUInt16 = function () {
this.position += 2
return this.vew.getUint16(this.position - 2)
}
Taf.BinBuffer.prototype.readUInt32 = function () {
this.position += 4
return this.vew.getUint32(this.position - 4)
}
Taf.BinBuffer.prototype.readInt64 = function () {
var t = this.vew.getUint32(this.position)
var e = this.vew.getUint32(this.position + 4)
this.position += 8
return t * 4294967296 + e
}
Taf.BinBuffer.prototype.readFloat = function () {
var t = this.vew.getFloat32(this.position)
this.position += 4
return t
}
Taf.BinBuffer.prototype.readDouble = function () {
var t = this.vew.getFloat64(this.position)
this.position += 8
return t
}
Taf.BinBuffer.prototype.readString = function (t) {
for (var e = [], i = 0; i < t; i++) {
e.push(String.fromCharCode(this.vew.getUint8(this.position++)))
}
var r = e.join("")
try {
r = decodeURIComponent(escape(r))
} catch (t) {
}
return r
}
Taf.BinBuffer.prototype.readBytes = function (t) {
var e = new Taf.BinBuffer
e.allocate(t)
e.memset(this.buf, this.position, t)
e.position = 0
e.len = t
this.position = this.position + t
return e
}
Taf.JceOutputStream = function () {
this.buf = new Taf.BinBuffer
this.getBinBuffer = function () {
return this.buf
}
this.getBuffer = function () {
return this.buf.getBuffer()
}
}
Taf.JceOutputStream.prototype.writeTo = function (t, e) {
if (t < 15) {
this.buf.writeUInt8(t << 4 & 240 | e)
} else {
this.buf.writeUInt16((240 | e) << 8 | t)
}
}
Taf.JceOutputStream.prototype.writeBoolean = function (t, e) {
this.writeInt8(t, e == true ? 1 : 0)
}
Taf.JceOutputStream.prototype.writeInt8 = function (t, e) {
if (e == 0) {
this.writeTo(t, Taf.DataHelp.EN_ZERO)
} else {
this.writeTo(t, Taf.DataHelp.EN_INT8)
this.buf.writeInt8(e)
}
}
Taf.JceOutputStream.prototype.writeInt16 = function (t, e) {
if (e >= -128 && e <= 127) {
this.writeInt8(t, e)
} else {
this.writeTo(t, Taf.DataHelp.EN_INT16)
this.buf.writeInt16(e)
}
}
Taf.JceOutputStream.prototype.writeInt32 = function (t, e) {
if (e >= -32768 && e <= 32767) {
this.writeInt16(t, e)
} else {
this.writeTo(t, Taf.DataHelp.EN_INT32)
this.buf.writeInt32(e)
}
}
Taf.JceOutputStream.prototype.writeInt64 = function (t, e) {
if (e >= -2147483648 && e <= 2147483647) {
this.writeInt32(t, e)
} else {
this.writeTo(t, Taf.DataHelp.EN_INT64)
this.buf.writeInt64(e)
}
}
Taf.JceOutputStream.prototype.writeUInt8 = function (t, e) {
this.writeInt16(t, e)
}
Taf.JceOutputStream.prototype.writeUInt16 = function (t, e) {
this.writeInt32(t, e)
}
Taf.JceOutputStream.prototype.writeUInt32 = function (t, e) {
this.writeInt64(t, e)
}
Taf.JceOutputStream.prototype.writeFloat = function (t, e) {
if (e == 0) {
this.writeTo(t, Taf.DataHelp.EN_ZERO)
} else {
this.writeTo(t, Taf.DataHelp.EN_FLOAT)
this.buf.writeFloat(e)
}
}
Taf.JceOutputStream.prototype.writeDouble = function (t, e) {
if (e == 0) {
this.writeTo(t, Taf.DataHelp.EN_ZERO)
} else {
this.writeTo(t, Taf.DataHelp.EN_DOUBLE)
this.buf.writeDouble(e)
}
}
Taf.JceOutputStream.prototype.writeStruct = function (t, e) {
if (e.writeTo == undefined) {
throw Error("not defined writeTo Function")
}
this.writeTo(t, Taf.DataHelp.EN_STRUCTBEGIN)
e.writeTo(this)
this.writeTo(0, Taf.DataHelp.EN_STRUCTEND)
}
Taf.JceOutputStream.prototype.writeString = function (t, e) {
var i = e
try {
i = unescape(encodeURIComponent(i))
} catch (t) {
}
if (i.length > 255) {
this.writeTo(t, Taf.DataHelp.EN_STRING4)
this.buf.writeUInt32(i.length)
} else {
this.writeTo(t, Taf.DataHelp.EN_STRING1)
this.buf.writeUInt8(i.length)
}
this.buf.writeString(i)
}
Taf.JceOutputStream.prototype.writeBytes = function (t, e) {
if (!(e instanceof Taf.BinBuffer)) {
throw Error("value not instanceof Taf.BinBuffer")
}
this.writeTo(t, Taf.DataHelp.EN_SIMPLELIST)
this.writeTo(0, Taf.DataHelp.EN_INT8)
this.writeInt32(0, e.length)
this.buf.writeBytes(e)
}
Taf.JceOutputStream.prototype.writeVector = function (t, e) {
this.writeTo(t, Taf.DataHelp.EN_LIST)
this.writeInt32(0, e.value.length)
for (var i = 0; i < e.value.length; i++) {
e.proto._write(this, 0, e.value[i])
}
}
Taf.JceOutputStream.prototype.writeMap = function (t, e) {
this.writeTo(t, Taf.DataHelp.EN_MAP)
this.writeInt32(0, e.size())
for (var i in e.value) {
e.kproto._write(this, 0, i)
e.vproto._write(this, 1, e.value[i])
}
}
Taf.JceInputStream = function (t) {
this.buf = new Taf.BinBuffer(t)
}
Taf.JceInputStream.prototype.readFrom = function () {
var t = this.buf.readUInt8()
var e = (t & 240) >> 4
var i = t & 15
if (e >= 15)
e = this.buf.readUInt8()
return {
tag: e,
type: i
}
}
Taf.JceInputStream.prototype.peekFrom = function () {
var t = this.buf.position
var e = this.readFrom()
this.buf.position = t
return {
tag: e.tag,
type: e.type,
size: e.tag >= 15 ? 2 : 1
}
}
Taf.JceInputStream.prototype.skipField = function (t) {
switch (t) {
case Taf.DataHelp.EN_INT8:
this.buf.position += 1
break
case Taf.DataHelp.EN_INT16:
this.buf.position += 2
break
case Taf.DataHelp.EN_INT32:
this.buf.position += 4
break
case Taf.DataHelp.EN_INT64:
this.buf.position += 8
break
case Taf.DataHelp.EN_STRING1:
var e = this.buf.readUInt8()
this.buf.position += e
break
case Taf.DataHelp.EN_STRING4:
var i = this.buf.readInt32()
this.buf.position += i
break
case Taf.DataHelp.EN_STRUCTBEGIN:
this.skipToStructEnd()
break
case Taf.DataHelp.EN_STRUCTEND:
case Taf.DataHelp.EN_ZERO:
break
case Taf.DataHelp.EN_MAP: {
var r = this.readInt32(0, true)
for (var n = 0; n < r * 2; ++n) {
var s = this.readFrom()
this.skipField(s.type)
}
break
}
case Taf.DataHelp.EN_SIMPLELIST: {
var s = this.readFrom()
if (s.type != Taf.DataHelp.EN_INT8) {
throw Error("skipField with invalid type, type value: " + t + "," + s.type)
}
var e = this.readInt32(0, true)
this.buf.position += e
break
}
case Taf.DataHelp.EN_LIST: {
var r = this.readInt32(0, true)
for (var n = 0; n < r; ++n) {
var s = this.readFrom()
this.skipField(s.type)
}
break
}
default:
throw new Error("skipField with invalid type, type value: " + t)
}
}
Taf.JceInputStream.prototype.skipToStructEnd = function () {
for (; ;) {
var t = this.readFrom()
this.skipField(t.type)
if (t.type == Taf.DataHelp.EN_STRUCTEND) {
return
}
}
}
Taf.JceInputStream.prototype.skipToTag = function (t, e) {
while (this.buf.position < this.buf.length) {
var i = this.peekFrom()
if (t <= i.tag || i.type == Taf.DataHelp.EN_STRUCTEND) {
return i.type == Taf.DataHelp.EN_STRUCTEND ? false : t == i.tag
}
this.buf.position += i.size
this.skipField(i.type)
}
if (e)
throw Error("require field not exist, tag:" + t)
return false
}
Taf.JceInputStream.prototype.readBoolean = function (t, e, i) {
return this.readInt8(t, e, i) == 1 ? true : false
}
Taf.JceInputStream.prototype.readInt8 = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
switch (r.type) {
case Taf.DataHelp.EN_ZERO:
return 0
case Taf.DataHelp.EN_INT8:
return this.buf.readInt8()
}
throw Error("read int8 type mismatch, tag:" + t + ", get type:" + r.type)
}
Taf.JceInputStream.prototype.readInt16 = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
switch (r.type) {
case Taf.DataHelp.EN_ZERO:
return 0
case Taf.DataHelp.EN_INT8:
return this.buf.readInt8()
case Taf.DataHelp.EN_INT16:
return this.buf.readInt16()
}
throw Error("read int8 type mismatch, tag:" + t + ", get type:" + r.type)
}
Taf.JceInputStream.prototype.readInt32 = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
switch (r.type) {
case Taf.DataHelp.EN_ZERO:
return 0
case Taf.DataHelp.EN_INT8:
return this.buf.readInt8()
case Taf.DataHelp.EN_INT16:
return this.buf.readInt16()
case Taf.DataHelp.EN_INT32:
return this.buf.readInt32()
}
throw Error("read int8 type mismatch, tag:" + t + ", get type:" + r.type)
}
Taf.JceInputStream.prototype.readInt64 = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
switch (r.type) {
case Taf.DataHelp.EN_ZERO:
return 0
case Taf.DataHelp.EN_INT8:
return this.buf.readInt8()
case Taf.DataHelp.EN_INT16:
return this.buf.readInt16()
case Taf.DataHelp.EN_INT32:
return this.buf.readInt32()
case Taf.DataHelp.EN_INT64:
return this.buf.readInt64()
}
throw Error("read int64 type mismatch, tag:" + t + ", get type:" + h.type)
}
Taf.JceInputStream.prototype.readFloat = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
switch (r.type) {
case Taf.DataHelp.EN_ZERO:
return 0
case Taf.DataHelp.EN_FLOAT:
return this.buf.readFloat()
}
throw Error("read float type mismatch, tag:" + t + ", get type:" + h.type)
}
Taf.JceInputStream.prototype.readDouble = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
switch (r.type) {
case Taf.DataHelp.EN_ZERO:
return 0
case Taf.DataHelp.EN_DOUBLE:
return this.buf.readDouble()
}
throw Error("read double type mismatch, tag:" + t + ", get type:" + h.type)
}
Taf.JceInputStream.prototype.readUInt8 = function (t, e, i) {
return this.readInt16(t, e, i)
}
Taf.JceInputStream.prototype.readUInt16 = function (t, e, i) {
return this.readInt32(t, e, i)
}
Taf.JceInputStream.prototype.readUInt32 = function (t, e, i) {
return this.readInt64(t, e, i)
}
Taf.JceInputStream.prototype.readStruct = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
if (r.type != Taf.DataHelp.EN_STRUCTBEGIN) {
return
}
// i.readFrom(this)
// this.skipToStructEnd()
// return i
var new_instance = i.readFrom(this)
this.skipToStructEnd()
return new_instance
}
Taf.JceInputStream.prototype.readString = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
if (r.type == Taf.DataHelp.EN_STRING1) {
return this.buf.readString(this.buf.readUInt8())
}
if (r.type == Taf.DataHelp.EN_STRING4) {
return this.buf.readString(this.buf.readUInt32())
}
throw Error("read 'string' type mismatch, tag: " + t + ", get type: " + r.type + ".")
}
Taf.JceInputStream.prototype.readString2 = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
if (r.type == Taf.DataHelp.EN_STRING1) {
return this.buf.readBytes(this.buf.readUInt8())
}
if (r.type == Taf.DataHelp.EN_STRING4) {
return this.buf.readBytes(this.buf.readUInt32())
}
throw Error("read 'string' type mismatch, tag: " + t + ", get type: " + r.type + ".")
}
Taf.JceInputStream.prototype.readBytes = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
if (r.type == Taf.DataHelp.EN_SIMPLELIST) {
var n = this.readFrom()
if (n.type != Taf.DataHelp.EN_INT8) {
throw Error("type mismatch, tag:" + t + ",type:" + r.type + "," + n.type)
}
var s = this.readInt32(0, true)
if (s < 0) {
throw Error("invalid size, tag:" + t + ",type:" + r.type + "," + n.type)
}
return this.buf.readBytes(s)
}
if (r.type == Taf.DataHelp.EN_LIST) {
var s = this.readInt32(0, true)
return this.buf.readBytes(s)
}
throw Error("type mismatch, tag:" + t + ",type:" + r.type)
}
Taf.JceInputStream.prototype.readVector = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
if (r.type != Taf.DataHelp.EN_LIST) {
throw Error("read 'vector' type mismatch, tag: " + t + ", get type: " + r.type)
}
var n = this.readInt32(0, true)
if (n < 0) {
throw Error("invalid size, tag: " + t + ", type: " + r.type + ", size: " + n)
}
for (var s = 0; s < n; ++s) {
i.value.push(i.proto._read(this, 0, i.proto._clone()))
}
return i
}
Taf.JceInputStream.prototype.readMap = function (t, e, i) {
if (this.skipToTag(t, e) == false) {
return i
}
var r = this.readFrom()
if (r.type != Taf.DataHelp.EN_MAP) {
throw Error("read 'map' type mismatch, tag: " + t + ", get type: " + r.type)
}
var n = this.readInt32(0, true)
if (n < 0) {
throw Error("invalid map, tag: " + t + ", size: " + n)
}
for (var s = 0; s < n; s++) {
var a = i.kproto._read(this, 0, i.kproto._clone())
var o = i.vproto._read(this, 1, i.vproto._clone())
i.put(a, o)
}
return i
}
Taf.Wup = function () {
this.iVersion = 3
this.cPacketType = 0
this.iMessageType = 0
this.iRequestId = 0
this.sServantName = ""
this.sFuncName = ""
this.sBuffer = new Taf.BinBuffer
this.iTimeout = 0
this.context = new Taf.Map(new Taf.STRING, new Taf.STRING)
this.status = new Taf.Map(new Taf.STRING, new Taf.STRING)
this.data = new Taf.Map(new Taf.STRING, new Taf.Map(new Taf.STRING, new Taf.BinBuffer))
this.newdata = new Taf.Map(new Taf.STRING, new Taf.BinBuffer)
}
Taf.Wup.prototype.setVersion = function (t) {
this.iVersion = t
}
Taf.Wup.prototype.getVersion = function (t) {
return this.iVersion
}
Taf.Wup.prototype.setServant = function (t) {
this.sServantName = t
}
Taf.Wup.prototype.setFunc = function (t) {
this.sFuncName = t
}
Taf.Wup.prototype.setRequestId = function (t) {
this.iRequestId = t ? t : ++this.iRequestId
}
Taf.Wup.prototype.getRequestId = function () {
return this.iRequestId
}
Taf.Wup.prototype.setTimeOut = function (t) {
this.iTimeout = t
}
Taf.Wup.prototype.getTimeOut = function () {
return this.iTimeout
}
Taf.Wup.prototype.writeTo = function () {
var t = new Taf.JceOutputStream
t.writeInt16(1, this.iVersion)
t.writeInt8(2, this.cPacketType)
t.writeInt32(3, this.iMessageType)
t.writeInt32(4, this.iRequestId)
t.writeString(5, this.sServantName)
t.writeString(6, this.sFuncName)
t.writeBytes(7, this.sBuffer)
t.writeInt32(8, this.iTimeout)
t.writeMap(9, this.context)
t.writeMap(10, this.status)
return new Taf.BinBuffer(t.getBuffer())
}
Taf.Wup.prototype.encode = function () {
var t = new Taf.JceOutputStream
if (this.iVersion == 3) {
t.writeMap(0, this.newdata)
} else {
t.writeMap(0, this.data)
}
this.sBuffer = t.getBinBuffer()
var e = new Taf.BinBuffer
e = this.writeTo()
var i = new Taf.BinBuffer
i.writeInt32(4 + e.len)
i.writeBytes(e)
return i
}
Taf.Wup.prototype.writeBoolean = function (t, e) {
var i = new Taf.JceOutputStream
i.writeBoolean(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = TAF.TypeHelp.BOOLEAN
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Taf.BinBuffer(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeInt8 = function (t, e) {
var i = new Taf.JceOutputStream
i.writeInt8(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = TAF.TypeHelp.CHAR
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Taf.BinBuffer(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeInt16 = function (t, e) {
var i = new Taf.JceOutputStream
i.writeInt16(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = TAF.TypeHelp.SHORT
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeInt32 = function (t, e) {
var i = new Taf.JceOutputStream
i.writeInt32(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = TAF.TypeHelp.INT32
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeInt64 = function (t, e) {
var i = new Taf.JceOutputStream
i.writeInt64(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = TAF.TypeHelp.INT64
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeFloat = function (t, e) {
var i = new Taf.JceOutputStream
i.writeFloat(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = TAF.TypeHelp.FLOAT
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeDouble = function (t, e) {
var i = new Taf.JceOutputStream
i.writeDouble(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = TAF.TypeHelp.DOUBLE
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeString = function (t, e) {
var i = new Taf.JceOutputStream
i.writeString(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = Taf.TypeHelp.STRING
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeVector = function (t, e) {
var i = new Taf.JceOutputStream
i.writeVector(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBinBuffer()))
} else {
var r = this.data.get(t)
var n = e._className()
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeStruct = function (t, e) {
var i = new Taf.JceOutputStream
i.writeStruct(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = " "
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeBytes = function (t, e) {
var i = new Taf.JceOutputStream
i.writeBytes(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = "vec"
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.writeMap = function (t, e) {
var i = new Taf.JceOutputStream
i.writeMap(0, e)
if (this.iVersion == 3) {
this.newdata.put(t, new Taf.BinBuffer(i.getBuffer()))
} else {
var r = this.data.get(t)
var n = Taf.Util.getClassType(e)
if (r == undefined) {
var s = new Taf.Map(Taf.STRING, Taf.STRING)
r = s
}
r.put(n, new Uint8Array(i.getBuffer()))
this.data.put(t, r)
}
}
Taf.Wup.prototype.readFrom = function (t) {
this.iVersion = t.readInt16(1, true)
this.cPacketType = t.readInt8(2, true)
this.iMessageType = t.readInt32(3, true)
this.iRequestId = t.readInt32(4, true)
this.sServantName = t.readString(5, true)
this.sFuncName = t.readString(6, true)
if (localStorage.__wup) {
console.info("%c@@@ " + this.sServantName + "." + this.sFuncName, "color:whitebackground:black;", this)
}
this.sBuffer = t.readBytes(7, true)
this.iTimeout = t.readInt32(8, true)
this.context = t.readMap(9, true)
this.status = t.readMap(10, true)
}
Taf.Wup.prototype.decode = function (t) {
var e = new Taf.JceInputStream(t)
var i = e.buf.vew.getInt32(e.buf.position)
if (i < 4) {
throw Error("packet length too short")
}
e.buf.position += 4
this.readFrom(e)
e = new Taf.JceInputStream(this.sBuffer.getBuffer())
if (this.iVersion == 3) {
this.newdata.clear()
e.readMap(0, true, this.newdata)
} else {
this.data.clear()
e.readMap(0, true, this.newdata)
}
}
Taf.Wup.prototype.readBoolean = function (t) {
var e, i
if (this.iVersion == 3) {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var r = new Taf.JceInputStream(e.buffer)
i = r.readBoolean(0, true, i)
} else {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = Taf.TypeHelp.BOOLEAN
var s = e.get(n)
if (s == undefined) {
throw Error("UniAttribute not found type:" + n)
}
var r = new Taf.JceInputStream(s)
i = r.readBoolean(0, true, i)
}
return i
}
Taf.Wup.prototype.readInt8 = function (t) {
var e, i
if (this.iVersion == 3) {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var r = new Taf.JceInputStream(e.buffer)
i = r.readInt8(0, true, i)
} else {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = Taf.TypeHelp.CHAR
var s = e.get(n)
if (s == undefined) {
throw Error("UniAttribute not found type:" + n)
}
var r = new Taf.JceInputStream(s)
i = r.readInt8(0, true, i)
}
return i
}
Taf.Wup.prototype.readInt16 = function (t) {
var e, i
if (this.iVersion == 3) {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var r = new Taf.JceInputStream(e.buffer)
i = r.readInt16(0, true, i)
} else {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = Taf.TypeHelp.SHORT
var s = e.get(n)
var r = new Taf.JceInputStream(s)
if (s == undefined) {
throw Error("UniAttribute not found type:" + n)
}
i = r.readInt16(0, true, i)
}
return i
}
Taf.Wup.prototype.readInt32 = function (t) {
var e, i
if (this.iVersion == 3) {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var r = new Taf.JceInputStream(e.buffer)
i = r.readInt32(0, true, i)
} else {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = Taf.TypeHelp.INT32
var s = e.get(n)
if (s == undefined) {
throw Error("UniAttribute not found type:" + n)
}
var r = new Taf.JceInputStream(s)
i = r.readInt32(0, true, i)
}
return i
}
Taf.Wup.prototype.readInt64 = function (t) {
var e, i
if (this.iVersion == 3) {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var r = new Taf.JceInputStream(e.buffer)
i = r.readInt64(0, true, i)
} else {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = Taf.TypeHelp.INT64
var s = e.get(n)
if (s == undefined) {
throw Error("UniAttribute not found type:" + n)
}
var r = new Taf.JceInputStream(s)
i = r.readInt64(0, true, i)
}
return i
}
Taf.Wup.prototype.readFloat = function (t) {
var e, i
if (this.iVersion == 3) {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var r = new Taf.JceInputStream(e.buffer)
i = r.readFloat(0, true, i)
} else {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = Taf.TypeHelp.FLOAT
var s = e.get(n)
if (s == undefined) {
throw Error("UniAttribute not found type:" + n)
}
var r = new Taf.JceInputStream(s)
i = r.readFloat(0, true, i)
}
return i
}
Taf.Wup.prototype.readDouble = function (t) {
let def;
var e
if (this.iVersion == 3) {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var i = new Taf.JceInputStream(e.buffer)
def = i.readDouble(0, true, def)
} else {
e = this.newdata.get(t)
if (e == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var r = Taf.TypeHelp.DOUBLE
var n = e.get(r)
if (n == undefined) {
throw Error("UniAttribute not found type:" + r)
}
var i = new Taf.JceInputStream(n)
def = i.readDouble(0, true, def)
}
return def
}
Taf.Wup.prototype.readVector = function (t, e, i) {
var r
if (this.iVersion == 3) {
r = this.newdata.get(t)
if (r == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = new Taf.JceInputStream(r.buffer)
e = n.readVector(0, true, e)
} else {
r = this.newdata.get(t)
if (r == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var s = r.get(i)
if (s == undefined) {
throw Error("UniAttribute not found type:" + i)
}
var n = new Taf.JceInputStream(s)
e = n.readVector(0, true, e)
}
return e
}
Taf.Wup.prototype.readStruct = function (t, e, i) {
var r
if (this.iVersion == 3) {
r = this.newdata.get(t)
if (r == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = new Taf.JceInputStream(r.buffer)
e = n.readStruct(0, true, e)
} else {
r = this.newdata.get(t)
if (r == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var s = r.get(i)
if (s == undefined) {
throw Error("UniAttribute not found type:" + i)
}
var n = new Taf.JceInputStream(s)
e = n.readStruct(0, true, e)
}
return e
}
Taf.Wup.prototype.readMap = function (t, e, i) {
var r
if (this.iVersion == 3) {
r = this.newdata.get(t)
if (r == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = new Taf.JceInputStream(r.buffer)
e = n.readMap(0, true, e)
} else {
r = this.newdata.get(t)
if (r == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var s = r.get(i)
if (s == undefined) {
throw Error("UniAttribute not found type:" + i)
}
var n = new Taf.JceInputStream(s)
e = n.readMap(0, true, e)
}
return e
}
Taf.Wup.prototype.readBytes = function (t, e, i) {
var r
if (this.iVersion == 3) {
r = this.newdata.get(t)
if (r == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var n = new Taf.JceInputStream(r.buffer)
e = n.readBytes(0, true, e)
} else {
r = this.newdata.get(t)
if (r == undefined) {
throw Error("UniAttribute not found key:" + t)
}
var s = r.get(i)
if (s == undefined) {
throw Error("UniAttribute not found type:" + i)
}
var n = new Taf.JceInputStream(s)
e = n.readBytes(0, true, e)
}
return e
}
Taf.Util = Taf.Util || {}
Taf.Util.jcestream = function (t, e) {
if (t == null || t == undefined) {
console.log("Taf.Util.jcestream::value is null or undefined")
return
}
if (!(t instanceof ArrayBuffer)) {
console.log("Taf.Util.jcestream::value is not ArrayBuffer")
return
}
e = e || 16
var i = new Uint8Array(t)
var r = ""
for (var n = 0; n < i.length; n++) {
if (n != 0 && n % e == 0) {
r += "n"
} else if (n != 0) {
r += " "
}
r += (i[n] > 15 ? "" : "0") + i[n].toString(16)
}
console.log(r.toUpperCase())
}
Taf.Util.str2ab = function (t) {
var e, i = t.length, r = new Array(i)
for (e = 0; e < i; ++e) {
r[e] = t.charCodeAt(e)
}
return new Uint8Array(r).buffer
}
Taf.Util.ajax = function (t, e, i, r) {
var n = new XMLHttpRequest
n.overrideMimeType("text/plain charset=x-user-defined");
var s = function () {
if (n.readyState === 4) {
if (n.status === 200 || n.status === 304) {
i(Taf.Util.str2ab(n.response))
} else {
r(n.status)
}
n.removeEventListener("readystatechange", s)
n = undefined
}
}
n.addEventListener("readystatechange", s)
n.open("post", t)
n.send(e)
}
ab2hex = function (buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
}
function hex2ab(value) {
var typedArray = new Uint8Array(value.match(/[da-f]{2}/gi).map(function (h) {
return parseInt(h, 16);
}))
return typedArray.buffer;
}
//组包方式的实现
function main() {
var s = {};
//定义 HomepageFeedsIconLabel1结构
s.HomepageFeedsIconLabel1 = function () {
this.sText = "ddd", this.iColor = 123456, this.usIconId = 0, this._classname = "MTT.HomepageFeedsIconLabel"
}
s.HomepageFeedsIconLabel1._classname = "MTT.HomepageFeedsIconLabel1"
s.HomepageFeedsIconLabel1.write = function (e, t, i) {
e.writeStruct(t, i)
}
s.HomepageFeedsIconLabel1.read = function (e, t, i) {
return e.readStruct(t, !0, i)
}
s.HomepageFeedsIconLabel1.readFrom = function (e) {
var t = new s.HomepageFeedsIconLabel1;
t.sText = e.readString(0, !0, "");
t.iColor = e.readInt32(1, !0, 1);
t.usIconId = e.readUInt16(2, !1, 0);
return t
}
s.HomepageFeedsIconLabel1.prototype.writeTo = function (e) {
e.writeString(0, this.sText), e.writeInt32(1, this.iColor), e.writeUInt16(2, this.usIconId)
}
//定义 HomepageFeedsIconLabel1结构
s.HomepageFeedsIconLabel = function () {
this.sText = "ddd", this.iColor = 123456, this.usIconId = 0, this._classname = "MTT.HomepageFeedsIconLabel", this.demo = new s.HomepageFeedsIconLabel1()
}
s.HomepageFeedsIconLabel._classname = "MTT.HomepageFeedsIconLabel"
s.HomepageFeedsIconLabel.write = function (e, t, i) {
e.writeStruct(t, i)
}
s.HomepageFeedsIconLabel.read = function (e, t, i) {
return e.readStruct(t, !0, i)
}
s.HomepageFeedsIconLabel.readFrom = function (e) {
var t = new s.HomepageFeedsIconLabel;
t.sText = e.readString(0, !0, "");
t.iColor = e.readInt32(1, !0, 1);
t.usIconId = e.readUInt16(2, !1, 0);
t.stIcon = e.readStruct(3, !1, s.HomepageFeedsIconLabel1);
return t
}
s.HomepageFeedsIconLabel.prototype.writeTo = function (e) {
e.writeString(0, this.sText), e.writeInt32(1, this.iColor), e.writeUInt16(2, this.usIconId), e.writeStruct(3, this.demo);
}
//定义HomepageBookInfo结构
s.HomepageBookInfo = function () {
this.sPicUrl = "aaaaa", this.stIcon = new s.HomepageFeedsIconLabel, this._classname = "MTT.HomepageBookInfo"
}, s.HomepageBookInfo._classname = "MTT.HomepageBookInfo", s.HomepageBookInfo._write = function (e, t, i) {
e.writeStruct(t, i)
}, s.HomepageBookInfo.read = function (e, t, i) {
return e.readStruct(t, !0, i)
}, s.HomepageBookInfo.readFrom = function (e) {
var t = new s.HomepageBookInfo;
t.sPicUrl = e.readString(0, !1, "");
t.stIcon = e.readStruct(5, !1, s.HomepageFeedsIconLabel);
return t
}, s.HomepageBookInfo.prototype.writeTo = function (e) {
e.writeString(0, this.sPicUrl);
e.writeStruct(5, this.stIcon);
}
//得到jce的二进制数据
const jceOutputStream1 = new Taf.JceOutputStream;
var c = new s.HomepageBookInfo
c.writeTo(jceOutputStream1);
console.log(jceOutputStream1.getBuffer());
//将jce的二进制数据解析位结构
const jce = new Taf.JceInputStream(jceOutputStream1.getBuffer())
t = s.HomepageBookInfo.readFrom(jce);
console.log(JSON.stringify(t));
return ab2hex(jceOutputStream1.getBuffer());
}
main()
代码很长,感谢你坚持到了这里。
如果你喜欢逆向和二进制分析请关注我
如果你喜欢js逆向和爬虫请关注我朋友
我是BestToYou,分享工作或日常学习中关于二进制逆向和分析的一些思路和一些自己闲暇时刻调试的一些程序,文中若有错误的地方,恳请大家联系我批评指正。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论