魔数前增加恶意头检测

This commit is contained in:
lushunming 2025-12-08 09:58:45 +08:00
parent ed88ad03cf
commit 3540ecc3aa
1 changed files with 64 additions and 1 deletions

View File

@ -143,7 +143,13 @@ object ProxyServer {
producerJob += CoroutineScope(Dispatchers.IO).launch {
// 异步下载数据块
val data = getVideoStream(chunkStart, chunkEnd, url, headers)
channels[i].send(data)
//如果是0开始且检测到恶意头那么就把数据截断
if (chunkStart == 0L) {
val offset = detectMaliciousPrefix(data)
channels[i].send(data.copyOfRange(offset, data.size))
} else {
channels[i].send(data)
}
}
currentStart = chunkEnd + 1
@ -169,7 +175,64 @@ object ProxyServer {
}
}
fun detectMaliciousPrefix(data: ByteArray): Int {
val buffer = ByteArray(64) // 读取前64字节足够
ByteArrayInputStream(data).use { fis ->
fis.read(buffer)
}
// 检查是否以合法魔数开头
if (isValidVideoHeader(buffer)) {
return 0 // 正常,无恶意前缀
}
// 在后续位置查找合法魔数比如最多跳过前256字节
val searchLimit = minOf(256, data.size)
val searchBuffer = ByteArray(searchLimit)
ByteArrayInputStream(data).use { fis ->
fis.read(searchBuffer)
}
// 尝试从偏移1开始查找合法视频头
for (offset in 1 until searchLimit - 16) {
if (isValidVideoHeader(searchBuffer, offset)) {
SpiderDebug.log("发现合法视频头位于偏移 $offset,疑似被插入恶意前缀!")
return offset
}
}
return 0 // 未找到合法头,可能是损坏或非视频文件
}
// 判断从指定偏移开始是否是合法视频头
fun isValidVideoHeader(data: ByteArray, offset: Int = 0): Boolean {
if (data.size - offset < 8) return false
// MP4 / MOV: ... ftyp
if (offset + 8 <= data.size && data[offset + 4].toInt() == 0x66 && // 'f'
data[offset + 5].toInt() == 0x74 && // 't'
data[offset + 6].toInt() == 0x79 && // 'y'
data[offset + 7].toInt() == 0x70 // 'p'
) {
// 还可进一步校验前4字节是否为合法 size>=8 且合理)
val size =
(data[offset].toLong() and 0xFF shl 24) or (data[offset + 1].toLong() and 0xFF shl 16) or (data[offset + 2].toLong() and 0xFF shl 8) or (data[offset + 3].toLong() and 0xFF)
if (size >= 8 && size <= 0x100000) return true
}
// AVI: RIFF
if (offset + 4 <= data.size && data[offset] == 0x52.toByte() && data[offset + 1] == 0x49.toByte() && data[offset + 2] == 0x46.toByte() && data[offset + 3] == 0x46.toByte()) return true
// MKV
if (offset + 4 <= data.size && data[offset] == 0x1A.toByte() && data[offset + 1] == 0x45.toByte() && data[offset + 2] == 0xDF.toByte() && data[offset + 3] == 0xA3.toByte()) return true
// FLV
if (offset + 4 <= data.size && data[offset] == 0x46.toByte() && data[offset + 1] == 0x4C.toByte() && data[offset + 2] == 0x56.toByte() && data[offset + 3] == 0x01.toByte()) return true
return false
}
private fun queryToMap(query: String?): Map<String, String>? {
if (query == null) {
return null