macos-artifacts 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bef9e063059ed8e1aa054b732e4fa670b438794331fd84c136088ddb3744ed79
4
+ data.tar.gz: 064d53b36446e2101a2d59479240d10c462ab22840627f6818ef9832d02d0948
5
+ SHA512:
6
+ metadata.gz: 3187009f4306d5ad8c41e496e0ce76c76a0e74741a66fb8e1cd9910a98b9c34fd7160a82f6d24e019d9d3d0a28844cc6e76af0a3c206ba65b57447a7d89130c9
7
+ data.tar.gz: 89d75dfe2fae0b58649ccc28fd27088ee3b37d6dd5f531c38fa568f95872730347dc41dad650c61c0909879effc118930f5b762d4bddf9ef2d1462e24a66df93
data/CHANGELOG.md ADDED
@@ -0,0 +1,62 @@
1
+ # Change Log
2
+
3
+
4
+ ---
5
+ ## version 0.6.0
6
+ - Add: `help` to output options. User `Macos::Artifacts::Help::options`
7
+
8
+ ---
9
+ ## version 0.5.2
10
+ - Add: `state` list of open network connections
11
+ - Add: `files` directory output for /private/tmp
12
+ - Add: `files` directory output for /Users/Shared
13
+
14
+ ---
15
+ ## version 0.5.0
16
+ - Add: `apps` module
17
+
18
+
19
+ ---
20
+ ## version 0.4.3
21
+ - Add: processCPU to `state` module
22
+ - Add: processMemoery to `state` module
23
+
24
+
25
+ ---
26
+ ## version 0.4.2
27
+ - Add: crontab to `files` module
28
+ - Add: hosts file to `files` module
29
+
30
+
31
+ ---
32
+ ## version 0.4.1
33
+ - Add: Preference files for system and users
34
+
35
+ ---
36
+ ## version 0.4.0
37
+ - UPDATE: refactor
38
+
39
+
40
+ ---
41
+ ## version 0.3.0
42
+ - UPDATE: break `logs` module out to it's own file
43
+
44
+
45
+ ---
46
+ ## version 0.2.2
47
+ - UPDATE: break `state` module out to it's own file
48
+
49
+
50
+ ---
51
+ ## version 0.2.0
52
+ - ADD: `state` module
53
+
54
+
55
+ ---
56
+ ## version 0.1.5
57
+ - ADD: `logs` module
58
+
59
+
60
+ ---
61
+ ## version 0.1.0
62
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 nic scott
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # Macos::Artifacts
2
+
3
+ ## Summary:
4
+ macOS Artifacts outpus a lot of information, from static facts about a machine (serial number, os verion), to outputs of file directories that may be usefull for discovery or reconnaissance (launchagenets and launchdaemons), to the current state of installed system extesnions.
5
+
6
+ Output is simple text making it able to be scraped up by an MDM or EDR solution to aid in an investiagtion. You can copy and save to a .yaml format if you want syntax highlighting, though output format is not strictly yaml.
7
+
8
+ ---
9
+ ## Installation:
10
+
11
+ `sudp gem install macos-artifacts`
12
+
13
+ ---
14
+ ## Usage:
15
+
16
+ `require 'macos/artifacts'`
17
+
18
+
19
+
20
+ For options:
21
+
22
+ Macos::Artifacts::Help::options
23
+
24
+ ```ruby
25
+ Macos::Artifacts::computerName
26
+ Macos::Artifacts::serial
27
+ Macos::Artifacts::version
28
+ Macos::Artifacts::build
29
+ Macos::Artifacts::kernel
30
+ Macos::Artifacts::modelName
31
+ Macos::Artifacts::modelID
32
+ Macos::Artifacts::chip
33
+ Macos::Artifacts::architecture
34
+ Macos::Artifacts::memory
35
+ Macos::Artifacts::hardwareUID
36
+ Macos::Artifacts::publicIP
37
+ Macos::Artifacts::privateIP
38
+ Macos::Artifacts::sipStatus
39
+ Macos::Artifacts::filevaultStatus
40
+ Macos::Artifacts::firewallStatus
41
+ Macos::Artifacts::screenlockStatus
42
+ Macos::Artifacts::lockStatus
43
+ Macos::Artifacts::softwareUpdates
44
+ Macos::Artifacts::Files::systemLaunchAgents
45
+ Macos::Artifacts::Files::systemLaunchDaemons
46
+ Macos::Artifacts::Files::userLaunchAgents
47
+ Macos::Artifacts::Files::listUsersAccountDirectory
48
+ Macos::Artifacts::Files::systemApplicationSupport
49
+ Macos::Artifacts::Files::userApplicationSupport
50
+ Macos::Artifacts::Files::libraryPreferences
51
+ Macos::Artifacts::Files::userLibraryPreferences
52
+ Macos::Artifacts::Files::cronTabs
53
+ Macos::Artifacts::Files::etcHosts
54
+ Macos::Artifacts::State::users
55
+ Macos::Artifacts::State::adminUsers
56
+ Macos::Artifacts::State::systemExtensions
57
+ Macos::Artifacts::State::processCPU
58
+ Macos::Artifacts::State::processMemory
59
+ ```
60
+
61
+
62
+
63
+ ```yaml
64
+ #Example output of all Macos::Artifacts commands
65
+ Host Name: nics-mac
66
+ Serial: X57CLJT7CV
67
+ Version: 13.5.1
68
+ Build: 22F82
69
+ Kernel: 22.5.0
70
+ Model Name: MacBook Pro
71
+ Model ID: MacBookPro18,3
72
+ Chip: Apple M1 Pro
73
+ Architecture: arm64
74
+ Memory: 32 GB
75
+ Hardware UID: 6AE03961-13A4-5418-BA2A-87FF9075FA91
76
+ Public IP: 172.76.37.139
77
+ Private IP: 192.68.68.68
78
+ SIP Status: enabled
79
+ FireVault Status: On
80
+ Firewall Status: Off
81
+ Screen Lock Status: screenLock delay is immediate
82
+ Activation Lock Status: Disabled
83
+ Software Updates:
84
+ Auto Updates: 1
85
+ Auto Download: 1
86
+ Auto Install: 1
87
+ Install Config Data: 1
88
+ Install Critical Updates: 1
89
+ ```
90
+
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Macos
4
+ module Artifacts
5
+ module Apps
6
+ def self.applications
7
+ $applicationsPath = "/Applications"
8
+ $applicationsDirectory = Dir.entries("#{$applicationsPath}")
9
+ puts "Applications Folder:"
10
+ $applicationsDirectory.sort!.each do | filename |
11
+ if ! filename.start_with?(".")
12
+ if File.extname(filename) == ".app"
13
+ plist = CFPropertyList::List.new(:file => "#{$applicationsPath}/#{filename}/Contents/Info.plist")
14
+ data = CFPropertyList.native_types(plist.value)
15
+ data.each do |k,v|
16
+ if k == "CFBundleShortVersionString"
17
+ puts " #{$applicationsPath}/#{filename}: #{v}"
18
+ end
19
+ end
20
+ else
21
+ if File.directory?("#{$applicationsPath}/#{filename}")
22
+ puts " #{$applicationsPath}/#{filename}:"
23
+ subpath = Dir.entries("#{$applicationsPath}/#{filename}")
24
+ subpath.each do |subdirapp|
25
+ if ! subdirapp.start_with?(".")
26
+ if File.extname(subdirapp) == ".app"
27
+ plist = CFPropertyList::List.new(:file => "#{$applicationsPath}/#{filename}/#{subdirapp}/Contents/Info.plist")
28
+ data = CFPropertyList.native_types(plist.value)
29
+ data.each do |k,v|
30
+ if k == "CFBundleShortVersionString"
31
+ puts " #{$applicationsPath}/#{filename}/#{subdirapp}: #{v}"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def self.packagesReceipts
44
+ pkgReceipts = `pkgutil --packages`.split("\n")
45
+ pkgReceipts.sort!
46
+ puts "Package Receipts: "
47
+
48
+ pkgReceipts.each do |pkg|
49
+ puts " #{pkg.strip}"
50
+ end
51
+ end
52
+
53
+ def self.installHistory
54
+ history = `system_profiler SPInstallHistoryDataType `.split("\n")
55
+ history.shift
56
+ history.shift
57
+ puts "Application Install History:"
58
+ history.each do |item|
59
+ item = item.strip
60
+ if ! item.empty?
61
+ if item.start_with?(/^Version:/)
62
+ puts " #{item}"
63
+ elsif item.start_with?(/^Source:/)
64
+ puts " #{item}"
65
+ elsif item.start_with?(/^Install Date:/)
66
+ puts " #{item}"
67
+ else
68
+ puts " #{item}"
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def self.appInstallLocations
75
+ history = `mdfind "kMDItemKind == Application"`.split("\n")
76
+ puts "Application Install Locations:"
77
+ history.each do |item|
78
+ if ! item.start_with?("/System")
79
+ puts " #{item.strip}"
80
+ end
81
+ end
82
+ end
83
+
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,279 @@
1
+ # frozen_string_literal: true
2
+
3
+ $currentUser = ENV['USER']
4
+
5
+ module Macos
6
+ module Artifacts
7
+ module Files
8
+
9
+ def self.systemLaunchAgents
10
+ $systemLaunchAgentsPath = "/Library/LaunchAgents"
11
+ $launchAgentDir = Dir.entries("#{$systemLaunchAgentsPath}")
12
+ puts "System Launchagents:"
13
+ $launchAgentDir.each do | filename |
14
+ if filename != "." && filename != ".."
15
+ puts " #{$systemLaunchAgentsPath}/#{filename}"
16
+ plist = CFPropertyList::List.new(:file => "#{$systemLaunchAgentsPath}/#{filename}")
17
+ data = CFPropertyList.native_types(plist.value)
18
+ data.each do |k,v|
19
+ puts " #{k}: #{v}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.systemLaunchDaemons
26
+ $systemLaunchAgentsPath = "/Library/LaunchDaemons"
27
+ $launchAgentDir = Dir.entries("#{$systemLaunchAgentsPath}")
28
+ puts "System LaunchDaemons:"
29
+ $launchAgentDir.each do | filename |
30
+ if filename != "." && filename != ".."
31
+ puts " #{$systemLaunchAgentsPath}/#{filename}"
32
+ plist = CFPropertyList::List.new(:file => "#{$systemLaunchAgentsPath}/#{filename}")
33
+ data = CFPropertyList.native_types(plist.value)
34
+ data.each do |k,v|
35
+ puts " #{k}: #{v}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def self.userLaunchAgents
42
+ userArray = []
43
+ Dir.entries("/Users").each do |username|
44
+ if !username.start_with?(".")
45
+ if username != "Shared" and username != "Guest"
46
+ userArray.push("#{username}")
47
+ end
48
+ end
49
+ end
50
+
51
+ userArray.each do |username|
52
+ userLaunchAgentsPath = "/Users/#{username}/Library/LaunchAgents"
53
+ if Dir.exist?("#{userLaunchAgentsPath}")
54
+ launchAgentDir = Dir.entries("#{userLaunchAgentsPath}")
55
+ puts "#{username} LaunchAgents:"
56
+ launchAgentDir.each do | filename |
57
+ if filename != "." && filename != ".." && filename != ".DS_Store"
58
+ puts " #{userLaunchAgentsPath}/#{filename}"
59
+ plist = CFPropertyList::List.new(:file => "#{userLaunchAgentsPath}/#{filename}")
60
+ data = CFPropertyList.native_types(plist.value)
61
+ data.each do |k,v|
62
+ puts " #{k}: #{v}"
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ def self.listUsersAccountDirectory
72
+ $userHomeFolder = Dir.entries("/Users/#{$currentUser}")
73
+ fileArray = []
74
+ $userHomeFolder.each do | filename |
75
+ if filename != "." && filename != ".."
76
+ filePath = "/Users/#{$currentUser}/#{filename}"
77
+ fileArray.push("#{filePath}")
78
+ end
79
+ end
80
+
81
+ fileArray = fileArray.sort
82
+
83
+ puts "Home Directory for #{$currentUser}:"
84
+ fileArray.each do |item|
85
+ if ! Dir.exist?("#{item}")
86
+ puts " #{item}"
87
+ elsif Dir.exist?("#{item}")
88
+ puts " #{item}:"
89
+ $subDir = Dir.entries("#{item}")
90
+ $subDir.each do |subfile|
91
+ if subfile != "." && subfile != ".."
92
+ puts " #{item}/#{subfile}"
93
+ end
94
+ end
95
+ else
96
+ puts "ERROR"
97
+ end
98
+ end
99
+ end
100
+
101
+ def self.userApplicationSupport
102
+ userApplicationSupport = "/Users/#{$currentUser}/Library/Application Support"
103
+ if Dir.exist?("#{userApplicationSupport}")
104
+ puts "#{$currentUser} Application Support:"
105
+ Dir.entries("#{userApplicationSupport}").each do | filename |
106
+ if filename != "." && filename != ".." && filename != ".DS_Store"
107
+ puts " #{userApplicationSupport}/#{filename}"
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ def self.systemApplicationSupport
114
+ systemApplicationSupport = "/Library/Application Support"
115
+ if Dir.exist?("#{systemApplicationSupport}")
116
+ puts "System Application Support:"
117
+ Dir.entries("#{systemApplicationSupport}").each do | filename |
118
+ if filename != "." && filename != ".." && filename != ".DS_Store"
119
+ puts " #{systemApplicationSupport}/#{filename}"
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ def self.libraryPreferences
126
+ systemApplicationSupport = "/Library/Preferences"
127
+ if Dir.exist?("#{systemApplicationSupport}")
128
+ puts "Library Preferences:"
129
+ Dir.entries("#{systemApplicationSupport}").each do | filename |
130
+ if filename != "." && filename != ".." && filename != ".DS_Store"
131
+ puts " #{systemApplicationSupport}/#{filename}"
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ def self.userLibraryPreferences
138
+ userArray = []
139
+ Dir.entries("/Users").each do |username|
140
+ if !username.start_with?(".")
141
+ if username != "Shared" and username != "Guest"
142
+ userArray.push("#{username}")
143
+ end
144
+ end
145
+ end
146
+ userArray.each do |username|
147
+ filesArray = []
148
+ userPreferences = "/Users/#{username}/Library/Preferences"
149
+ if Dir.exist?("#{userPreferences}")
150
+ puts "#{username} Preferences:"
151
+ Dir.entries("#{userPreferences}").each do | filename |
152
+ if filename != "." && filename != ".." && filename != ".DS_Store"
153
+ filesArray.push("#{userPreferences}/#{filename}")
154
+ end
155
+ end
156
+ end
157
+ filesArray.sort.each do |filename|
158
+ puts " #{filename}"
159
+ end
160
+ end
161
+ end
162
+
163
+ def self.cronTabs
164
+ cronTab = `/usr/bin/crontab -l`.strip
165
+ puts "crontabs:"
166
+ if cronTab.empty?
167
+ puts " No current crontabs"
168
+ else
169
+ puts " #{cronTab}"
170
+ end
171
+ end
172
+
173
+ def self.etcHosts
174
+ hostfiles = `cat /etc/hosts`.split("\n")
175
+ puts "Hosts File:"
176
+ hostfiles.each do |line|
177
+ puts " #{line}"
178
+ end
179
+ end
180
+
181
+ def self.usrLocal
182
+ path = "/usr/local"
183
+
184
+ puts "#{path} Directory:"
185
+ if File.exists?("#{path}")
186
+ output = `ls -al #{path}`.split("\n")
187
+ output.shift
188
+ output.each do |item|
189
+ puts " #{item}"
190
+ end
191
+ else
192
+ puts " No such file or directory"
193
+ end
194
+ end
195
+
196
+ def self.usrLocalBin
197
+ path = "/usr/local/bin"
198
+
199
+ puts "#{path} Directory:"
200
+ if File.exists?("#{path}")
201
+ output = `ls -al #{path}`.split("\n")
202
+ output.shift
203
+ output.each do |item|
204
+ puts " #{item}"
205
+ end
206
+ else
207
+ puts " No such file or directory"
208
+ end
209
+ end
210
+
211
+ def self.usrLocalSbin
212
+ path = "/usr/local/sbin"
213
+
214
+ puts "#{path} Directory:"
215
+ if File.exists?("#{path}")
216
+ output = `ls -al #{path}`.split("\n")
217
+ output.shift
218
+ output.each do |item|
219
+ puts " #{item}"
220
+ end
221
+ else
222
+ puts " No such file or directory"
223
+ end
224
+ end
225
+
226
+ def self.usersShared
227
+ path = "/Users/Shared"
228
+
229
+ puts "#{path} Directory:"
230
+ if File.exists?("#{path}")
231
+ output = `ls -al #{path}`.split("\n")
232
+ output.shift
233
+ output.each do |item|
234
+ puts " #{item}"
235
+ end
236
+ else
237
+ puts " No such file or directory"
238
+ end
239
+ end
240
+
241
+ def self.privateTmp
242
+ path = "/private/tmp"
243
+
244
+ puts "#{path} Directory:"
245
+ if File.exists?("#{path}")
246
+ output = `ls -al #{path}`.split("\n")
247
+ output.shift
248
+ output.each do |item|
249
+ puts " #{item}"
250
+ end
251
+ else
252
+ puts " No such file or directory"
253
+ end
254
+ end
255
+
256
+ def self.scriptInstallLocations
257
+ history1 = `mdfind "kMDItemKind == 'Shell Script'"`.split("\n")
258
+ puts "Script Install Locations:"
259
+ history1.each do |item|
260
+ if ! item.start_with?("/System", "/Library/Developer", "/usr/share", "/usr/bin", "/Library/Ruby")
261
+ if ! item.include? "/Library/Application Support/Code/User/History"
262
+ puts " #{item.strip}"
263
+ end
264
+ end
265
+ end
266
+
267
+ history = `mdfind "kMDItemKind == '* Source'"`.split("\n")
268
+ history.each do |item|
269
+ if ! item.start_with?("/System", "/Library/Developer", "/usr/share", "/usr/bin", "/Library/Ruby")
270
+ if ! item.include? "/Library/Application Support/Code/User/History"
271
+ puts " #{item.strip}"
272
+ end
273
+ end
274
+ end
275
+ end
276
+
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Macos
4
+ module Artifacts
5
+ module Help
6
+ def self.options
7
+ puts ""
8
+ puts "Summary:
9
+ Artifact is an easy way to output a lot of facts and states about a macOS machine.
10
+ It's meant to be quick text output so it can be returned via an MDM or EDR solution to aid in investigations"
11
+ puts ""
12
+ puts "Macos::Artifact Usage:"
13
+ puts " Macos::Artifacts::computerName uses scutil to return computername"
14
+ puts " Macos::Artifacts::serial returns serial number from system_profiler"
15
+ puts " Macos::Artifacts::version uses sw_vers to return os version"
16
+ puts " Macos::Artifacts::build uses sw_vers to return buld number"
17
+ puts " Macos::Artifacts::kernel uses uname to return kernel"
18
+ puts " Macos::Artifacts::modelName users system_profiler to return model name"
19
+ puts " Macos::Artifacts::modelID users system_profiler to return model id"
20
+ puts " Macos::Artifacts::chip users system_profiler to return hardware chip"
21
+ puts " Macos::Artifacts::architecture users uanme to return hardware architecture"
22
+ puts " Macos::Artifacts::memory users system_profiler to return memory installed"
23
+ puts " Macos::Artifacts::hardwareUID users system_profiler to return hardware id"
24
+ puts " Macos::Artifacts::publicIP public ip returned by dig"
25
+ puts " Macos::Artifacts::privateIP private ip returned by ipconfig"
26
+ puts " Macos::Artifacts::sipStatus returns sip status from csrutil"
27
+ puts " Macos::Artifacts::filevaultStatus returns filevault status from fdesetup"
28
+ puts " Macos::Artifacts::firewallStatus read firewall status from com.apple.alf"
29
+ puts " Macos::Artifacts::screenlockStatus checks screenlock status and time"
30
+ puts " Macos::Artifacts::lockStatus returns Activation Lock Status"
31
+ puts " Macos::Artifacts::softwareUpdates returns machines softwareupate settings"
32
+ puts ""
33
+ puts "Macos::Artifacts::Files Usage:"
34
+ puts " Macos::Artifacts::Files::systemLaunchAgents list output of installed /Library/LaunchAgents"
35
+ puts " Macos::Artifacts::Files::systemLaunchDaemons list output of installed /Library/LaunchDaemons"
36
+ puts " Macos::Artifacts::Files::userLaunchAgents list output of Users ~/Library/LaunchAgents"
37
+ puts " Macos::Artifacts::Files::listUsersAccountDirectory list output of users home directory"
38
+ puts " Macos::Artifacts::Files::systemApplicationSupport list output of /Library/Application Support"
39
+ puts " Macos::Artifacts::Files::userApplicationSupport list output of ~/Library/Application Support"
40
+ puts " Macos::Artifacts::Files::libraryPreferences list output of /Library/Preferences"
41
+ puts " Macos::Artifacts::Files::userLibraryPreferences list output of ~/Library/Preferences"
42
+ puts " Macos::Artifacts::Files::cronTabs list output crontabs"
43
+ puts " Macos::Artifacts::Files::etcHosts list output of /etc/hosts file"
44
+ puts " Macos::Artifacts::Files::usrLocal list output of /usr/local"
45
+ puts " Macos::Artifacts::Files::usrLocalBin list output of /usr/local/bin"
46
+ puts " Macos::Artifacts::Files::usrLocalSbin list output of /usr/local/sbin"
47
+ puts " Macos::Artifacts::Files::usersShared list output of /User/Shared"
48
+ puts " Macos::Artifacts::Files::privateTmp list ooutput of /private/tmp"
49
+ puts " Macos::Artifacts::Files::scriptInstallLocations list output paths for shell, python, ruby scripts"
50
+ puts ""
51
+ puts "Macos::Artifacts::State Usage:"
52
+ puts " Macos::Artifacts::State::users list of local users with UIDs"
53
+ puts " Macos::Artifacts::State::adminUsers list of users in admin gropu"
54
+ puts " Macos::Artifacts::State::systemExtensions output of systemextensionctl"
55
+ puts " Macos::Artifacts::State::processCPU top 10 CPU Processes"
56
+ puts " Macos::Artifacts::State::processMemory top 10 Memory Processes"
57
+ puts " Macos::Artifacts::State::openNetworkConnections open network connections"
58
+ puts " Macos::Artifacts::State::networkInterfaces returns network interfaces"
59
+ puts ""
60
+ puts "Macos::Artifacts::Apps Usage:"
61
+ puts " Macos::Artifacts::Apps::applications outputs main applicaitons folder with version"
62
+ puts " Macos::Artifacts::Apps::packagesReceipts outputs list of installed packages"
63
+ puts " Macos::Artifacts::Apps::installHistory outputs history of installed apps"
64
+ puts " Macos::Artifacts::Apps::appInstallLocations outputs list of appliction install paths"
65
+ puts ""
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Macos
4
+ module Artifacts
5
+ module State
6
+ def self.users
7
+ $userHash={}
8
+ Dir.entries("/Users").each do |username|
9
+ if !username.start_with?(".")
10
+ if username != "Shared" and username != "Guest"
11
+ uid = `id -u #{username}`.strip
12
+ $userHash["#{username}"] = uid
13
+ end
14
+ end
15
+ end
16
+
17
+ puts "Local Users:"
18
+ $userHash.each do |key, value|
19
+ puts " #{key}: #{value}"
20
+ end
21
+ end
22
+
23
+ def self.adminUsers
24
+ admins=`dscl . -read /Groups/admin GroupMembership`.split(" ")
25
+ admins.shift()
26
+
27
+ puts "Admins:"
28
+ admins.each do |name|
29
+ puts " #{name}"
30
+ end
31
+ end
32
+
33
+ def self.systemExtensions
34
+ sysext = `systemextensionsctl list`.split("\n")
35
+ sysext.shift()
36
+
37
+ puts "System Extensions:"
38
+ sysext.each do |line|
39
+
40
+ if line.start_with?('---')
41
+ line = line.split(" ")
42
+ puts " Type: #{line[1]}"
43
+ elsif !line.start_with?("enabled")
44
+ line = line.split(" ")
45
+ if line[0] = "*"
46
+ puts " Enabled: true"
47
+ else
48
+ puts " Enabled: false"
49
+ end
50
+ if line[1] = "*"
51
+ puts " Active: true"
52
+ else
53
+ puts " Active: false"
54
+ end
55
+ puts " TeamID: #{line[2]}"
56
+ puts " BundleID: #{line[3]}"
57
+ puts " Version: #{line[4]}"
58
+
59
+ if line[5] != "[activated"
60
+ if line[6] != "[activated"
61
+ if line[7] != "[activated"
62
+ if line[8] != "[activated"
63
+ puts " Name: #{line[5]} #{line[6]} #{line[7]} #{line[8]}"
64
+ else
65
+ puts " Name: #{line[5]} #{line[6]} #{line[7]}"
66
+ end
67
+ end
68
+ else
69
+ puts " Name: #{line[5]}"
70
+ end
71
+ else
72
+ puts " Name: #{line[5]}"
73
+ end
74
+
75
+ if line[6] == "[activated"
76
+ puts " State: #{line[6]} #{line[7]}"
77
+ elsif line[7] == "[activated"
78
+ puts " State: #{line[7]} #{line[8]}"
79
+ elsif line[8] == "[activated"
80
+ puts " State: #{line[8]} #{line[9]}"
81
+ elsif line[9] == "[activated"
82
+ puts " State: #{line[9]} #{line[10]}"
83
+ else
84
+ puts " State: #{line[6]} #{line[7]}"
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ def self.processCPU
91
+ $psArray = []
92
+ $psHash = {}
93
+ processes = `ps axc -o user,pid,%cpu,%mem,start,time,command`.split("\n")
94
+ processes.shift()
95
+
96
+ processes.each do |item|
97
+ data = item.split(" ")
98
+ psHash = {
99
+ :user => "#{data[0].strip}",
100
+ :pid => "#{data[1].strip}",
101
+ :cpu => "#{data[2].to_f}",
102
+ :mem => "#{data[3].strip}",
103
+ :start => "#{data[4].strip}",
104
+ :time => "#{data[5].strip}",
105
+ :command => "#{data[6].strip}"
106
+ }
107
+ $psArray.push(psHash)
108
+ end
109
+
110
+ $psArray.sort_by! { |hash| hash[:cpu] }
111
+ puts "Top 10 CPU Processes:"
112
+
113
+ $psArray.last(10).reverse.each do |ps|
114
+ ps.each do |key,value|
115
+ if key.to_s == "user"
116
+ puts " #{key}: #{value}"
117
+ else
118
+ puts " #{key}: #{value}"
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ def self.processMemory
125
+ $psArray = []
126
+ $psHash = {}
127
+ processes = `ps axc -o user,pid,%cpu,%mem,start,time,command`.split("\n")
128
+ processes.shift()
129
+
130
+ processes.each do |item|
131
+ data = item.split(" ")
132
+ psHash = {
133
+ :user => "#{data[0].strip.to_s}",
134
+ :pid => "#{data[1].strip}",
135
+ :cpu => "#{data[2].to_f}",
136
+ :mem => "#{data[3].strip}",
137
+ :start => "#{data[4].strip}",
138
+ :time => "#{data[5].strip}",
139
+ :command => "#{data[6].strip}"
140
+ }
141
+ $psArray.push(psHash)
142
+ end
143
+
144
+ $psArray.sort_by! { |hash| hash[:mem] }
145
+ puts "Top 10 Memory Processes:"
146
+
147
+ $psArray.last(10).reverse.each do |ps|
148
+ ps.each do |key,value|
149
+ if key.to_s == "user"
150
+ puts " #{key}: #{value}"
151
+ else
152
+ puts " #{key}: #{value}"
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ def self.openNetworkConnections
159
+ listOfOpenConnections = `lsof -i`.split("\n")
160
+ listOfOpenConnections.shift
161
+ puts "Open Network Connections:"
162
+ listOfOpenConnections.each do |line|
163
+ line = line.split(" ")
164
+ puts " Command: #{line[0]}"
165
+ puts " PID: #{line[1]}"
166
+ puts " USER: #{line[2]}"
167
+ puts " TYPE: #{line[4]}"
168
+ puts " NODE: #{line[7]}"
169
+ puts " NAME: #{line[8]}"
170
+ end
171
+ end
172
+
173
+ def self.networkInterfaces
174
+ listOfNetworkInterfaces = `ifconfig`.split("\n")
175
+ puts "Network Interfaces:"
176
+ listOfNetworkInterfaces.each do |item|
177
+ if item.start_with?(/^*:/)
178
+ puts item.strip
179
+ else
180
+ puts " #{item}"
181
+ end
182
+ end
183
+ end
184
+
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Macos
4
+ module Artifacts
5
+ VERSION = "0.6.0"
6
+ end
7
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "artifacts/version"
4
+ require_relative "artifacts/state"
5
+ require_relative "artifacts/files"
6
+ require_relative "artifacts/apps"
7
+ require_relative "artifacts/help"
8
+ require 'cfpropertylist'
9
+
10
+ $currentUser = ENV['USER']
11
+
12
+ module Macos
13
+ module Artifacts
14
+ def self.computerName
15
+ computerName = `scutil --get ComputerName`.strip
16
+ puts "Host Name: #{computerName}"
17
+ end
18
+
19
+ def self.serial
20
+ serialNumber = `system_profiler SPHardwareDataType | grep Serial | cut -d ":" -f2 | xargs`.strip
21
+ puts "Serial: #{serialNumber}"
22
+ end
23
+
24
+ def self.version
25
+ osVersion = `sw_vers -ProductVersion`.strip
26
+ puts "Version: #{osVersion}"
27
+ end
28
+
29
+ def self.build
30
+ osBuild = `sw_vers -BuildVersion`.strip
31
+ puts "Build: #{osBuild}"
32
+ end
33
+
34
+ def self.kernel
35
+ arch = `uname -r`.strip
36
+ puts "Kernel: #{arch}"
37
+ end
38
+
39
+ def self.modelName
40
+ modelName = `system_profiler SPHardwareDataType | grep "Model Name" | cut -d ":" -f2 | xargs`.strip
41
+ puts "Model Name: #{modelName}"
42
+ end
43
+
44
+ def self.modelID
45
+ modelID = `system_profiler SPHardwareDataType | grep "Model Identifier" | cut -d ":" -f2 | xargs`.strip
46
+ puts "Model ID: #{modelID}"
47
+ end
48
+
49
+ def self.chip
50
+ chipArch = `system_profiler SPHardwareDataType | grep "Chip" | cut -d ":" -f2 | xargs`.strip
51
+ puts "Chip: #{chipArch}"
52
+ end
53
+
54
+ def self.architecture
55
+ arch = `uname -m`.strip
56
+ puts "Architecture: #{arch}"
57
+ end
58
+
59
+ def self.memory
60
+ memory = `system_profiler SPHardwareDataType | grep "Memory" | cut -d ":" -f2 | xargs`.strip
61
+ puts "Memory: #{memory}"
62
+ end
63
+
64
+ def self.hardwareUID
65
+ uuid = `system_profiler SPHardwareDataType | grep "Hardware" | cut -d ":" -f2 | xargs`.strip
66
+ puts "Hardware UID: #{uuid}"
67
+ end
68
+
69
+ def self.publicIP
70
+ ip = `dig -4 TXT +short o-o.myaddr.l.google.com ns1.google.com | tr -d '"'`.strip
71
+ puts "Public IP: #{ip}"
72
+ end
73
+
74
+ def self.privateIP
75
+ ip = `ipconfig getifaddr en0`.strip
76
+ puts "Private IP: #{ip}"
77
+ end
78
+
79
+ def self.sipStatus
80
+ command = `csrutil status | cut -d ":" -f2 | xargs | head -c7 | xargs`.strip
81
+ puts "SIP Status: #{command}"
82
+ end
83
+
84
+ def self.filevaultStatus
85
+ command = `fdesetup status | awk '{print $3}' | head -c2 | xargs`.strip
86
+ puts "FireVault Status: #{command}"
87
+ end
88
+
89
+ def self.firewallStatus
90
+ command = `defaults read /Library/Preferences/com.apple.alf globalstate`.strip
91
+
92
+ if command == "0"
93
+ puts "Firewall Status: Off"
94
+ else
95
+ puts "Firewall Status: On"
96
+ end
97
+ end
98
+
99
+ def self.lockStatus
100
+ status = `system_profiler SPHardwareDataType | grep "Activation Lock Status" | cut -d ":" -f2 | xargs`.strip
101
+ puts "Activation Lock Status: #{status}"
102
+ end
103
+
104
+ def self.screenlockStatus
105
+ screensaverPlist = "/Library/Managed Preferences/com.apple.screensaver.plist"
106
+
107
+ if File.exists?("#{screensaverPlist}")
108
+ screenSaverTime = `defaults read '#{screensaverPlist}' askForPasswordDelay`.strip
109
+ puts "found"
110
+ else
111
+ $askForPasswordStatus = `sysadminctl -screenLock status 2>&1 >/dev/null`.split("]")
112
+ puts "Screen Lock Status: #{$askForPasswordStatus[1].strip}"
113
+ end
114
+ end
115
+
116
+ def self.softwareUpdates
117
+ managedUpdates = "/Library/Managed Preferences/com.apple.SoftwareUpdate.plist"
118
+
119
+ puts "Software Updates:"
120
+ if File.exists?("#{managedUpdates}")
121
+ autoCheck = `defaults read "#{managedUpdates}" AutomaticCheckEnabled`.strip
122
+ automaticDownload = `defaults read "#{managedUpdates}" AutomaticDownload`.strip
123
+ automaticallyInstallMacOSUpdates = `defaults read "#{managedUpdates}" AutomaticallyInstallMacOSUpdates`.strip
124
+ configDataInstall = `defaults read "#{managedUpdates}" ConfigDataInstall`.strip
125
+ criticalUpdateInstall = `defaults read "#{managedUpdates}" CriticalUpdateInstall`.strip
126
+ puts " Auto Updates: #{autoCheck}"
127
+ puts " Auto Download: #{automaticDownload}"
128
+ puts " Auto Install: #{automaticallyInstallMacOSUpdates}"
129
+ puts " Install Config Data: #{configDataInstall}"
130
+ puts " Install Critical Updates: #{criticalUpdateInstall}"
131
+ else
132
+ autoCheck = `defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled`.strip
133
+ automaticDownload = `defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload`.strip
134
+ automaticallyInstallMacOSUpdates = `defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticallyInstallMacOSUpdates`.strip
135
+ configDataInstall = `defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist ConfigDataInstall`.strip
136
+ criticalUpdateInstall = `defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall`.strip
137
+ puts " Auto Updates: #{autoCheck}"
138
+ puts " Auto Download: #{automaticDownload}"
139
+ puts " Auto Install: #{automaticallyInstallMacOSUpdates}"
140
+ puts " Install Config Data: #{configDataInstall}"
141
+ puts " Install Critical Updates: #{criticalUpdateInstall}"
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/macos/artifacts/version"
4
+ require_relative "lib/macos/artifacts/state"
5
+ require_relative "lib/macos/artifacts/files"
6
+ require_relative "lib/macos/artifacts/apps"
7
+ require_relative "lib/macos/artifacts/help"
8
+
9
+ Gem::Specification.new do |spec|
10
+ spec.name = "macos-artifacts"
11
+ spec.version = Macos::Artifacts::VERSION
12
+ spec.authors = ["nic scott"]
13
+ spec.email = ["nls.inbox@gmail.com"]
14
+ spec.summary = %q{A collection of macOS artifacts}
15
+ spec.homepage = "https://github.com/nlscott/macos-artifacts"
16
+ spec.license = "MIT"
17
+ spec.required_ruby_version = ">= 2.6.0"
18
+
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(__dir__) do
23
+ `git ls-files -z`.split("\x0").reject do |f|
24
+ (File.expand_path(f) == __FILE__) ||
25
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+ spec.add_development_dependency "bundler", ">= 2.2.33"
34
+ spec.add_development_dependency "CFPropertyList", ">= 3.0.6"
35
+ end
@@ -0,0 +1,6 @@
1
+ module Macos
2
+ module Artifacts
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: macos-artifacts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ platform: ruby
6
+ authors:
7
+ - nic scott
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-09-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.33
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.33
27
+ - !ruby/object:Gem::Dependency
28
+ name: CFPropertyList
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.6
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 3.0.6
41
+ description:
42
+ email:
43
+ - nls.inbox@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - CHANGELOG.md
49
+ - LICENSE.txt
50
+ - README.md
51
+ - Rakefile
52
+ - lib/macos/artifacts.rb
53
+ - lib/macos/artifacts/apps.rb
54
+ - lib/macos/artifacts/files.rb
55
+ - lib/macos/artifacts/help.rb
56
+ - lib/macos/artifacts/state.rb
57
+ - lib/macos/artifacts/version.rb
58
+ - macos-artifacts.gemspec
59
+ - sig/macos/artifacts.rbs
60
+ homepage: https://github.com/nlscott/macos-artifacts
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 2.6.0
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubygems_version: 3.2.3
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: A collection of macOS artifacts
83
+ test_files: []