122 lines
3.2 KiB
Kotlin
122 lines
3.2 KiB
Kotlin
package burp
|
|
|
|
import com.ensarsarajcic.kotlinx.serialization.msgpack.MsgPack
|
|
import kotlinx.serialization.ExperimentalSerializationApi
|
|
import kotlinx.serialization.json.Json
|
|
import kotlinx.serialization.serializer
|
|
|
|
var buffer = byteArrayOf()
|
|
|
|
@OptIn(ExperimentalSerializationApi::class)
|
|
val JSON = Json {
|
|
allowStructuredMapKeys = true
|
|
prettyPrint = true
|
|
prettyPrintIndent = " "
|
|
}
|
|
|
|
enum class MessageType {
|
|
Null, Invocation, StreamItem, Completion, StreamInvocation, CancelInvocation, Ping, Close
|
|
}
|
|
|
|
interface Message {
|
|
val raw: String
|
|
}
|
|
|
|
data class InvocationMessage(
|
|
val identifier: String?,
|
|
val method: String,
|
|
val arguments: List<String>,
|
|
val result: List<String>?,
|
|
override val raw: String
|
|
) : Message
|
|
|
|
data class CompletionMessage(
|
|
val identifier: String?, val num: Int, val extra: List<Any>, override val raw: String
|
|
) : Message
|
|
|
|
data class PingMessage(
|
|
val extra: List<Any>?, override val raw: String
|
|
) : Message
|
|
|
|
data class UnknownMessage(
|
|
val type: MessageType, val extra: List<Any>?, override val raw: String
|
|
) : Message
|
|
|
|
fun listToMessage(data: ArrayList<Any>, raw: String): Message {
|
|
return when (val type = MessageType.values()[(data[0] as Byte).toInt()]) {
|
|
MessageType.Invocation -> {
|
|
InvocationMessage(
|
|
identifier = data[2] as String?,
|
|
method = data[3] as String,
|
|
arguments = data[4] as List<String>,
|
|
result = if (data.size > 5) data[5] as List<String> else (null),
|
|
raw = raw
|
|
)
|
|
}
|
|
|
|
MessageType.Completion -> {
|
|
CompletionMessage(
|
|
identifier = data[2] as String?,
|
|
num = (data[3] as Byte).toInt(),
|
|
extra = data.slice(4 until data.size),
|
|
raw = raw
|
|
)
|
|
}
|
|
|
|
MessageType.Ping -> {
|
|
PingMessage(
|
|
extra = data.slice(1 until data.size), raw = raw
|
|
)
|
|
}
|
|
|
|
else -> {
|
|
UnknownMessage(
|
|
type = type, extra = data.slice(1 until data.size), raw = raw
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun decode(data: ByteArray): List<Message> {
|
|
var idx = 0
|
|
val messages = mutableListOf<Message>()
|
|
while (idx < data.size) {
|
|
var msgSize = 0
|
|
var shift = 0
|
|
|
|
while (true) {
|
|
val size = data[idx].toUByte().toInt()
|
|
idx++
|
|
|
|
msgSize += (size and 0x7F) shl shift
|
|
shift += 7
|
|
|
|
if (size < 0x80) {
|
|
break
|
|
}
|
|
}
|
|
|
|
val message = MsgPack.decodeFromByteArray(MsgPackSerializer, data.sliceArray(idx until idx + msgSize))
|
|
messages.add(listToMessage(message as ArrayList<Any>, JSON.encodeToString(MsgPackSerializer, message)))
|
|
idx += msgSize
|
|
}
|
|
|
|
return messages
|
|
}
|
|
|
|
fun encodeSize(packed: ByteArray): ByteArray {
|
|
var encodedSize = ByteArray(0)
|
|
var sz = packed.size
|
|
while (sz > 0) {
|
|
val s = sz and 0x7f
|
|
sz = sz shr 7
|
|
encodedSize += (if (sz > 0) s or 0x80 else s).toByte()
|
|
}
|
|
return encodedSize
|
|
}
|
|
|
|
fun encodeJson(input: String): ByteArray {
|
|
val packed = MsgPack.encodeToByteArray(Json.serializersModule.serializer(), input)
|
|
val size = encodeSize(packed)
|
|
return size + packed
|
|
} |