Permalink
Browse files

Add script to unsign Mac executables

  • Loading branch information...
1 parent 840c897 commit c8587717be12e80f1f5b2d81e29c1c5707a495ed @tfmorris tfmorris committed Jul 29, 2013
Showing with 99 additions and 0 deletions.
  1. +99 −0 unsign
View
@@ -0,0 +1,99 @@
+#!/usr/bin/env ruby
+# Deactivates any embedded code signatures in a Mach-O binary.
+
+module MachO
+ class Unsign
+ def self.unsign(filename)
+ File.open(filename, "r+") do |f|
+ Unsign.new(f).headers
+ end
+ end
+
+ attr_accessor :headers
+
+ protected
+
+ FatHeader = Struct.new(:cpu_type, :cpu_subtype, :offset, :size, :align, :mach)
+ MachHeader = Struct.new(:cpu_type, :cpu_subtype, :filetype, :ncmds, :sizeofcmds, :flags, :reserved, :cmds)
+ LoadCommand = Struct.new(:cmd, :cmdsize)
+
+ def initialize(f)
+ @f = f
+ @headers = process
+ end
+
+ def debug(message)
+ puts message if ENV["DEBUG"]
+ end
+
+ def word_type
+ @big_endian ? 'N' : 'V'
+ end
+
+ def patch_code_signature(lc)
+ # just change LC_CODE_SIGNATURE to a high value that will be ignored by the loader
+ debug "PATCHING LC_CODE_SIGNATURE"
+ @f.seek(-8, IO::SEEK_CUR)
+ @f.write([0xff, lc.cmdsize].pack("#{word_type}2"))
+ lc
+ end
+
+ def process_mach
+ len = @x86_64 ? 7 : 6
+ header = MachHeader.new(*@f.read(len*4).unpack("#{word_type}#{len}"))
+ debug "MACH HEADER: #{header.inspect}"
+ header.cmds = (1..(header.ncmds)).collect do
+ lc = LoadCommand.new(*@f.read(8).unpack("#{word_type}2"))
+ debug "LOAD COMMAND: #{lc.inspect}"
+
+ lc = case lc.cmd
+ when 0x1d then patch_code_signature(lc)
+ else lc
+ end
+
+ @f.seek(lc.cmdsize - 8, IO::SEEK_CUR)
+
+ lc
+ end
+ header
+ end
+
+ def process_fat
+ num_arches, = @f.read(4).unpack("N")
+ arches = (1..num_arches).collect do
+ FatHeader.new(*@f.read(20).unpack("N5"))
+ end
+ debug "FAT HEADER: #{arches.inspect}"
+ arches.each do |arch|
+ @f.seek(arch.offset)
+ arch.mach = process
+ end
+ arches
+ end
+
+ def process
+ magic, = @f.read(4).unpack("N")
+ debug "MAGIC: 0x%08x" % magic
+ case magic
+ when 0xcafebabe then @big_endian, @x86_64 = false, false; process_fat
+ when 0xfeedface then @big_endian, @x86_64 = true, false; process_mach
+ when 0xcffaedfe then @big_endian, @x86_64 = false, true; process_mach
+ when 0xcefaedfe then @big_endian, @x86_64 = false, false; process_mach
+ else raise "unknown magic: 0x%08x" % magic
+ end
+ end
+ end
+end
+
+# command line driver
+if __FILE__ == $0
+ if ARGV.empty?
+ $stderr.puts "usage: #{$0} filename ..."
+ exit 1
+ end
+
+ ARGV.each do |filename|
+ puts "removing signatures from: #{filename}"
+ MachO::Unsign::unsign(filename)
+ end
+end

0 comments on commit c858771

Please sign in to comment.