codeobscure 0.1.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
+ SHA1:
3
+ metadata.gz: 8d45e95289d085a0efdd2c8597a5a5aa2cce266d
4
+ data.tar.gz: b1ca9ac495f2742f6a0d98629c4e0a6f66147807
5
+ SHA512:
6
+ metadata.gz: e475da848a16558d2cb66723a10ef58233e9e76a3599a0158fc9907360db5a58c0c84a5f173cb7c511ef4ff39e866b7ddfaf2ac99e5c8887c4b7650585ffc022
7
+ data.tar.gz: bb113db57be6ab97f88f5cefc3ad1840a8930448a511d0bf9c7b3b9105288fba88de9477874ef4d9e03344807b749551f05449e4607b272e32f9dfeff28ce8af
data/bin/codeobscure ADDED
@@ -0,0 +1,3 @@
1
+ require 'codeobscure'
2
+
3
+ Codeobscure.obscure
data/filtSymbols ADDED
Binary file
Binary file
@@ -0,0 +1,107 @@
1
+ require "codeobscure/version"
2
+ require "codeobscure/funclist"
3
+ require "codeobscure/obscure"
4
+ require "codeobscure/filtsymbols"
5
+ require "colorize"
6
+ require 'xcodeproj'
7
+ require 'fileutils'
8
+ require 'optparse'
9
+
10
+ module Codeobscure
11
+
12
+ def self.root
13
+ File.dirname __dir__
14
+ end
15
+
16
+ #waiting for add optionparse and add class obscure
17
+ def self.obscure
18
+
19
+ options = {}
20
+ OptionParser.new do |opts|
21
+ opts.banner = "Usage: obscure code for object-c project"
22
+
23
+ opts.on("-o", "--obscure XcodeprojPath", "obscure code") do |v|
24
+ options[:obscure] = v
25
+ end
26
+
27
+ opts.on("-l", "--load path1,path2,path3",Array,"load filt symbols from path") do |v|
28
+ options[:load] = v
29
+ end
30
+
31
+ opts.on("-r", "--reset", "reset loaded symbols") do |v|
32
+ options[:reset] = true
33
+ end
34
+
35
+ opts.on("-f", "--fetch type1,type2,type3", "fetch and replace type,default type is [c,p,f].c for class,p for property,f for function") do |v|
36
+ options[:fetch] = v
37
+ end
38
+
39
+ end.parse!
40
+
41
+ if options[:reset]
42
+ `rm -f #{root_dir}/filtSymbols`
43
+ `cp #{root_dir}/filtSymbols_standard #{root_dir}/filtSymbols`
44
+ end
45
+
46
+ #only load, execute load only
47
+ #only obscure, execute obscure only
48
+ #load and obscure at same time,load firt,then obscure.That's mean you can get rid of some directoies.
49
+ load_pathes = options[:load]
50
+ if load_pathes
51
+ load_pathes.each do |load_path|
52
+ if File.exist? load_path
53
+ FiltSymbols.loadFiltSymbols load_path
54
+ puts "加载完毕!".colorize(:green)
55
+ else
56
+ puts "指定的目录不存在:#{path}".colorize(:red)
57
+ end
58
+ end
59
+ end
60
+
61
+ fetch_types = ["p","c","f"]
62
+ if options[:fetch].length > 0
63
+ fetch_types = options[:fetch]
64
+ end
65
+
66
+ if options[:obscure]
67
+
68
+ xpj_path = options[:obscure]
69
+ if File.exist? xpj_path
70
+ root_dir = xpj_path.split("/")[0...-1].join "/"
71
+ FuncList.genFuncList root_dir , "all", true, fetch_types
72
+ header_file = Obscure.run root_dir
73
+ project = Xcodeproj::Project.open xpj_path
74
+ project_name = xpj_path.split("/").last
75
+ main_group = project.main_group
76
+ if !main_group.find_file_by_path("codeObfuscation.h")
77
+ main_group.new_reference header_file
78
+ end
79
+ project.targets.each do |target|
80
+ if target.name = project_name
81
+ build_configs = target.build_configurations
82
+ build_configs.each do |build_config|
83
+ build_settings = build_config.build_settings
84
+ prefix_key = "GCC_PREFIX_HEADER"
85
+ prefix_header = build_settings[prefix_key]
86
+ if prefix_header.nil? || prefix_header.empty?
87
+ build_config.build_settings[prefix_key] = "./codeObfuscation.h"
88
+ elsif prefix_header.include? "codeObfuscation.h"
89
+ puts "#{target.name}:#{build_config}配置文件已配置完成".colorize(:green)
90
+ else
91
+ puts "请在#{prefix_header.class.name}中#import \"codeObfuscation.h\"".colorize(:green)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ project.save
97
+ puts "配置完成!".colorize(:green)
98
+ puts "请直接运行项目,如果项目中出现类似: `+[LoremIpsum PyTJvHwWNmeaaVzp:]: unrecognized selector sent to class`。在codeObfuscation.h中查询PyTJvHwWNmeaaVzp并删除它!".colorize(:yellow)
99
+ else
100
+ puts "指定的目录不存在:#{path}".colorize(:red)
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,47 @@
1
+ require_relative "funclist.rb"
2
+ require "colorize"
3
+ module FiltSymbols
4
+ @@filt_db_path = "#{File.expand_path '../../..', __FILE__}/filtSymbols"
5
+ @@table_name = "symbols"
6
+ @@key_words = ["interface","NSInteger","BOOL","Class","free","M_PI_2","abort","change","top","bottom","NSUIntegerMax","intoString"]
7
+
8
+ def self.createTable
9
+ if !File.exist? @@filt_db_path
10
+ `echo "create table #{@@table_name}(src text,PRIMARY KEY (src));" | sqlite3 #{@@filt_db_path}`
11
+ end
12
+ end
13
+
14
+ def self.insertValue(line)
15
+ `echo "insert or ignore into #{@@table_name} values('#{line}');" | sqlite3 #{@@filt_db_path}`
16
+ end
17
+
18
+ def self.query(line)
19
+ `echo "select * from #{@@table_name} where src='#{line}';" | sqlite3 #{@@filt_db_path}`
20
+ end
21
+
22
+ def self.loadFiltSymbols(path)
23
+
24
+ createTable
25
+
26
+ funclist_path = FuncList.genFuncList path , "h" , false
27
+
28
+ puts "处理中,可能需要一段时间,耐心等候...".colorize(:yellow)
29
+ symbol_file = File.open(funclist_path).read
30
+ symbol_file.each_line do |line|
31
+ line_content = line.rstrip.split(":").last
32
+ insertValue line_content
33
+ end
34
+
35
+ @@key_words.each do |word|
36
+ insertValue word
37
+ end
38
+
39
+ if File.exist? funclist_path
40
+ `rm -f #{funclist_path}`
41
+ end
42
+
43
+ `sqlite3 #{@@filt_db_path} .dump`
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,159 @@
1
+ module FuncList
2
+
3
+ @@func_regex = /\s*(\w+)\s*:\s*\(\s*\w*\s*\s*\w+\s*\*?\s*\)\s*\w+\s*/
4
+ @@func_simple_regex = /\s*[-\+]\s*\(\s*\w+\s*\*?\)\s*(\w+)\s*;*/
5
+ @@hcls_regex = /@interface\s+(\w+)\s*/
6
+ @@mcls_regex = /@implementation\s+(\w+)\s*/
7
+ @@property_regex = /\s*@property\s*\(.*?getter=(\w+).*?\)\s*\w+\s*\*?\s*\w+\s*.*;/
8
+ @@property_regex2 = /\s*@property\s*\(.*?\)\s*\w+\s*\*?\s*(\w+)\s*.*;/
9
+ @@property_regex3 = /\s*@property\s*\(.*?\)\s*\w+\s*<.*>\s*\*?\s*(\w+)\s*.*;/
10
+
11
+ def self.to_utf8(str)
12
+ str = str.force_encoding('UTF-8')
13
+ return str if str.valid_encoding?
14
+ str.encode("UTF-8", 'binary', invalid: :replace, undef: :replace, replace: '')
15
+ end
16
+
17
+ def self.capture(content_str,type = "m",fetch_types=["p","f","c"])
18
+ results = []
19
+ str = to_utf8 content_str
20
+ if fetch_types.include? "f"
21
+ str.scan @@func_regex do |curr_match|
22
+ md = Regexp.last_match
23
+ whole_match = md[0]
24
+ captures = md.captures
25
+
26
+ captures.each do |capture|
27
+ results << "f:#{capture}"
28
+ #p [whole_match, capture]
29
+ p "f:[#{capture}]"
30
+ end
31
+ end
32
+ #no arguments function
33
+ str.scan @@func_simple_regex do |curr_match|
34
+ md = Regexp.last_match
35
+ whole_match = md[0]
36
+ captures = md.captures
37
+
38
+ captures.each do |capture|
39
+ results << "f:#{capture}"
40
+ #p [whole_match, capture]
41
+ p "f:[#{capture}]"
42
+ end
43
+ end
44
+ end
45
+ cls_regex = ""
46
+ if type == "h"
47
+ cls_regex = @@hcls_regex
48
+ else
49
+ cls_regex = @@mcls_regex
50
+ end
51
+ if fetch_types.include? "c"
52
+ str.scan cls_regex do |curr_match|
53
+ md = Regexp.last_match
54
+ whole_match = md[0]
55
+ captures = md.captures
56
+
57
+ captures.each do |capture|
58
+ results << "c:#{capture}"
59
+ #p [whole_match, capture]
60
+ p "c:[#{capture}]"
61
+ end
62
+ end
63
+ end
64
+ if fetch_types.include? "p"
65
+ str.scan @@property_regex do |curr_match|
66
+ md = Regexp.last_match
67
+ whole_match = md[0]
68
+ captures = md.captures
69
+
70
+ captures.each do |capture|
71
+ results << "p:#{capture}"
72
+ #p [whole_match, capture]
73
+ p "p:[#{capture}]"
74
+ end
75
+ end
76
+ str.scan @@property_regex2 do |curr_match|
77
+ md = Regexp.last_match
78
+ whole_match = md[0]
79
+ captures = md.captures
80
+
81
+ captures.each do |capture|
82
+ results << "p:#{capture}"
83
+ #p [whole_match, capture]
84
+ p "p:[#{capture}]"
85
+ end
86
+ end
87
+ str.scan @@property_regex3 do |curr_match|
88
+ md = Regexp.last_match
89
+ whole_match = md[0]
90
+ captures = md.captures
91
+
92
+ captures.each do |capture|
93
+ results << "p:#{capture}"
94
+ #p [whole_match, capture]
95
+ p "p:[#{capture}]"
96
+ end
97
+ end
98
+ end
99
+
100
+ results
101
+ end
102
+
103
+ def self.genFuncList(path,type = "m",need_filt=true,fetch_types=["p","f","c"])
104
+ puts "#######################{fetch_types}"
105
+ capture_methods = []
106
+ p_methods = []
107
+ funclist_path = "#{path}/func.list"
108
+ file = File.open(funclist_path, "w")
109
+ file_pathes = []
110
+ if type == "h" || type == "m"
111
+ file_pathes = `find #{path} -name "*.#{type}" -d`.split "\n"
112
+ elsif type == "all"
113
+ file_pathes += `find #{path} -name "*.h" -d`.split "\n"
114
+ file_pathes += `find #{path} -name "*.m" -d`.split "\n"
115
+ end
116
+ file_pathes.each do |file_path|
117
+ content = File.read file_path
118
+ captures = capture content , type , fetch_types
119
+ captures.each do |capture_method|
120
+ method_type = capture_method.split(":").first
121
+ method_content = capture_method.split(":").last
122
+ if !(method_content.start_with?("init") || method_content.start_with?("set") || method_content.start_with?("_") || method_content.length < 4) || !need_filt
123
+ if method_type == "c" || method_type == "f"
124
+ if !capture_methods.include? capture_method
125
+ capture_methods << capture_method
126
+ end
127
+ elsif method_type == "p"
128
+ if !p_methods.include? capture_method
129
+ p_methods << capture_method
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ p_methods.each do |capture_method|
137
+ method_type = capture_method.split(":").first
138
+ method_content = capture_method.split(":").last
139
+ c_method = "c:#{method_content}"
140
+ f_method = "f:#{method_content}"
141
+ if capture_methods.include? c_method
142
+ capture_methods.delete c_method
143
+ end
144
+ if capture_methods.include? f_method
145
+ capture_methods.delete f_method
146
+ end
147
+ end
148
+
149
+ capture_methods += p_methods
150
+
151
+ if capture_methods.length > 0
152
+ file.write(capture_methods.join "\n")
153
+ end
154
+ file.close
155
+ funclist_path
156
+ end
157
+
158
+ end
159
+
@@ -0,0 +1,89 @@
1
+ require_relative 'filtsymbols.rb'
2
+
3
+ class String
4
+ def upcase_first_letter
5
+ self.slice(0,1).capitalize + self.slice(1..-1)
6
+ end
7
+ end
8
+
9
+ module Obscure
10
+
11
+
12
+ @@TABLENAME="symbols"
13
+ @@SYMBOL_DB_FILE="symbols"
14
+ @@STRING_SYMBOL_FILE="func.list"
15
+
16
+ #维护数据库方便日后作排重
17
+ def self.createTable
18
+ if !File.exist? @@SYMBOL_DB_FILE
19
+ `echo "create table #{@@TABLENAME}(src text, des text,PRIMARY KEY (src));" | sqlite3 #{@@SYMBOL_DB_FILE}`
20
+ end
21
+ end
22
+
23
+ def self.insertValue(line,ramdom)
24
+ `echo "insert or ignore into #{@@TABLENAME} values('#{line}' ,'#{ramdom}');" | sqlite3 #{@@SYMBOL_DB_FILE}`
25
+ end
26
+
27
+ def self.query(line)
28
+ `echo "select * from #{@@TABLENAME} where src='#{line}';" | sqlite3 #{@@SYMBOL_DB_FILE}`
29
+ end
30
+
31
+ def self.ramdomString
32
+ `openssl rand -base64 64 | tr -cd 'a-zA-Z' |head -c 16`
33
+ end
34
+
35
+ #有define重复的问题等待解决
36
+ def self.run(root_dir)
37
+
38
+ @@HEAD_FILE="#{root_dir}/codeObfuscation.h"
39
+ @@SYMBOL_DB_FILE = "#{root_dir}/#{@@SYMBOL_DB_FILE}"
40
+ @@STRING_SYMBOL_FILE = "#{root_dir}/#{@@STRING_SYMBOL_FILE}"
41
+
42
+ if File.exist? @@SYMBOL_DB_FILE
43
+ `rm -f #{@@SYMBOL_DB_FILE}`
44
+ end
45
+ if File.exists? @@HEAD_FILE
46
+ `rm -f #{@@HEAD_FILE}`
47
+ end
48
+ createTable
49
+
50
+ date = `date`
51
+ file = File.new @@HEAD_FILE , 'w'
52
+ file.puts "#ifndef co_codeObfuscation_h"
53
+ file.puts "#define co_codeObfuscation_h"
54
+ file.puts "//confuse string at #{date.to_s}"
55
+
56
+ symbol_file = File.open(@@STRING_SYMBOL_FILE).read
57
+ symbol_file.each_line do |line|
58
+ line_type = line.rstrip.split(":").first
59
+ line_content = line.rstrip.split(":").last
60
+ result = FiltSymbols.query(line_content)
61
+ if result.nil? || result.empty?
62
+ ramdom = ramdomString
63
+ insertValue line_content , ramdom
64
+ if line_type == "p"
65
+ result = FiltSymbols.query("set#{line_content.upcase_first_letter}")
66
+ if result.nil? || result.empty?
67
+ file.puts "#define #{line_content} #{ramdom}"
68
+ file.puts "#define _#{line_content} _#{ramdom}"
69
+ file.puts "#define set#{line_content.upcase_first_letter} set#{ramdom.upcase_first_letter}"
70
+ end
71
+ else
72
+ file.puts "#define #{line_content} #{ramdom}"
73
+ end
74
+ end
75
+ end
76
+
77
+ file.puts "#endif"
78
+ file.close
79
+
80
+ `sqlite3 #{@@SYMBOL_DB_FILE} .dump`
81
+ if File.exist? @@SYMBOL_DB_FILE
82
+ `rm -f #{@@SYMBOL_DB_FILE}`
83
+ end
84
+ if File.exist? @@STRING_SYMBOL_FILE
85
+ `rm -f #{@@STRING_SYMBOL_FILE}`
86
+ end
87
+ @@HEAD_FILE
88
+ end
89
+ end
@@ -0,0 +1,3 @@
1
+ module Codeobscure
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+
3
+ class CodeobscureTest < Minitest::Test
4
+ def test_that_it_has_a_version_number
5
+ refute_nil ::Codeobscure::VERSION
6
+ end
7
+
8
+ def test_it_funclist_capture
9
+ result = FuncList.capture '+ (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view'
10
+ #因为没有去重
11
+ assert_equal result , ['f:pickerView','f:viewForRow','f:forComponent','f:reusingView','f:pickerView']
12
+ end
13
+
14
+ def test_it_funclist_genFuncList
15
+ test_dir = "#{File.dirname(__FILE__)}/objcTemple"
16
+ funclist_path = "#{test_dir}/func.list"
17
+ if File.exist? funclist_path
18
+ File.delete funclist_path
19
+ end
20
+ FuncList.genFuncList(test_dir)
21
+ is_exist = File.exist? funclist_path
22
+ assert is_exist , "generate func.list file failed"
23
+
24
+ content = File.read funclist_path
25
+ puts "=========#{content.split "\n"}"
26
+ expect_result = "f:addItem\nf:getClusters\nf:getRectWithPt\nf:Span\nf:getDistanceSquared\nf:point\nf:clearItems\nc:BMKClusterAlgorithm"
27
+ assert_equal expect_result , content
28
+ end
29
+
30
+ def test_it_obscure_run
31
+ test_dir = "#{File.dirname(__FILE__)}/objcTemple"
32
+ FuncList.genFuncList(test_dir)
33
+ path = "#{test_dir}/codeObfuscation.h"
34
+ if File.exist? path
35
+ File.delete path
36
+ end
37
+ Obscure.run test_dir
38
+ is_exist = File.exist? path
39
+ assert is_exist , "generate codeObfuscation.h failed"
40
+ end
41
+
42
+ #def test_it_filtsymbols_load
43
+ #test_dir = "#{File.dirname(__FILE__)}/objcTemple"
44
+ #FiltSymbols.loadFiltSymbols test_dir
45
+ #path = "#{File.expand_path '../..', __FILE__}/filtSymbols"
46
+ #is_exist = File.exist? path
47
+ #assert is_exist , "generate filtSymbols failed"
48
+ #end
49
+
50
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'codeobscure'
3
+
4
+ require 'minitest/autorun'
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: codeobscure
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - kaich
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-02 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: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: colorize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.7'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 0.7.7
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '0.7'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 0.7.7
75
+ - !ruby/object:Gem::Dependency
76
+ name: xcodeproj
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 1.0.0
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 1.0.0
89
+ description: Code Obscure Tool.You can use it simplely
90
+ email:
91
+ - chengkai1853@163.com
92
+ executables:
93
+ - codeobscure
94
+ extensions: []
95
+ extra_rdoc_files: []
96
+ files:
97
+ - bin/codeobscure
98
+ - filtSymbols
99
+ - filtSymbols_standard
100
+ - lib/codeobscure.rb
101
+ - lib/codeobscure/filtsymbols.rb
102
+ - lib/codeobscure/funclist.rb
103
+ - lib/codeobscure/obscure.rb
104
+ - lib/codeobscure/version.rb
105
+ - test/codeobscure_test.rb
106
+ - test/test_helper.rb
107
+ homepage: https://github.com/kaich/codeobscure
108
+ licenses:
109
+ - MIT
110
+ metadata:
111
+ allowed_push_host: https://rubygems.org
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ - bin
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.4.5
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Code Obscure For Xcode Project
133
+ test_files:
134
+ - test/codeobscure_test.rb
135
+ - test/test_helper.rb