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
|