peplum-john 0.2.0
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.
- 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: []
|