Skip to content

Commit 9b70496

Browse files
authored
Create macho2app.rb
1 parent ce7b967 commit 9b70496

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

tools/exploit/macho2app.rb

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# $Id$
4+
#
5+
# This script converts a macho file to a macOS .app
6+
#
7+
# $Revision$
8+
#
9+
10+
require 'optparse'
11+
12+
msfbase = __FILE__
13+
while File.symlink?(msfbase)
14+
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
15+
end
16+
17+
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib')))
18+
require 'msfenv'
19+
20+
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
21+
22+
class MachoToApp
23+
24+
macho_path = nil
25+
app_name = nil
26+
27+
def get_opts
28+
29+
ARGV.options do |opt|
30+
opt.separator ''
31+
32+
opt.on('-f', String, 'The macho file produced by msfvenom') do |x|
33+
macho_path = x
34+
end
35+
36+
opt.on('-o', String, 'The output app name (without .app)') do |x|
37+
app_name = x
38+
end
39+
40+
opt.on_tail('-h', '--help', 'Show this message') do
41+
$stderr.puts opt
42+
exit
43+
end
44+
45+
opt.parse!
46+
47+
end
48+
end
49+
50+
def initialize
51+
@args = get_opts
52+
rescue OptionParser::MissingArgument => e
53+
$stderr.puts e.message
54+
exit
55+
end
56+
57+
def main
58+
if @args.empty?
59+
fail OptionParser::MissingArgument, 'No options set, try -h for usage'
60+
elsif @args[0].nil?
61+
fail OptionParser::MissingArgument, '-f is required'
62+
elsif @args[1].nil?
63+
fail OptionParser::MissingArgument, '-o is required'
64+
end
65+
orig_macho = File.expand_path(@args[0])
66+
warn orig_macho
67+
plist_outline = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
68+
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
69+
<plist version=\"1.0\">
70+
<dict>
71+
<key>CFBundleName</key>
72+
<string>#{@args[1]}</string>
73+
<key>CFBundleVersion</key>
74+
<string>1.0</string>
75+
<key>CFBundlePackageType</key>
76+
<string>APPL</string>
77+
<key>CFBundleExecutable</key>
78+
<string>#{@args[0]}</string>
79+
</dict>
80+
</plist>"
81+
82+
# A .app file is essentially a specialy treated directory on macOS,
83+
# so we will treat it as such
84+
system("chmod 777 #{@args[0]}") # This is the only way macOS will execute the macho
85+
Dir.mkdir("#{@args[1]}.app")
86+
Dir.chdir("#{@args[1]}.app")
87+
Dir.mkdir('Contents')
88+
Dir.chdir('Contents')
89+
Dir.mkdir('MacOS')
90+
File.open('Info.plist', 'w') do |f|
91+
f.write plist_outline
92+
end
93+
Dir.chdir('MacOS')
94+
system("mv #{orig_macho.inspect} ./#{@args[0]}")
95+
system("chmod 777 #{@args[0]}")
96+
Dir.chdir('../../..')
97+
puts "Final app produced: #{Dir.pwd}/#{@args[1]}.app"
98+
end
99+
100+
end
101+
102+
if __FILE__ == $PROGRAM_NAME
103+
bin = MachoToApp.new
104+
bin.main
105+
end

0 commit comments

Comments
 (0)