|
0 |
From: g0tmi1k <[email protected]>
|
|
1 |
Date: Wed, 1 Apr 2020 10:39:56 +0200
|
|
2 |
Subject: Switch to Python 3
|
|
3 |
|
|
4 |
Last-Update: 2020-03-31
|
|
5 |
Description: https://github.com/galkan/crowbar/pull/38
|
|
6 |
---
|
|
7 |
README.md | 73 +++++++++++++++++++-------------------------------
|
|
8 |
crowbar.py | 14 +++++-----
|
|
9 |
lib/core/iprange.py | 11 ++++----
|
|
10 |
lib/core/logger.py | 2 +-
|
|
11 |
lib/core/threadpool.py | 4 +--
|
|
12 |
lib/main.py | 14 +++++-----
|
|
13 |
lib/nmap.py | 21 ++++++++++-----
|
|
14 |
requirements.txt | 2 ++
|
|
15 |
8 files changed, 67 insertions(+), 74 deletions(-)
|
|
16 |
mode change 100644 => 100755 crowbar.py
|
|
17 |
create mode 100644 requirements.txt
|
|
18 |
|
|
19 |
diff --git a/README.md b/README.md
|
|
20 |
index 1a101bd..9a6c7c7 100644
|
|
21 |
--- a/README.md
|
|
22 |
+++ b/README.md
|
|
23 |
@@ -17,13 +17,26 @@ Currently **Crowbar** supports:
|
|
24 |
- SSH private key authentication (`-b sshkey`)
|
|
25 |
- VNC key authentication (`-b vpn`)
|
|
26 |
|
|
27 |
-
|
|
28 |
### Installation
|
|
29 |
|
|
30 |
-Install all the dependencies:
|
|
31 |
+**Kali Linux users can do**
|
|
32 |
+
|
|
33 |
+```
|
|
34 |
+# sudo apt install -y crowbar
|
|
35 |
+```
|
|
36 |
+
|
|
37 |
+Else if you wish to install from source, install all the dependencies:
|
|
38 |
+
|
|
39 |
+**Debain 9/10+ & Kali Rolling**
|
|
40 |
|
|
41 |
```
|
|
42 |
-# apt-get -y install openvpn freerdp-x11 vncviewer
|
|
43 |
+# apt install -y nmap openvpn freerdp2-x11 tigervnc-viewer
|
|
44 |
+```
|
|
45 |
+
|
|
46 |
+**Debain 7/8 & Kali 1/2**
|
|
47 |
+
|
|
48 |
+```
|
|
49 |
+# apt-get install -y nmap openvpn freerdp-x11 vncviewer
|
|
50 |
```
|
|
51 |
|
|
52 |
Then get latest version from GitHub:
|
|
53 |
@@ -34,11 +47,12 @@ Then get latest version from GitHub:
|
|
54 |
|
|
55 |
Note: The RDP client package depends on your OS:
|
|
56 |
|
|
57 |
++ Debain 9/10 & Kali Rolling uses `freerdp2-x11`
|
|
58 |
+ Debian 7/8 & Kali 1/2 uses `freerdp-x11` package.
|
|
59 |
+ Else you can try `xfreerdp`.
|
|
60 |
-+ Else you may need to compile & tweak `freerdp` by following: http://opentechnotes.blogspot.co.uk/2015/02/compile-headless-freerdp-credential-checking.html
|
|
61 |
++ The fall back method would be to compile & tweak `freerdp` by following: http://opentechnotes.blogspot.co.uk/2015/02/compile-headless-freerdp-credential-checking.html
|
|
62 |
|
|
63 |
-_Don't forget to edit the script to point to the new binary_!
|
|
64 |
+_Don't forget to patch `./lib/main.py` to point to the new binary_!
|
|
65 |
|
|
66 |
### Usage
|
|
67 |
|
|
68 |
@@ -96,14 +110,10 @@ If you want see all usage options, please use: `./crowbar.py --help`.
|
|
69 |
2015-03-28 11:04:00 RDP-SUCCESS : 10.68.35.150:3389 - "gokhan alkan@DOMAIN":Aa123456,
|
|
70 |
```
|
|
71 |
|
|
72 |
-
|
|
73 |
-
|
|
74 |
#### Brute Forcing Remote Desktop Protocol (RDP)
|
|
75 |
|
|
76 |
Below are a few examples of attacking RDP using Crowbar.
|
|
77 |
|
|
78 |
-
|
|
79 |
-
|
|
80 |
RDP brute forcing a single IP address using a single username and a single password:
|
|
81 |
|
|
82 |
```
|
|
83 |
@@ -112,134 +122,107 @@ RDP brute forcing a single IP address using a single username and a single passw
|
|
84 |
|
|
85 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowbar-rdp.jpg)
|
|
86 |
|
|
87 |
-
|
|
88 |
- - -
|
|
89 |
|
|
90 |
-
|
|
91 |
RDP brute forcing a single IP address using username list file and a single password:
|
|
92 |
|
|
93 |
```
|
|
94 |
-# ./crowbar.py -b rdp -s 192.168.2.211/32 -U /root/Desktop/userlist -c passw0rd
|
|
95 |
+# ./crowbar.py -b rdp -s 192.168.2.211/32 -U ~/Desktop/userlist -c passw0rd
|
|
96 |
```
|
|
97 |
|
|
98 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowvar-rdp-dosya.jpg)
|
|
99 |
|
|
100 |
-
|
|
101 |
- - -
|
|
102 |
|
|
103 |
-
|
|
104 |
RDP brute forcing a single IP address using a single username and a password list:
|
|
105 |
|
|
106 |
```
|
|
107 |
-# ./crowbar.py -b rdp -s 192.168.2.250/32 -u localuser -C /root/Desktop/passlist
|
|
108 |
+# ./crowbar.py -b rdp -s 192.168.2.250/32 -u localuser -C ~/Desktop/passlist
|
|
109 |
```
|
|
110 |
|
|
111 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowvar-rdp-dosya2.jpg)
|
|
112 |
|
|
113 |
-
|
|
114 |
- - -
|
|
115 |
|
|
116 |
-
|
|
117 |
RDP brute forcing a subnet using a username list and a password list in discovery mode:
|
|
118 |
|
|
119 |
```
|
|
120 |
-# ./crowbar.py -b rdp -s 192.168.2.0/24 -U /root/Desktop/userlist -C /root/Desktop/passlist -d
|
|
121 |
+# ./crowbar.py -b rdp -s 192.168.2.0/24 -U ~/Desktop/userlist -C ~/Desktop/passlist -d
|
|
122 |
```
|
|
123 |
|
|
124 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowvar-rdp-kadi-parola-dosya.jpg)
|
|
125 |
|
|
126 |
-
|
|
127 |
- - -
|
|
128 |
|
|
129 |
-
|
|
130 |
#### Brute Forcing SSH Private Keys
|
|
131 |
|
|
132 |
Below are a few examples which you have using Crowbar.
|
|
133 |
|
|
134 |
-
|
|
135 |
-
|
|
136 |
SSH key brute force attempt to a single IP address using a single username and a single private SSH key:
|
|
137 |
|
|
138 |
```
|
|
139 |
-# ./crowbar.py -b sshkey -s 192.168.2.105/32 -u root -k /root/.ssh/id_rsa
|
|
140 |
+# ./crowbar.py -b sshkey -s 192.168.2.105/32 -u root -k ~/.ssh/id_rsa
|
|
141 |
```
|
|
142 |
|
|
143 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowbar-ssh1.jpg)
|
|
144 |
|
|
145 |
-
|
|
146 |
- - -
|
|
147 |
|
|
148 |
-
|
|
149 |
SSH key brute force attempt to a single IP address using a single username and all the SSH keys in a folder:
|
|
150 |
|
|
151 |
```
|
|
152 |
-# ./crowbar.py -b sshkey -s 192.168.2.105/32 -u root -k /root/.ssh/
|
|
153 |
+# ./crowbar.py -b sshkey -s 192.168.2.105/32 -u root -k ~/.ssh/
|
|
154 |
```
|
|
155 |
|
|
156 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowbar-ssh2.jpg)
|
|
157 |
|
|
158 |
-
|
|
159 |
- - -
|
|
160 |
|
|
161 |
-
|
|
162 |
SSH key brute force attempt to a subnet using a single username and all the SSH keys in a folder in discovery mode:
|
|
163 |
|
|
164 |
```
|
|
165 |
-# ./crowbar.py -b sshkey -s 192.168.2.0/24 -u root -k /root/.ssh/ -d
|
|
166 |
+# ./crowbar.py -b sshkey -s 192.168.2.0/24 -u root -k ~/.ssh/ -d
|
|
167 |
```
|
|
168 |
|
|
169 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowbar-ssh3.jpg)
|
|
170 |
|
|
171 |
-
|
|
172 |
-
|
|
173 |
#### Brute Forcing VNC
|
|
174 |
|
|
175 |
Below is an example of attacking a VNC service using Crowbar.
|
|
176 |
|
|
177 |
-
|
|
178 |
-
|
|
179 |
VNC brute force attempt to a single IP address using a password file with specified port number:
|
|
180 |
|
|
181 |
```
|
|
182 |
-# ./crowbar.py -b vnckey -s 192.168.2.105/32 -p 5902 -k /root/.vnc/passwd
|
|
183 |
+# ./crowbar.py -b vnckey -s 192.168.2.105/32 -p 5902 -k ~/.vnc/passwd
|
|
184 |
```
|
|
185 |
|
|
186 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowbar-vnc.jpg)
|
|
187 |
|
|
188 |
-
|
|
189 |
-
|
|
190 |
### Brute Forcing OpenVPN
|
|
191 |
|
|
192 |
Below is an example of attacking OpenVPN using Crowbar.
|
|
193 |
|
|
194 |
-
|
|
195 |
-
|
|
196 |
OpenVPN brute force attempt to a single IP address using a configuration file, a certificate file, a single username and a single password with specified port number:
|
|
197 |
|
|
198 |
```
|
|
199 |
-# ./crowbar.py -b openvpn -s 198.7.62.204/32 -p 443 -m /root/Desktop/vpnbook.ovpn -k /root/Desktop/vpnbook_ca.crt -u vpnbook -c cr2hudaF
|
|
200 |
+# ./crowbar.py -b openvpn -s 198.7.62.204/32 -p 443 -m ~/Desktop/vpnbook.ovpn -k ~/Desktop/vpnbook_ca.crt -u vpnbook -c cr2hudaF
|
|
201 |
```
|
|
202 |
|
|
203 |
![](https://raw.githubusercontent.com/galkan/crowbar/master/images/crowbar-vpn.jpg)
|
|
204 |
|
|
205 |
-
|
|
206 |
-
|
|
207 |
- - -
|
|
208 |
|
|
209 |
### Logs & Output
|
|
210 |
|
|
211 |
Once you have executed Crowbar, it generates 2 files for logging and result that are located in your current directory. Default log file name is `crowbar.log` which stores all brute force attempts while execution. If you don't want use default log file, you should use `-l log_path`. The second file is `crowbar.out` which stores successful attempts while execution. If you don't want use default output file, you should use `-o output_path`. After that you can observe Crowbar operations.
|
|
212 |
|
|
213 |
-
|
|
214 |
- - -
|
|
215 |
|
|
216 |
### Thanks To
|
|
217 |
|
|
218 |
- Bahtiyar Bircan
|
|
219 |
- ErtuÄŸrul BaÅŸaranoÄŸlu
|
|
220 |
-- G0tmi1k
|
|
221 |
-
|
|
222 |
-
|
|
223 |
+- [g0tmi1k](https://twitter.com/g0tmi1k)
|
|
224 |
|
|
225 |
- - -
|
|
226 |
|
|
227 |
diff --git a/crowbar.py b/crowbar.py
|
|
228 |
old mode 100644
|
|
229 |
new mode 100755
|
|
230 |
index d35135c..12ae8ed
|
|
231 |
--- a/crowbar.py
|
|
232 |
+++ b/crowbar.py
|
|
233 |
@@ -1,12 +1,12 @@
|
|
234 |
-#!/usr/bin/env python2
|
|
235 |
+#!/usr/bin/env python3
|
|
236 |
|
|
237 |
try:
|
|
238 |
from lib.main import Main
|
|
239 |
from lib.core.exceptions import CrowbarExceptions
|
|
240 |
-except Exception, err:
|
|
241 |
- import sys
|
|
242 |
- print >> sys.stderr, err
|
|
243 |
- sys.exit(1)
|
|
244 |
+except Exception as err:
|
|
245 |
+ import sys
|
|
246 |
+ print(err, file=sys.stderr)
|
|
247 |
+ sys.exit(1)
|
|
248 |
|
|
249 |
##
|
|
250 |
### Main
|
|
251 |
@@ -17,7 +17,7 @@ if __name__ == "__main__":
|
|
252 |
try:
|
|
253 |
crowbar = Main()
|
|
254 |
crowbar.run(crowbar.args.brute)
|
|
255 |
- except Exception, err:
|
|
256 |
+ except Exception as err:
|
|
257 |
import sys
|
|
258 |
- print >> sys.stderr, err
|
|
259 |
+ print(err, file=sys.stderr)
|
|
260 |
sys.exit(1)
|
|
261 |
diff --git a/lib/core/iprange.py b/lib/core/iprange.py
|
|
262 |
index 6976bcc..528a9c9 100644
|
|
263 |
--- a/lib/core/iprange.py
|
|
264 |
+++ b/lib/core/iprange.py
|
|
265 |
@@ -3,8 +3,9 @@ try:
|
|
266 |
import sys
|
|
267 |
import socket
|
|
268 |
import struct
|
|
269 |
+ from functools import reduce
|
|
270 |
from lib.core.exceptions import CrowbarExceptions
|
|
271 |
-except Exceptions, err:
|
|
272 |
+except Exception as err:
|
|
273 |
from lib.core.exceptions import CrowbarExceptions
|
|
274 |
|
|
275 |
raise CrowbarExceptions(str(err))
|
|
276 |
@@ -23,7 +24,7 @@ class IpRange:
|
|
277 |
|
|
278 |
def ipaddr_to_binary(self, ipaddr):
|
|
279 |
q = ipaddr.split('.')
|
|
280 |
- return reduce(lambda a, b: long(a) * 256 + long(b), q)
|
|
281 |
+ return reduce(lambda a, b: int(a) * 256 + int(b), q)
|
|
282 |
|
|
283 |
def binary_to_ipaddr(self, ipbinary):
|
|
284 |
return socket.inet_ntoa(struct.pack('!I', ipbinary))
|
|
285 |
@@ -66,11 +67,11 @@ class IpRange:
|
|
286 |
b = b + 1
|
|
287 |
|
|
288 |
def cidr_iprange(self, ipaddr, cidrmask):
|
|
289 |
- mask = (long(2) ** long(32 - long(cidrmask))) - 1
|
|
290 |
+ mask = (int(2) ** int(32 - int(cidrmask))) - 1
|
|
291 |
b = self.ipaddr_to_binary(ipaddr)
|
|
292 |
e = self.ipaddr_to_binary(ipaddr)
|
|
293 |
- b = long(b & ~mask)
|
|
294 |
- e = long(e | mask)
|
|
295 |
+ b = int(b & ~mask)
|
|
296 |
+ e = int(e | mask)
|
|
297 |
while (b <= e):
|
|
298 |
yield self.binary_to_ipaddr(b)
|
|
299 |
b = b + 1
|
|
300 |
diff --git a/lib/core/logger.py b/lib/core/logger.py
|
|
301 |
index 7bd96c4..d610303 100644
|
|
302 |
--- a/lib/core/logger.py
|
|
303 |
+++ b/lib/core/logger.py
|
|
304 |
@@ -2,7 +2,7 @@ try:
|
|
305 |
import logging
|
|
306 |
import os.path
|
|
307 |
from lib.core.exceptions import CrowbarExceptions
|
|
308 |
-except Exception, err:
|
|
309 |
+except Exception as err:
|
|
310 |
from lib.core.exceptions import CrowbarExceptions
|
|
311 |
|
|
312 |
raise CrowbarExceptions(str(err))
|
|
313 |
diff --git a/lib/core/threadpool.py b/lib/core/threadpool.py
|
|
314 |
index 5d9609e..256529d 100644
|
|
315 |
--- a/lib/core/threadpool.py
|
|
316 |
+++ b/lib/core/threadpool.py
|
|
317 |
@@ -1,9 +1,9 @@
|
|
318 |
try:
|
|
319 |
import sys
|
|
320 |
- from Queue import Queue
|
|
321 |
+ from queue import Queue
|
|
322 |
from threading import Thread
|
|
323 |
from lib.core.exceptions import CrowbarExceptions
|
|
324 |
-except Exception, err:
|
|
325 |
+except Exception as err:
|
|
326 |
from lib.core.exceptions import CrowbarExceptions
|
|
327 |
|
|
328 |
raise CrowbarExceptions(str(err))
|
|
329 |
diff --git a/lib/main.py b/lib/main.py
|
|
330 |
index d526c75..3dfe828 100644
|
|
331 |
--- a/lib/main.py
|
|
332 |
+++ b/lib/main.py
|
|
333 |
@@ -14,12 +14,12 @@ try:
|
|
334 |
from lib.core.threadpool import ThreadPool
|
|
335 |
from lib.core.exceptions import CrowbarExceptions
|
|
336 |
from lib.core.iprange import IpRange, InvalidIPAddress
|
|
337 |
-except Exception, err:
|
|
338 |
+except Exception as err:
|
|
339 |
from lib.core.exceptions import CrowbarExceptions
|
|
340 |
|
|
341 |
raise CrowbarExceptions(str(err))
|
|
342 |
|
|
343 |
-__version__ = '0.3.5-dev'
|
|
344 |
+__version__ = '0.3.6-dev'
|
|
345 |
__banner__ = 'Crowbar v%s' % (__version__)
|
|
346 |
|
|
347 |
class AddressAction(argparse.Action):
|
|
348 |
@@ -131,7 +131,7 @@ class Main:
|
|
349 |
|
|
350 |
try:
|
|
351 |
self.args = parser.parse_args()
|
|
352 |
- except Exception, err:
|
|
353 |
+ except Exception as err:
|
|
354 |
raise CrowbarExceptions(str(err))
|
|
355 |
|
|
356 |
self.ip_list = []
|
|
357 |
@@ -214,7 +214,7 @@ class Main:
|
|
358 |
|
|
359 |
try:
|
|
360 |
pool = ThreadPool(int(self.args.thread))
|
|
361 |
- except Exception, err:
|
|
362 |
+ except Exception as err:
|
|
363 |
raise CrowbarExceptions(str(err))
|
|
364 |
|
|
365 |
for config_line in open(self.args.config, "r"):
|
|
366 |
@@ -310,7 +310,7 @@ class Main:
|
|
367 |
|
|
368 |
try:
|
|
369 |
pool = ThreadPool(int(self.args.thread))
|
|
370 |
- except Exception, err:
|
|
371 |
+ except Exception as err:
|
|
372 |
raise CrowbarExceptions(str(err))
|
|
373 |
|
|
374 |
for ip in self.ip_list:
|
|
375 |
@@ -358,7 +358,7 @@ class Main:
|
|
376 |
|
|
377 |
try:
|
|
378 |
pool = ThreadPool(int(self.args.thread))
|
|
379 |
- except Exception, err:
|
|
380 |
+ except Exception as err:
|
|
381 |
raise CrowbarExceptions(str(err))
|
|
382 |
|
|
383 |
for ip in self.ip_list:
|
|
384 |
@@ -435,7 +435,7 @@ class Main:
|
|
385 |
|
|
386 |
try:
|
|
387 |
pool = ThreadPool(self.args.thread)
|
|
388 |
- except Exception, err:
|
|
389 |
+ except Exception as err:
|
|
390 |
raise CrowbarExceptions(str(err))
|
|
391 |
|
|
392 |
if not os.path.exists(self.args.key_file):
|
|
393 |
diff --git a/lib/nmap.py b/lib/nmap.py
|
|
394 |
index a5edbb1..10b7bbb 100644
|
|
395 |
--- a/lib/nmap.py
|
|
396 |
+++ b/lib/nmap.py
|
|
397 |
@@ -5,7 +5,7 @@ try:
|
|
398 |
import tempfile
|
|
399 |
import subprocess
|
|
400 |
from lib.core.exceptions import CrowbarExceptions
|
|
401 |
-except Exception, err:
|
|
402 |
+except Exception as err:
|
|
403 |
from lib.core.exceptions import CrowbarExceptions
|
|
404 |
|
|
405 |
raise CrowbarExceptions(str(err))
|
|
406 |
@@ -20,7 +20,7 @@ class Nmap:
|
|
407 |
import nmap
|
|
408 |
self.lib = False
|
|
409 |
except ImportError:
|
|
410 |
- mess = "Please install the python-nmap module (pip install nmap)!"
|
|
411 |
+ mess = "Please install the python3-nmap module (pip3 install nmap)!"
|
|
412 |
raise CrowbarExceptions(mess)
|
|
413 |
except:
|
|
414 |
mess = "File: %s doesn't exists!" % self.nmap_path
|
|
415 |
@@ -34,17 +34,24 @@ class Nmap:
|
|
416 |
tmpfile = tempfile.NamedTemporaryFile(mode='w+t')
|
|
417 |
tmpfile_name = tmpfile.name
|
|
418 |
|
|
419 |
+ if os.geteuid() != 0:
|
|
420 |
+ nmap_scan_type = "-sT"
|
|
421 |
+ else:
|
|
422 |
+ nmap_scan_type = "-sS"
|
|
423 |
+
|
|
424 |
+ nmap_scan_option = "-n -Pn -T4 %s --open -p %s --host-timeout=10m --max-rtt-timeout=600ms --initial-rtt-timeout=300ms --min-rtt-timeout=300ms --max-retries=2 --min-rate=150 -oG %s" % (
|
|
425 |
+ nmap_scan_type, port, tmpfile_name)
|
|
426 |
+
|
|
427 |
if self.lib:
|
|
428 |
- nmap_scan_option = "-n -Pn -T4 -sS %s --open -p %s --host-timeout=10m --max-rtt-timeout=600ms --initial-rtt-timeout=300ms --min-rtt-timeout=300ms --max-retries=2 --min-rate=150 -oG %s" % (
|
|
429 |
- ip_list, port, tmpfile_name)
|
|
430 |
+ nmap_scan_option = "%s %s" % (
|
|
431 |
+ ip_list, nmap_scan_option)
|
|
432 |
run_nmap = "%s %s" % (self.nmap_path, nmap_scan_option)
|
|
433 |
proc = subprocess.Popen([run_nmap], shell=True, stdout=subprocess.PIPE, )
|
|
434 |
stdout_value = str(proc.communicate())
|
|
435 |
else:
|
|
436 |
nm = nmap.PortScanner()
|
|
437 |
nm.scan(hosts=ip_list,
|
|
438 |
- arguments="-n -Pn -T4 -sS --open -p %s --host-timeout=10m --max-rtt-timeout=600ms --initial-rtt-timeout=300ms --min-rtt-timeout=300ms --max-retries=2 --min-rate=150 -oG %s" % (
|
|
439 |
- port, tmpfile_name))
|
|
440 |
+ arguments=nmap_scan_option)
|
|
441 |
|
|
442 |
try:
|
|
443 |
for line in open(tmpfile_name, "r"):
|
|
444 |
@@ -52,5 +59,5 @@ class Nmap:
|
|
445 |
ip = line[:-1].split(" ")[1]
|
|
446 |
result.append(ip)
|
|
447 |
return result
|
|
448 |
- except Exception, err:
|
|
449 |
+ except Exception as err:
|
|
450 |
raise CrowbarExceptions(str(err))
|
|
451 |
diff --git a/requirements.txt b/requirements.txt
|
|
452 |
new file mode 100644
|
|
453 |
index 0000000..7a1e8f7
|
|
454 |
--- /dev/null
|
|
455 |
+++ b/requirements.txt
|
|
456 |
@@ -0,0 +1,2 @@
|
|
457 |
+paramiko>=2.7.1
|
|
458 |
+nmap>=0.0.1
|