Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
Mirai
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
Mirai
Commits
368abbe1
Commit
368abbe1
authored
Nov 11, 2019
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add unknown statuses
parent
62088295
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
145 additions
and
95 deletions
+145
-95
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/OnlineStatus.kt
...c/commonMain/kotlin/net.mamoe.mirai/utils/OnlineStatus.kt
+9
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/TEA.kt
...i-core/src/commonMain/kotlin/net.mamoe.mirai/utils/TEA.kt
+3
-0
mirai-debug/src/main/kotlin/PacketDebuger.kt
mirai-debug/src/main/kotlin/PacketDebuger.kt
+133
-91
No files found.
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/OnlineStatus.kt
View file @
368abbe1
...
@@ -26,13 +26,18 @@ enum class OnlineStatus(
...
@@ -26,13 +26,18 @@ enum class OnlineStatus(
*/
*/
OFFLINE
(
0
x02u
),
OFFLINE
(
0
x02u
),
/**
UNKNOWN1
(
0
x20u
),
* ?
UNKNOWN2
(
0
x46u
),
*/
UNKNOWN3
(
0
x14u
),
UNKNOWN
(
0
x20u
)
UNKNOWN4
(
0
xC9u
),
UNKNOWN5
(
0
x1Eu
),
;
;
// TODO: 2019/10/29 what is 0x20u
// TODO: 2019/10/29 what is 0x20u
// TODO: 2019/11/11 what is 0x46u
// TODO: 2019/11/11 what is 0x14u
// TODO: 2019/11/11 0xC9u
// TODO: 2019/11/11 0x1Eu
companion
object
{
companion
object
{
fun
ofId
(
id
:
UByte
):
OnlineStatus
?
=
values
().
firstOrNull
{
it
.
id
==
id
}
fun
ofId
(
id
:
UByte
):
OnlineStatus
?
=
values
().
firstOrNull
{
it
.
id
==
id
}
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/TEA.kt
View file @
368abbe1
...
@@ -3,6 +3,7 @@ package net.mamoe.mirai.utils
...
@@ -3,6 +3,7 @@ package net.mamoe.mirai.utils
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.pool.useInstance
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.network.protocol.tim.packet.Decrypter
import
net.mamoe.mirai.network.protocol.tim.packet.DecrypterByteArray
import
net.mamoe.mirai.network.protocol.tim.packet.DecrypterByteArray
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.utils.io.*
import
kotlin.experimental.and
import
kotlin.experimental.and
...
@@ -123,6 +124,8 @@ fun ByteReadPacket.decryptBy(key: ByteArray): ByteReadPacket = decryptAsByteArra
...
@@ -123,6 +124,8 @@ fun ByteReadPacket.decryptBy(key: ByteArray): ByteReadPacket = decryptAsByteArra
fun
ByteReadPacket
.
decryptBy
(
key
:
IoBuffer
):
ByteReadPacket
=
decryptAsByteArray
(
key
)
{
data
->
ByteReadPacket
(
data
,
0
)
}
fun
ByteReadPacket
.
decryptBy
(
key
:
IoBuffer
):
ByteReadPacket
=
decryptAsByteArray
(
key
)
{
data
->
ByteReadPacket
(
data
,
0
)
}
fun
ByteReadPacket
.
decryptBy
(
key
:
Decrypter
):
ByteReadPacket
=
key
.
decrypt
(
this
)
fun
ByteReadPacket
.
decryptBy
(
keyHex
:
String
):
ByteReadPacket
=
decryptBy
(
keyHex
.
hexToBytes
())
fun
ByteReadPacket
.
decryptBy
(
keyHex
:
String
):
ByteReadPacket
=
decryptBy
(
keyHex
.
hexToBytes
())
inline
fun
<
R
>
ByteReadPacket
.
decryptAsByteArray
(
key
:
ByteArray
,
consumer
:
(
ByteArray
)
->
R
):
R
=
inline
fun
<
R
>
ByteReadPacket
.
decryptAsByteArray
(
key
:
ByteArray
,
consumer
:
(
ByteArray
)
->
R
):
R
=
...
...
mirai-debug/src/main/kotlin/PacketDebuger.kt
View file @
368abbe1
...
@@ -4,15 +4,13 @@ import PacketDebugger.dataSent
...
@@ -4,15 +4,13 @@ import PacketDebugger.dataSent
import
PacketDebugger.localIp
import
PacketDebugger.localIp
import
PacketDebugger.qq
import
PacketDebugger.qq
import
PacketDebugger.sessionKey
import
PacketDebugger.sessionKey
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.*
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.*
import
kotlinx.io.core.readBytes
import
kotlinx.io.core.readUInt
import
kotlinx.io.core.readUShort
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.message.internal.readMessageChain
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.handler.ActionPacketHandler
import
net.mamoe.mirai.network.protocol.tim.handler.DataPacketSocketAdapter
import
net.mamoe.mirai.network.protocol.tim.handler.DataPacketSocketAdapter
import
net.mamoe.mirai.network.protocol.tim.handler.PacketHandler
import
net.mamoe.mirai.network.protocol.tim.handler.PacketHandler
import
net.mamoe.mirai.network.protocol.tim.handler.TemporaryPacketHandler
import
net.mamoe.mirai.network.protocol.tim.handler.TemporaryPacketHandler
...
@@ -29,10 +27,13 @@ import net.mamoe.mirai.utils.decryptBy
...
@@ -29,10 +27,13 @@ import net.mamoe.mirai.utils.decryptBy
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.utils.io.*
import
org.pcap4j.core.BpfProgram.BpfCompileMode
import
org.pcap4j.core.BpfProgram.BpfCompileMode
import
org.pcap4j.core.PacketListener
import
org.pcap4j.core.PacketListener
import
org.pcap4j.core.PcapNetworkInterface
import
org.pcap4j.core.PcapNetworkInterface.PromiscuousMode
import
org.pcap4j.core.PcapNetworkInterface.PromiscuousMode
import
org.pcap4j.core.Pcaps
import
org.pcap4j.core.Pcaps
import
java.util.concurrent.Executors
import
kotlin.concurrent.thread
import
kotlin.concurrent.thread
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
import
kotlin.io.use
/**
/**
* 需使用 32 位 JDK
* 需使用 32 位 JDK
...
@@ -47,39 +48,58 @@ fun main() {
...
@@ -47,39 +48,58 @@ fun main() {
JpcapCaptor.openDevice(JpcapCaptor.getDeviceList()[0], 65535, true, 1000).loopPacket(Int.MAX_VALUE) {
JpcapCaptor.openDevice(JpcapCaptor.getDeviceList()[0], 65535, true, 1000).loopPacket(Int.MAX_VALUE) {
println(it)
println(it)
}*/
}*/
Pcaps
.
findAllDevs
().
forEach
{
listenDevice
()
listenDevice
(
it
)
}
}
}
private
fun
listenDevice
()
{
/**
* 避免 print 重叠. 单线程处理足够调试
*/
val
DISPATCHER
=
Executors
.
newFixedThreadPool
(
1
).
asCoroutineDispatcher
()
private
fun
listenDevice
(
device
:
PcapNetworkInterface
)
{
val
sender
=
device
.
openLive
(
65536
,
PromiscuousMode
.
PROMISCUOUS
,
10
)
thread
{
thread
{
val
sender
=
Pcaps
.
findAllDevs
().
first
{
it
.
addresses
.
any
{
it
.
address
.
hostAddress
==
localIp
}
}.
openLive
(
65536
,
PromiscuousMode
.
PROMISCUOUS
,
10
)
sender
.
setFilter
(
"src $localIp && udp port 8000"
,
BpfCompileMode
.
OPTIMIZE
)
sender
.
setFilter
(
"src $localIp && udp port 8000"
,
BpfCompileMode
.
OPTIMIZE
)
println
(
"sendListener started"
)
println
(
"sendListener started"
)
try
{
try
{
sender
.
loop
(
999999
,
PacketListener
{
sender
.
loop
(
Int
.
MAX_VALUE
,
PacketListener
{
try
{
runBlocking
{
dataSent
(
it
.
rawData
.
drop
(
42
).
toByteArray
())
withContext
(
DISPATCHER
)
{
}
catch
(
e
:
Throwable
)
{
try
{
e
.
printStackTrace
()
dataSent
(
it
.
rawData
.
drop
(
42
).
toByteArray
())
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
}
}
}
}
})
})
}
catch
(
e
:
Exception
)
{
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
e
.
printStackTrace
()
}
}
}
}
/*
val
receiver
=
device
.
openLive
(
65536
,
PromiscuousMode
.
PROMISCUOUS
,
10
)
thread
{
thread
{
val receiver = Pcaps.findAllDevs().first { it.addresses.any { it.address.hostAddress == localIp } }.openLive(65536, PromiscuousMode.PROMISCUOUS, 10)
receiver
.
setFilter
(
"dst $localIp && udp port 8000"
,
BpfCompileMode
.
OPTIMIZE
)
receiver
.
setFilter
(
"dst $localIp && udp port 8000"
,
BpfCompileMode
.
OPTIMIZE
)
println
(
"receiveListener started"
)
println
(
"receiveListener started"
)
receiver.loop(Int.MAX_VALUE, PacketListener {
try
{
runBlocking {
receiver
.
loop
(
Int
.
MAX_VALUE
,
PacketListener
{
dataReceived(it.rawData.drop(42).toByteArray())
runBlocking
{
}
withContext
(
DISPATCHER
)
{
})
try
{
}*/
PacketDebugger
.
dataReceived
(
it
.
rawData
.
drop
(
42
).
toByteArray
())
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
}
}
}
})
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
}
}
}
}
/**
/**
...
@@ -103,9 +123,15 @@ object PacketDebugger {
...
@@ -103,9 +123,15 @@ object PacketDebugger {
* 7. 运行完 `mov eax,dword ptr ss:[ebp+10]`
* 7. 运行完 `mov eax,dword ptr ss:[ebp+10]`
* 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey`
* 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey`
*/
*/
val
sessionKey
:
ByteArray
=
"F9 37 23 8F E7 04 AF 52 6D B9 94 13 E1 3A BD 4A"
.
hexToBytes
(
)
val
sessionKey
:
SessionKey
=
SessionKey
(
"9B AA 9C 93 78 47 7B 6F C4 57 F2 13 76 AC C7 72"
.
hexToBytes
()
)
const
val
qq
:
UInt
=
1040400290
u
const
val
qq
:
UInt
=
1040400290
u
const
val
localIp
=
"192.168.3.10"
val
localIp
:
String
=
"10.162.12.231"
.
also
{
println
(
"Local IP: $it"
)
}
val
IgnoredPacketIdList
:
List
<
PacketId
>
=
listOf
(
KnownPacketId
.
FRIEND_ONLINE_STATUS_CHANGE
,
KnownPacketId
.
CHANGE_ONLINE_STATUS
,
KnownPacketId
.
HEARTBEAT
)
suspend
fun
dataReceived
(
data
:
ByteArray
)
{
suspend
fun
dataReceived
(
data
:
ByteArray
)
{
//println("raw = " + data.toUHexString())
//println("raw = " + data.toUHexString())
...
@@ -115,28 +141,34 @@ object PacketDebugger {
...
@@ -115,28 +141,34 @@ object PacketDebugger {
val
sequenceId
=
readUShort
()
val
sequenceId
=
readUShort
()
if
(
id
==
KnownPacketId
.
HEARTBEAT
||
readUInt
()
!=
qq
)
if
(
id
==
KnownPacketId
.
HEARTBEAT
||
readUInt
()
!=
qq
)
return
@
read
return
@
read
if
(
IgnoredPacketIdList
.
contains
(
id
))
{
return
}
println
(
"--------------"
)
println
(
"--------------"
)
println
(
"接收数据包"
)
discardExact
(
3
)
//0x00 0x00 0x00. 但更可能是应该 discard 8
discardExact
(
3
)
//0x00 0x00 0x00. 但更可能是应该 discard 8
println
(
"id=$id, sequence=${sequenceId.toUHexString()}"
)
println
(
val
remaining
=
this
.
readRemainingBytes
().
cutTail
(
1
)
"接收包id=$id, "
+
"\nsequence=${sequenceId.toUHexString()}"
)
// val remaining = this.readRemainingBytes().cutTail(1)
try
{
try
{
val
decrypted
=
remaining
.
decryptBy
(
sessionKey
)
println
(
"解密body=${decrypted.toUHexString()}"
)
val
packet
=
use
{
val
packet
=
use
{
with
(
id
.
factory
)
{
with
(
id
.
factory
)
{
provideDecrypter
(
id
.
factory
)
provideDecrypter
(
id
.
factory
)
.
decrypt
(
this
@
read
)
.
decrypt
(
this
@
read
.
readRemainingBytes
().
let
{
ByteReadPacket
(
it
,
0
,
it
.
size
-
1
)
}
)
.
decode
(
id
,
sequenceId
,
DebugNetworkHandler
)
.
decode
(
id
,
sequenceId
,
DebugNetworkHandler
)
}
}
}
}
println
(
" 解析body=$packet"
)
handlePacket
(
id
,
sequenceId
,
packet
,
id
.
factory
)
handlePacket
(
id
,
sequenceId
,
packet
,
id
.
factory
)
}
catch
(
e
:
DecryptionFailedException
)
{
}
catch
(
e
:
DecryptionFailedException
)
{
println
(
"密文body="
+
remaining
.
toUHexString
())
//
println("密文body=" + remaining.toUHexString())
println
(
"解密body=解密失败"
)
println
(
"
解密body=解密失败"
)
}
}
}
}
}
}
...
@@ -162,6 +194,7 @@ object PacketDebugger {
...
@@ -162,6 +194,7 @@ object PacketDebugger {
packet
:
TPacket
,
packet
:
TPacket
,
factory
:
PacketFactory
<
TPacket
,
*
>
factory
:
PacketFactory
<
TPacket
,
*
>
)
{
)
{
return
when
(
packet
)
{
when
(
packet
)
{
is
UnknownEventPacket
->
{
is
UnknownEventPacket
->
{
println
(
"--------------"
)
println
(
"--------------"
)
...
@@ -195,16 +228,21 @@ object PacketDebugger {
...
@@ -195,16 +228,21 @@ object PacketDebugger {
// 01 BD 63 D6
// 01 BD 63 D6
// 3E 03 3F A2 02 00 00 00 01 2E 01 00 00 69 35
// 3E 03 3F A2 02 00 00 00 01 2E 01 00 00 69 35
println
(
"---------------------------"
)
discardExact
(
3
)
//head
discardExact
(
3
)
//head
val
idHex
=
readBytes
(
4
).
toUHexString
()
val
id
=
matchPacketId
(
readUShort
())
println
(
"发出包ID = $idHex"
)
val
sequence
=
readUShort
()
if
(
IgnoredPacketIdList
.
contains
(
id
))
{
return
}
if
(
readUInt
()
!=
qq
)
{
if
(
readUInt
()
!=
qq
)
{
return
@
read
return
@
read
}
}
println
(
"---------------------------"
)
println
(
"发出包ID = $id"
)
println
(
"sequence = $sequence"
)
println
(
println
(
"fixVer2="
+
when
(
val
flag
=
readByte
().
toInt
())
{
"
fixVer2="
+
when
(
val
flag
=
readByte
().
toInt
())
{
2
->
byteArrayOf
(
2
)
+
readBytes
(
TIMProtocol
.
fixVer2
.
hexToBytes
().
size
-
1
)
2
->
byteArrayOf
(
2
)
+
readBytes
(
TIMProtocol
.
fixVer2
.
hexToBytes
().
size
-
1
)
4
->
byteArrayOf
(
4
)
+
readBytes
(
TIMProtocol
.
fixVer2
.
hexToBytes
().
size
-
1
+
8
)
//8个0
4
->
byteArrayOf
(
4
)
+
readBytes
(
TIMProtocol
.
fixVer2
.
hexToBytes
().
size
-
1
+
8
)
//8个0
0
->
byteArrayOf
(
0
)
+
readBytes
(
2
)
0
->
byteArrayOf
(
0
)
+
readBytes
(
2
)
...
@@ -216,78 +254,82 @@ object PacketDebugger {
...
@@ -216,78 +254,82 @@ object PacketDebugger {
val
encryptedBody
=
readRemainingBytes
()
val
encryptedBody
=
readRemainingBytes
()
try
{
try
{
println
(
"
解密body=${encryptedBody.decryptBy(sessionKey
).toUHexString()}"
)
println
(
"
解密body=${encryptedBody.decryptBy(sessionKey.value
).toUHexString()}"
)
}
catch
(
e
:
DecryptionFailedException
)
{
}
catch
(
e
:
DecryptionFailedException
)
{
println
(
"密文="
+
encryptedBody
.
toUHexString
())
println
(
"
密文="
+
encryptedBody
.
toUHexString
())
println
(
"解密body=解密失败"
)
println
(
"
解密body=解密失败"
)
}
}
encryptedBody
.
read
{
encryptedBody
.
read
{
when
(
idHex
.
substring
(
0
,
5
))
{
/*
"00 CD"
->
{
when (idHex.substring(0, 5)) {
println
(
"好友消息"
)
"00 CD" -> {
println("好友消息")
val
raw
=
readRemainingBytes
()
//println("解密前数据: " + raw.toUHexString())
val raw = readRemainingBytes()
val
messageData
=
raw
.
decryptBy
(
sessionKey
)
//println("解密前数据: " + raw.toUHexString())
//println("解密结果: " + messageData.toUHexString())
val messageData = raw.decryptBy(sessionKey.value)
println
(
"尝试解消息"
)
//println("解密结果: " + messageData.toUHexString())
println("尝试解消息")
try
{
messageData
.
read
{
try {
discardExact
(
messageData.read {
4
+
4
+
12
+
2
+
4
+
4
+
16
+
2
+
2
+
4
+
2
+
16
+
4
+
4
+
7
+
15
+
2
discardExact(
+
1
4 + 4 + 12 + 2 + 4 + 4 + 16 + 2 + 2 + 4 + 2 + 16 + 4 + 4 + 7 + 15 + 2
)
+ 1
val
chain
=
readMessageChain
()
)
println
(
chain
)
val chain = readMessageChain()
}
println(chain)
}
catch
(
e
:
Exception
)
{
}
println
(
"失败"
)
} catch (e: Exception) {
}
println("失败")
}
}
}*/
"03 88"
->
{
println
(
"0388上传图片-获取图片ID"
)
/*
discardExact
(
8
)
"03 88" -> {
println("0388上传图片-获取图片ID")
//val body = readRemainingBytes().decryptBy(sessionKey)
discardExact(8)
//println(body.toUHexString())
}
//val body = readRemainingBytes().decryptBy(sessionKey)
//println(body.toUHexString())
}
}
}*/
}
}
}
}
}
}
internal
object
DebugNetworkHandler
:
BotNetworkHandler
<
DataPacketSocketAdapter
>
{
internal
object
DebugNetworkHandler
:
BotNetworkHandler
<
DataPacketSocketAdapter
>,
CoroutineScope
{
override
val
socket
:
DataPacketSocketAdapter
override
val
socket
:
DataPacketSocketAdapter
=
object
:
DataPacketSocketAdapter
{
get
()
=
object
:
DataPacketSocketAdapter
{
override
val
serverIp
:
String
override
val
serverIp
:
String
get
()
=
""
get
()
=
""
override
val
channel
:
PlatformDatagramChannel
override
val
channel
:
PlatformDatagramChannel
get
()
=
error
(
"UNSUPPORTED"
)
get
()
=
error
(
"UNSUPPORTED"
)
override
val
isOpen
:
Boolean
override
val
isOpen
:
Boolean
get
()
=
true
get
()
=
true
override
suspend
fun
sendPacket
(
packet
:
OutgoingPacket
)
{
override
suspend
fun
sendPacket
(
packet
:
OutgoingPacket
)
{
}
}
override
fun
close
()
{
override
fun
close
()
{
}
}
override
val
owner
:
Bot
override
val
owner
:
Bot
get
()
=
bot
get
()
=
bot
}
}
override
val
bot
:
Bot
=
Bot
(
0
u
,
""
)
override
val
bot
:
Bot
=
Bot
(
0
u
,
""
)
val
session
=
BotSession
(
bot
,
sessionKey
,
socket
,
this
)
val
action
=
ActionPacketHandler
(
session
)
override
fun
<
T
:
PacketHandler
>
get
(
key
:
PacketHandler
.
Key
<
T
>):
T
=
error
(
"UNSUPPORTED"
)
@Suppress
(
"UNCHECKED_CAST"
)
override
fun
<
T
:
PacketHandler
>
get
(
key
:
PacketHandler
.
Key
<
T
>):
T
=
action
as
?
T
?:
error
(
"UNSUPPORTED"
)
override
suspend
fun
login
(
configuration
:
BotConfiguration
):
LoginResult
=
error
(
"UNSUPPORTED"
)
override
suspend
fun
login
(
configuration
:
BotConfiguration
):
LoginResult
=
LoginResult
.
SUCCESS
override
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
,
*
>)
{
override
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
,
*
>)
{
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment