针对Besder网络摄像头的逆向分析和漏洞挖掘
来源:岁月联盟
时间:2020-01-29
4 = 0x00000005
5 = 0x00000006
6 = 0x00000007
7 = 0x00000008
8 = 0x00000009
[Done] exited with code=0 in 1.025 seconds
由于SessionID就像一个简单的增量器,因此我可以轻松地编写自己的值。了解摄像头如何产生其SessionID字段。
让我尝试登录后发送另一个命令,我首先将尝试重播命令SessionID,然后尝试使用随机的SessionID重播命令。这将使我对有效的方法和无效的方法有更深入的了解。
对于此命令,我将使用SystemInfo,客户端使用它来获得一些设置和版本号的列表。但SessionID字段中的播放显示摄像头并不使用它。我尝试了0x00000007、0x11111117和其他几个随机数,它们似乎都可以工作!
Success!
{
"Name" : "SystemInfo",
"Ret" : 100,
"SessionID" : "0x11111117",
"SystemInfo" : {
"AlarmInChannel" : 1,
"AlarmOutChannel" : 1,
"AudioInChannel" : 1,
"BuildTime" : "2018-08-29 09:00:36",
"CombineSwitch" : 0,
"DeviceModel" : "",
"DeviceRunTime" : "0x00000FFA",
"DeviceType" : 0,
"DigChannel" : 0,
"EncryptVersion" : "Unknown",
"ExtraChannel" : 0,
"HardWare" : "HI3516EV100_50H20L_S38",
"HardWareVersion" : "Unknown",
"SerialNo" : "41e6853ada5e9323",
"SoftWareVersion" : "V4.02.R12.00035520.12012.047500.00200",
"TalkInChannel" : 1,
"TalkOutChannel" : 1,
"UpdataTime" : "",
"UpdataType" : "0x00000000",
"VideoInChannel" : 1,
"VideoOutChannel" : 1
}
}
[Done] exited with code=0 in 0.86 seconds
在20个字节的标头中还有几个我无法解读的值,所以我写了一个模糊器,看它们到底是什么。
Class that contains the basic process for making a message to/from the camera
class XMMessage
property type : UInt32
property session_id : UInt32
property unknown1 : UInt32
property unknown2 : UInt16
property magic : UInt16
property size : UInt32
property message : String
#TODO: Allow for spoofing of size, for example changing size to say that its 32 bytes, when its 0 or something
def self.from_s(string)
io = IO::Memory.new string
m = XMMessage.new
m.type = io.read_bytes(UInt32, IO::ByteFormat::LittleEndian)
m.session_id = io.read_bytes(UInt32, IO::ByteFormat::LittleEndian)
m.unknown1 = io.read_bytes(UInt32, IO::ByteFormat::LittleEndian)
m.unknown2 = io.read_bytes(UInt16, IO::ByteFormat::LittleEndian)
m.magic = io.read_bytes(UInt16, IO::ByteFormat::LittleEndian)
m.size = io.read_bytes(UInt32, IO::ByteFormat::LittleEndian)
m.message = string[20..string.size]
m
end
def initialize(@type = 0x000001ff_u32, @session_id = 0_u32, @unknown1 = 0_u32, @unknown2 = 0_u16, @magic = 0_u16, @size = 0_u32, @message = "")
end
def magic1 : UInt8
(magic & 0xFF).to_u8
end
def magic2 : UInt8
(magic >> 8).to_u8
end
def make_header
header_io = IO::Memory.new
header_io.write_bytes(type, IO::ByteFormat::LittleEndian)
header_io.write_bytes(session_id, IO::ByteFormat::LittleEndian)
header_io.write_bytes(unknown1, IO::ByteFormat::LittleEndian)
header_io.write_bytes(unknown2, IO::ByteFormat::LittleEndian)
header_io.write_bytes(magic, IO::ByteFormat::LittleEndian)
header_io.write_bytes(self.message.size, IO::ByteFormat::LittleEndian)
header_io.to_s
end
def make : String
(make_header + self.message)
end
end
接下来,我制作了模糊器的主要部分,它将填充每个可能的字节值,等待响应,然后断开连接并循环。
关于这个工作的一些注意事项:
1.我要定位两个字节,第一个是magic1,然后是magic2。
2.模糊器本身必须具有极高的容错能力,因为使用它时会发生很多错误。
当我想运行它时,理想的结果如下:
class Command::SystemInfo
这将运行一段时间,最终产生结果,尽管结果准确,但速度太慢了!从0x3到0x8的单次扫描可能需要24小时。
幸运的是,我有一些想法可以使其更快。
在测试过程中,我注意到该协议的一个有趣之处,服务器(摄像头)允许对同一个IP地址开放任意数量的连接,只要它们都位于不同的端口上即可。这意味着如果我可以创建一个套接字组,就可以使用它们一次审核多个magic字段,每个magic字段都等待自己的响应,
你可以在GitHub上查看相关代码。
Fuzzing Command::SystemInfo
Time: 00:29:14.794430000
Current: 4096/4097 : 1000
Total Completion: 99.976%
Waiting for magics:
0x0ffc : unused : 15642636659266745398 : 00:00:00.394592000
0x0ffd : unused : 3995498554981886474 : 00:00:00.394431000
0x0ff1 : unused : 16849123052220723596 : 00:00:00.424488000
0x0ffe : unused : 15843022912141103538 : 00:00:00.385055000
0x0ff2 : unused : 666834066939202384 : 00:00:00.424001000
0x0ff3 : unused : 11959220922209025486 : 00:00:00.423846000
上一页 [1] [2] [3] [4] [5] [6] [7] 下一页
下一篇:开源WAF测试评估方法