codeobscure 0.1.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 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