peplum-john 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/examples/rest/helpers.rb +44 -0
- data/examples/rest.rb +57 -0
- data/examples/rpc.rb +30 -0
- data/lib/peplum/john/application/payload.rb +144 -0
- data/lib/peplum/john/application.rb +21 -0
- data/lib/peplum/john/version.rb +7 -0
- data/lib/peplum/john.rb +15 -0
- data/peplum-john.gemspec +23 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3557101f19534057d6928e39832552c6d3f752efc61ab5818f32dc12c4bf73fa
|
4
|
+
data.tar.gz: 9f52968910d916f5f29066a21d68afa0d12b9e0e1839145d77c907e4ab485437
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3dea930e2f89973e7bd90830352d709db0274aceb90daad387760c6f3e83df2422f488ed262c0a22aeb76993fc6c24e0639e959a3fa11f6e8e52a382b5ca210c
|
7
|
+
data.tar.gz: 3bbf00ab6898ce84806a4dc92e082705ec1134ec32d656c4d7e2a861006cc86652a30074d8f38ede56680ac935f14cbd5cf26e2f1f5dbe1093e406e34ec38671
|
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "peplum/john"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
require "irb"
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
def response
|
6
|
+
if @last_response['Content-Type'].include? 'json'
|
7
|
+
data = JSON.load( @last_response.body )
|
8
|
+
else
|
9
|
+
data = @last_response.body
|
10
|
+
end
|
11
|
+
{
|
12
|
+
code: @last_response.code,
|
13
|
+
data: data
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def response_data
|
18
|
+
response[:data]
|
19
|
+
end
|
20
|
+
|
21
|
+
def request( method, resource = nil, parameters = nil )
|
22
|
+
uri = URI( "http://127.0.0.1:7331/#{resource}" )
|
23
|
+
|
24
|
+
Net::HTTP.start( uri.host, uri.port) do |http|
|
25
|
+
case method
|
26
|
+
when :get
|
27
|
+
uri.query = URI.encode_www_form( parameters ) if parameters
|
28
|
+
request = Net::HTTP::Get.new( uri )
|
29
|
+
|
30
|
+
when :post
|
31
|
+
request = Net::HTTP::Post.new( uri )
|
32
|
+
request.body = parameters.to_json
|
33
|
+
|
34
|
+
when :delete
|
35
|
+
request = Net::HTTP::Delete.new( uri )
|
36
|
+
|
37
|
+
when :put
|
38
|
+
request = Net::HTTP::Put.new( uri )
|
39
|
+
request.body = parameters.to_json
|
40
|
+
end
|
41
|
+
|
42
|
+
@last_response = http.request( request )
|
43
|
+
end
|
44
|
+
end
|
data/examples/rest.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'peplum/john'
|
2
|
+
require 'pp'
|
3
|
+
require_relative 'rest/helpers'
|
4
|
+
|
5
|
+
# Boot up our REST server for easy integration.
|
6
|
+
rest_pid = Peplum::John::Application.spawn( :rest, daemonize: true )
|
7
|
+
at_exit { Cuboid::Processes::Manager.kill rest_pid }
|
8
|
+
|
9
|
+
# Wait for the REST server to boot up.
|
10
|
+
while sleep 1
|
11
|
+
begin
|
12
|
+
request :get
|
13
|
+
rescue Errno::ECONNREFUSED
|
14
|
+
next
|
15
|
+
end
|
16
|
+
|
17
|
+
break
|
18
|
+
end
|
19
|
+
|
20
|
+
# Assign an Agent to the REST service for it to provide us with Instances.
|
21
|
+
john_agent = Peplum::John::Application.spawn( :agent, daemonize: true )
|
22
|
+
request :put, 'agent/url', john_agent.url
|
23
|
+
at_exit { john_agent.shutdown rescue nil }
|
24
|
+
|
25
|
+
# Create a new Instance and run with the following options.
|
26
|
+
request :post, 'instances', {
|
27
|
+
peplum: {
|
28
|
+
objects: %w(
|
29
|
+
6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090
|
30
|
+
36f583dd16f4e1e201eb1e6f6d8e35a2ccb3bbe2658de46b4ffae7b0e9ed872e
|
31
|
+
),
|
32
|
+
max_workers: 2
|
33
|
+
},
|
34
|
+
payload: {
|
35
|
+
format: 'raw-sha256'
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
# The ID is used to represent that instance and allow us to manage it from here on out.
|
40
|
+
instance_id = response_data['id']
|
41
|
+
|
42
|
+
while sleep( 1 )
|
43
|
+
# Continue looping while instance status is 'busy'.
|
44
|
+
request :get, "instances/#{instance_id}"
|
45
|
+
break if !response_data['busy']
|
46
|
+
end
|
47
|
+
|
48
|
+
puts '*' * 88
|
49
|
+
|
50
|
+
# Get the report.
|
51
|
+
request :get, "instances/#{instance_id}/report.json"
|
52
|
+
|
53
|
+
# Print out the report.
|
54
|
+
puts JSON.pretty_generate( JSON.load( response_data['data'] ) )
|
55
|
+
|
56
|
+
# Shutdown the Instance.
|
57
|
+
request :delete, "instances/#{instance_id}"
|
data/examples/rpc.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'peplum/john'
|
3
|
+
|
4
|
+
# Spawn an Agent as a daemon.
|
5
|
+
john_agent = Peplum::John::Application.spawn( :agent, daemonize: true )
|
6
|
+
at_exit { john_agent.shutdown rescue nil }
|
7
|
+
|
8
|
+
# Spawn and connect to an Instance.
|
9
|
+
john = Peplum::John::Application.connect( john_agent.spawn )
|
10
|
+
# Don't forget this!
|
11
|
+
at_exit { john.shutdown }
|
12
|
+
|
13
|
+
john.run(
|
14
|
+
peplum: {
|
15
|
+
objects: %w(
|
16
|
+
6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090
|
17
|
+
36f583dd16f4e1e201eb1e6f6d8e35a2ccb3bbe2658de46b4ffae7b0e9ed872e
|
18
|
+
),
|
19
|
+
max_workers: 2
|
20
|
+
},
|
21
|
+
payload: {
|
22
|
+
format: 'raw-sha256'
|
23
|
+
}
|
24
|
+
)
|
25
|
+
|
26
|
+
# Waiting to complete.
|
27
|
+
sleep 1 while john.running?
|
28
|
+
|
29
|
+
# Hooray!
|
30
|
+
puts JSON.pretty_generate( john.generate_report.data )
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Peplum
|
5
|
+
class John
|
6
|
+
class Application
|
7
|
+
|
8
|
+
module Payload
|
9
|
+
|
10
|
+
# For some reason doesn't work when specifying sane directories.
|
11
|
+
HASHES_FILE = "hashes.#{Process.pid}.txt"
|
12
|
+
at_exit { FileUtils.rm_f HASHES_FILE }
|
13
|
+
|
14
|
+
POT_FILE = "hashes.#{Process.pid}.pot"
|
15
|
+
at_exit { FileUtils.rm_f POT_FILE }
|
16
|
+
|
17
|
+
JOHN = 'john-the-ripper'
|
18
|
+
|
19
|
+
FORMATS = Set.new(%w(descrypt bsdicrypt md5crypt md5crypt-long bcrypt scrypt LM AFS
|
20
|
+
tripcode AndroidBackup adxcrypt agilekeychain aix-ssha1 aix-ssha256
|
21
|
+
aix-ssha512 andOTP ansible argon2 as400-des as400-ssha1 asa-md5
|
22
|
+
AxCrypt AzureAD BestCrypt BestCryptVE4 bfegg Bitcoin BitLocker
|
23
|
+
bitshares Bitwarden BKS Blackberry-ES10 WoWSRP Blockchain cardano
|
24
|
+
chap Clipperz cloudkeychain dynamic_n cq CRC32 cryptoSafe sha1crypt
|
25
|
+
sha256crypt sha512crypt Citrix_NS10 dahua dashlane diskcryptor Django
|
26
|
+
django-scrypt dmd5 dmg dominosec dominosec8 DPAPImk dragonfly3-32
|
27
|
+
dragonfly3-64 dragonfly4-32 dragonfly4-64 Drupal7 eCryptfs eigrp
|
28
|
+
electrum ENCDataVault-MD5 ENCDataVault-PBKDF2 EncFS enpass EPI
|
29
|
+
EPiServer ethereum fde Fortigate256 Fortigate FormSpring FVDE geli
|
30
|
+
gost gpg HAVAL-128-4 HAVAL-256-3 hdaa hMailServer hsrp IKE ipb2
|
31
|
+
itunes-backup iwork KeePass keychain keyring keystore known_hosts
|
32
|
+
krb4 krb5 krb5asrep krb5pa-sha1 krb5pa-md5 krb5tgs krb5-17 krb5-18
|
33
|
+
krb5-3 kwallet lp lpcli leet lotus5 lotus85 LUKS MD2 mdc2
|
34
|
+
MediaWiki monero money MongoDB scram Mozilla mscash mscash2 MSCHAPv2
|
35
|
+
mschapv2-naive mssql mssql05 mssql12 multibit mysqlna mysql-sha1
|
36
|
+
mysql net-ah nethalflm netlm netlmv2 net-md5 netntlmv2 netntlm
|
37
|
+
netntlm-naive net-sha1 nk notes md5ns nsec3 NT NT-long o10glogon
|
38
|
+
o3logon o5logon ODF Office oldoffice OpenBSD-SoftRAID openssl-enc
|
39
|
+
oracle oracle11 Oracle12C osc ospf Padlock Palshop Panama
|
40
|
+
PBKDF2-HMAC-MD4 PBKDF2-HMAC-MD5 PBKDF2-HMAC-SHA1 PBKDF2-HMAC-SHA256
|
41
|
+
PBKDF2-HMAC-SHA512 PDF PEM pfx pgpdisk pgpsda pgpwde phpass PHPS
|
42
|
+
PHPS2 pix-md5 PKZIP po postgres PST PuTTY pwsafe qnx RACF
|
43
|
+
RACF-KDFAES radius RAdmin RAKP rar RAR5 Raw-SHA512 Raw-Blake2
|
44
|
+
Raw-Keccak Raw-Keccak-256 Raw-MD4 Raw-MD5 Raw-MD5u Raw-SHA1
|
45
|
+
Raw-SHA1-AxCrypt Raw-SHA1-Linkedin Raw-SHA224 Raw-SHA256 Raw-SHA3
|
46
|
+
Raw-SHA384 restic ripemd-128 ripemd-160 rsvp RVARY Siemens-S7
|
47
|
+
Salted-SHA1 SSHA512 sapb sapg saph sappse securezip 7z Signal SIP
|
48
|
+
skein-256 skein-512 skey SL3 Snefru-128 Snefru-256 LastPass SNMP
|
49
|
+
solarwinds SSH sspr Stribog-256 Stribog-512 STRIP SunMD5 SybaseASE
|
50
|
+
Sybase-PROP tacacs-plus tcp-md5 telegram tezos Tiger timeroast
|
51
|
+
tc_aes_xts tc_ripemd160 tc_ripemd160boot tc_sha512 tc_whirlpool vdi
|
52
|
+
OpenVMS vmx VNC vtp wbb3 whirlpool whirlpool0 whirlpool1 wpapsk
|
53
|
+
wpapsk-pmk xmpp-scram xsha xsha512 zed ZIP ZipMonster plaintext
|
54
|
+
has-160 HMAC-MD5 HMAC-SHA1 HMAC-SHA224 HMAC-SHA256 HMAC-SHA384
|
55
|
+
HMAC-SHA512 AndroidBackup-opencl agilekeychain-opencl ansible-opencl
|
56
|
+
axcrypt-opencl axcrypt2-opencl bcrypt-opencl Bitcoin-opencl
|
57
|
+
BitLocker-opencl bitwarden-opencl blockchain-opencl cloudkeychain-opencl
|
58
|
+
md5crypt-opencl cryptosafe-opencl sha1crypt-opencl sha256crypt-opencl
|
59
|
+
sha512crypt-opencl dashlane-opencl descrypt-opencl diskcryptor-opencl
|
60
|
+
diskcryptor-aes-opencl dmg-opencl electrum-modern-opencl EncFS-opencl
|
61
|
+
enpass-opencl ethereum-opencl ethereum-presale-opencl FVDE-opencl
|
62
|
+
geli-opencl gpg-opencl iwork-opencl KeePass-opencl keychain-opencl
|
63
|
+
keyring-opencl keystore-opencl krb5pa-md5-opencl krb5pa-sha1-opencl
|
64
|
+
krb5tgs-opencl krb5asrep-aes-opencl lp-opencl lpcli-opencl LM-opencl
|
65
|
+
lotus5-opencl mscash-opencl mscash2-opencl mysql-sha1-opencl
|
66
|
+
notes-opencl NT-opencl ntlmv2-opencl NT-long-opencl o5logon-opencl
|
67
|
+
ODF-opencl office-opencl oldoffice-opencl OpenBSD-SoftRAID-opencl
|
68
|
+
PBKDF2-HMAC-SHA256-opencl PBKDF2-HMAC-SHA512-opencl PBKDF2-HMAC-MD4-opencl
|
69
|
+
PBKDF2-HMAC-MD5-opencl PBKDF2-HMAC-SHA1-opencl pem-opencl pfx-opencl
|
70
|
+
pgpdisk-opencl pgpsda-opencl pgpwde-opencl phpass-opencl pwsafe-opencl
|
71
|
+
RAKP-opencl rar-opencl RAR5-opencl raw-MD4-opencl raw-MD5-opencl
|
72
|
+
raw-SHA1-opencl raw-SHA256-opencl raw-SHA512-free-opencl
|
73
|
+
raw-SHA512-opencl salted-SHA1-opencl sappse-opencl 7z-opencl SL3-opencl
|
74
|
+
solarwinds-opencl ssh-opencl sspr-opencl strip-opencl TrueCrypt-opencl
|
75
|
+
telegram-opencl tezos-opencl timeroast-opencl vmx-opencl wpapsk-opencl
|
76
|
+
wpapsk-pmk-opencl XSHA512-free-opencl XSHA512-opencl zed-opencl
|
77
|
+
))
|
78
|
+
|
79
|
+
def run( hashes, options )
|
80
|
+
validate( options )
|
81
|
+
|
82
|
+
File.open( HASHES_FILE, 'w+', 0666 ) do |f|
|
83
|
+
hashes.each do |hash|
|
84
|
+
f.puts hash
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
_run options
|
89
|
+
end
|
90
|
+
|
91
|
+
# Distribute `objects` into `chunks` amount of groups, one for each worker.
|
92
|
+
#
|
93
|
+
# @param [Array] objects All objects that need to be processed.
|
94
|
+
# @param [Integer] chunks Amount of object groups that should be generated.
|
95
|
+
#
|
96
|
+
# @return [Array<Array<Object>>] `objects` split in `chunks` amount of groups
|
97
|
+
# @abstract
|
98
|
+
def group( objects, chunks )
|
99
|
+
objects.chunk chunks
|
100
|
+
end
|
101
|
+
|
102
|
+
# Merge result `data` for reporting.
|
103
|
+
#
|
104
|
+
# @param [Array] data Report data from workers.
|
105
|
+
# @abstract
|
106
|
+
def merge( data )
|
107
|
+
f = data.pop
|
108
|
+
data.each { |d| f.merge! d }
|
109
|
+
f
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def executable
|
115
|
+
@executable ||= `which #{JOHN}`.strip
|
116
|
+
return @executable if !@executable.empty?
|
117
|
+
|
118
|
+
fail Error, 'Could not locate John The Ripper executable!'
|
119
|
+
end
|
120
|
+
|
121
|
+
def _run( options )
|
122
|
+
`#{executable} --no-log --pot=#{POT_FILE} --format=#{options['format']} #{HASHES_FILE} 2> /dev/null`
|
123
|
+
`#{executable} --format=#{options['format']} #{HASHES_FILE} 2> /dev/null`
|
124
|
+
|
125
|
+
results = {}
|
126
|
+
File.open( POT_FILE , 'r' ) do |f|
|
127
|
+
line = f.readline
|
128
|
+
hash, password = line.split( '$' ).last.split( ':' )
|
129
|
+
results[hash] = password.strip
|
130
|
+
end
|
131
|
+
results
|
132
|
+
end
|
133
|
+
|
134
|
+
def validate( options )
|
135
|
+
fail ArgumentError, 'Missing hash format' if !options['format']
|
136
|
+
fail ArgumentError, "Unknown format: options['format']" if FORMATS.include? options['format']
|
137
|
+
end
|
138
|
+
|
139
|
+
extend self
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'peplum'
|
4
|
+
|
5
|
+
module Peplum
|
6
|
+
class John
|
7
|
+
|
8
|
+
class Application < Peplum::Application
|
9
|
+
require_relative "application/payload"
|
10
|
+
|
11
|
+
provision_memory 100 * 1024 * 1024
|
12
|
+
provision_disk 100 * 1024 * 1024
|
13
|
+
|
14
|
+
def payload
|
15
|
+
Payload
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/peplum/john.rb
ADDED
data/peplum-john.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/peplum/john/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "peplum-john"
|
7
|
+
spec.version = Peplum::John::VERSION
|
8
|
+
spec.authors = ["Tasos Laskos"]
|
9
|
+
spec.email = ["tasos.laskos@ecsypno.com"]
|
10
|
+
|
11
|
+
spec.summary = "Peplum-powered John the Ripper."
|
12
|
+
spec.description = "A distributed approach to the John the Ripper password recovery tool"
|
13
|
+
spec.homepage = "http://ecsypno.com/"
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
15
|
+
|
16
|
+
spec.files = Dir.glob( 'bin/*')
|
17
|
+
spec.files += Dir.glob( 'lib/**/*')
|
18
|
+
spec.files += Dir.glob( 'examples/**/*')
|
19
|
+
spec.files += %w(peplum-john.gemspec)
|
20
|
+
|
21
|
+
|
22
|
+
spec.add_dependency "peplum"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: peplum-john
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tasos Laskos
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-05-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: peplum
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: A distributed approach to the John the Ripper password recovery tool
|
28
|
+
email:
|
29
|
+
- tasos.laskos@ecsypno.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- bin/console
|
35
|
+
- bin/setup
|
36
|
+
- examples/rest.rb
|
37
|
+
- examples/rest/helpers.rb
|
38
|
+
- examples/rpc.rb
|
39
|
+
- lib/peplum/john.rb
|
40
|
+
- lib/peplum/john/application.rb
|
41
|
+
- lib/peplum/john/application/payload.rb
|
42
|
+
- lib/peplum/john/version.rb
|
43
|
+
- peplum-john.gemspec
|
44
|
+
homepage: http://ecsypno.com/
|
45
|
+
licenses: []
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 2.6.0
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubygems_version: 3.4.13
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: Peplum-powered John the Ripper.
|
66
|
+
test_files: []
|