neri 0.9.4 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/neri/build.rb +66 -20
- data/lib/neri/runtime.rb +76 -60
- data/lib/neri/version.rb +1 -1
- data/neri.gemspec +0 -2
- metadata +3 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 588a4e8a5a9ad862218a5ed2b58607fc6433d0dfd3921b82201053194e4b11e2
|
4
|
+
data.tar.gz: 643ad4e58dfb6235532967bff42fcbcb2482abf78a47f4e180e22012b3105c52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e653c9a96b631386bd0501ace47feafa2c46d58d68358cb9735f9e1d53a03bcb3f8e7710e8f54c874c932c03c9bc9c91b47e5cee34741b7c1661cffc06d7983
|
7
|
+
data.tar.gz: 8ca1e16f5eb2e768ceec1dc5d1e04a019985411c684d70b186cec26796f044308d01cb68263f86e23dba7ef4e986df95278ede44200e0220e7938618080ff2ca
|
data/lib/neri/build.rb
CHANGED
@@ -18,7 +18,7 @@ module Neri
|
|
18
18
|
|
19
19
|
enable_gems: false,
|
20
20
|
enable_did_you_mean: false,
|
21
|
-
chdir_first:
|
21
|
+
chdir_first: true,
|
22
22
|
pause_last: nil,
|
23
23
|
pause_text: nil,
|
24
24
|
|
@@ -27,6 +27,7 @@ module Neri
|
|
27
27
|
|
28
28
|
datafile: nil,
|
29
29
|
encryption_key: nil,
|
30
|
+
virtual_directory: nil,
|
30
31
|
|
31
32
|
no_exe: false,
|
32
33
|
use_b2ec: false,
|
@@ -111,7 +112,7 @@ options:
|
|
111
112
|
|
112
113
|
--enable-gems
|
113
114
|
--enable-did-you-mean
|
114
|
-
--chdir
|
115
|
+
--no-chdir
|
115
116
|
--pause-last
|
116
117
|
--no-pause-last
|
117
118
|
--pause-text <text>
|
@@ -155,6 +156,7 @@ options:
|
|
155
156
|
|
156
157
|
--create-recipe <recipefile>
|
157
158
|
--recipe <recipefile>
|
159
|
+
--virtual-directory <string>
|
158
160
|
HELP_MESSAGE
|
159
161
|
end
|
160
162
|
|
@@ -209,7 +211,9 @@ options:
|
|
209
211
|
options[:enable_gems] = true
|
210
212
|
when "--enable-did-you-mean"
|
211
213
|
options[:enable_did_you_mean] = true
|
212
|
-
when "--chdir
|
214
|
+
when "--no-chdir"
|
215
|
+
options[:chdir_first] = false
|
216
|
+
when "--chdir-first" # deprecated
|
213
217
|
options[:chdir_first] = true
|
214
218
|
when "--pause-last"
|
215
219
|
options[:pause_last] = true
|
@@ -292,6 +296,8 @@ options:
|
|
292
296
|
filename = ARGV.shift.encode("utf-8")
|
293
297
|
nputs_v "Loading recipe_file '#{filename}'."
|
294
298
|
load File.expand_path(filename)
|
299
|
+
when "--virtual-directory"
|
300
|
+
options[:virtual_directory] = ARGV.shift.encode("utf-8")
|
295
301
|
when "--"
|
296
302
|
break
|
297
303
|
when /^(--.+)/
|
@@ -328,27 +334,54 @@ options:
|
|
328
334
|
end
|
329
335
|
|
330
336
|
def dll_dependencies
|
331
|
-
require "
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
+
require "fiddle/import"
|
338
|
+
|
339
|
+
pointer_type = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
|
340
|
+
psapi = Fiddle.dlopen("psapi.dll")
|
341
|
+
kernel32 = Fiddle.dlopen("kernel32.dll")
|
342
|
+
enumprocessmodules = Fiddle::Function.new(
|
343
|
+
psapi["EnumProcessModules"],
|
344
|
+
[Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP],
|
345
|
+
Fiddle::TYPE_LONG,
|
346
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
347
|
+
)
|
348
|
+
getmodulefilename = Fiddle::Function.new(
|
349
|
+
kernel32["GetModuleFileNameW"],
|
350
|
+
[Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG],
|
351
|
+
Fiddle::TYPE_LONG,
|
352
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
353
|
+
)
|
354
|
+
getcurrentprocess = Fiddle::Function.new(
|
355
|
+
kernel32["GetCurrentProcess"],
|
356
|
+
[],
|
357
|
+
Fiddle::TYPE_LONG,
|
358
|
+
Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[:stdcall]
|
359
|
+
)
|
360
|
+
|
337
361
|
bytes_needed = 4 * 32
|
338
362
|
module_handle_buffer = nil
|
339
363
|
process_handle = getcurrentprocess.call
|
340
364
|
loop do
|
341
365
|
module_handle_buffer = "\x00" * bytes_needed
|
342
366
|
bytes_needed_buffer = [0].pack("I")
|
343
|
-
enumprocessmodules.call(
|
367
|
+
enumprocessmodules.call(
|
368
|
+
[process_handle].pack("I").unpack1("i"),
|
369
|
+
[module_handle_buffer].pack("p").unpack1(pointer_type),
|
370
|
+
[module_handle_buffer.size].pack("I").unpack1("i"),
|
371
|
+
[bytes_needed_buffer].pack("p").unpack1(pointer_type)
|
372
|
+
)
|
344
373
|
bytes_needed = bytes_needed_buffer.unpack1("I")
|
345
374
|
break if bytes_needed <= module_handle_buffer.size
|
346
375
|
end
|
347
|
-
|
376
|
+
|
348
377
|
handles = module_handle_buffer.unpack("I*")
|
349
378
|
dependencies = handles.select { |handle| handle > 0 }.map do |handle|
|
350
379
|
str = "\x00\x00" * 256
|
351
|
-
modulefilename_length = getmodulefilename.call(
|
380
|
+
modulefilename_length = getmodulefilename.call(
|
381
|
+
[handle].pack("I").unpack1("i"),
|
382
|
+
[str].pack("p").unpack1(pointer_type),
|
383
|
+
[str.size].pack("I").unpack1("i")
|
384
|
+
)
|
352
385
|
str[0, modulefilename_length * 2].force_encoding("UTF-16LE").encode("UTF-8")
|
353
386
|
end
|
354
387
|
|
@@ -535,7 +568,20 @@ options:
|
|
535
568
|
@data_files.select { |file| File.directory? file }.each do |dir|
|
536
569
|
data_files += Dir.glob("#{dir}/**/*").select { |file| File.file? file }
|
537
570
|
end
|
538
|
-
data_files
|
571
|
+
data_files.uniq! { |file| File.expand_path(file) }
|
572
|
+
|
573
|
+
unless options[:virtual_directory]
|
574
|
+
dir_pwd = Dir.pwd.encode(Encoding::UTF_8)
|
575
|
+
virtual_directories = Pathname.new(dir_pwd).ascend.to_a.map(&:to_s)
|
576
|
+
data_files.each do |file|
|
577
|
+
fullpath = File.expand_path(file)
|
578
|
+
next if fullpath.start_with?(rubydir) || Pathname.new(file).absolute?
|
579
|
+
virtual_directories.shift until fullpath.start_with?(virtual_directories.first)
|
580
|
+
end
|
581
|
+
options[:virtual_directory] = relative_path(dir_pwd, virtual_directories.first, "/_neri_virtual_directory_/")
|
582
|
+
puts "virtual_directory: #{options[:virtual_directory]}"
|
583
|
+
end
|
584
|
+
|
539
585
|
if options[:encryption_key]
|
540
586
|
require "digest/sha2"
|
541
587
|
@encryption_key = Digest::SHA2.hexdigest(options[:encryption_key])
|
@@ -543,23 +589,20 @@ options:
|
|
543
589
|
Neri.key = @encryption_key || "0" * 64
|
544
590
|
File.open(datafile, "wb") do |f|
|
545
591
|
pos = 0
|
546
|
-
|
592
|
+
file_informations = data_files.map do |file|
|
547
593
|
fullpath = File.expand_path(file)
|
548
594
|
filename = if fullpath.start_with?(rubydir)
|
549
|
-
relative_path(fullpath, rubydir, "
|
595
|
+
relative_path(fullpath, rubydir, "#{options[:system_dir]}#{File::SEPARATOR}")
|
550
596
|
else
|
551
597
|
file
|
552
598
|
end
|
553
599
|
filedata = [filename, File.size(file), pos].join("\t")
|
554
600
|
nputs_v " - #{filename}:#{File.size(file)} bytes"
|
555
|
-
if File.expand_path(filename).start_with?(Dir.pwd) && filename.include?("..")
|
556
|
-
cd_path = ".#{File.expand_path(filename).delete_prefix(Dir.pwd)}"
|
557
|
-
filedata += "\n" + [cd_path, File.size(file), pos].join("\t")
|
558
|
-
end
|
559
601
|
pos += File.size(file)
|
560
602
|
pos += BLOCK_LENGTH - pos % BLOCK_LENGTH unless pos % BLOCK_LENGTH == 0
|
561
603
|
filedata
|
562
|
-
|
604
|
+
end
|
605
|
+
files_str = file_informations.join("\n").encode(Encoding::UTF_8)
|
563
606
|
|
564
607
|
f.write(format("%#{BLOCK_LENGTH}d", files_str.bytesize))
|
565
608
|
f.write(xor(files_str))
|
@@ -721,6 +764,9 @@ END
|
|
721
764
|
ruby_code = "Neri.key='#{@encryption_key}';" if @encryption_key
|
722
765
|
if options[:datafile]
|
723
766
|
ruby_code += "Neri.datafile='#{system_dir}' + #{unpack_filename(options[:datafile])};"
|
767
|
+
if options[:virtual_directory]
|
768
|
+
ruby_code += "Neri.virtual_directory=#{unpack_filename(options[:virtual_directory])};"
|
769
|
+
end
|
724
770
|
ruby_code += "load #{unpack_filename(File.basename(scriptfile))}"
|
725
771
|
else
|
726
772
|
ruby_code += "load File.expand_path('#{system_dir}' + #{unpack_filename(scriptfile)})"
|
data/lib/neri/runtime.rb
CHANGED
@@ -1,79 +1,91 @@
|
|
1
1
|
require "neri/version"
|
2
|
+
require "pathname"
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
module Kernel
|
5
|
+
unless defined?(neri_original_require)
|
6
|
+
alias neri_original_require require
|
7
|
+
private :neri_original_require
|
8
|
+
end
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
|
10
|
+
unless defined?(neri_original_load)
|
11
|
+
alias neri_original_load load
|
12
|
+
private :neri_original_load
|
13
|
+
end
|
14
|
+
|
15
|
+
def require(feature)
|
16
|
+
Neri.require(feature)
|
17
|
+
end
|
9
18
|
|
10
|
-
def load(file, priv = false)
|
11
|
-
|
19
|
+
def load(file, priv = false)
|
20
|
+
Neri.load(file, priv)
|
21
|
+
end
|
12
22
|
end
|
13
23
|
|
14
24
|
module Neri
|
15
25
|
BLOCK_LENGTH = 32
|
16
26
|
@datafile = nil
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
27
|
+
@file_informations = {}
|
28
|
+
@fullpath_files = {}
|
29
|
+
@virtual_files = {}
|
30
|
+
@virtual_directory = "."
|
21
31
|
@xor = nil
|
22
32
|
|
23
33
|
class << self
|
24
34
|
def datafile=(datafile)
|
25
35
|
@datafile = datafile.encode(Encoding::UTF_8)
|
26
|
-
@system_dir = File.dirname(File.expand_path(@datafile)) + File::SEPARATOR
|
27
36
|
files_length = File.binread(@datafile, BLOCK_LENGTH).to_i
|
28
37
|
files_str = read(files_length, BLOCK_LENGTH)
|
29
38
|
pos = files_length + BLOCK_LENGTH
|
30
39
|
pos += BLOCK_LENGTH - pos % BLOCK_LENGTH unless pos % BLOCK_LENGTH == 0
|
31
40
|
files_str.force_encoding(Encoding::UTF_8)
|
32
|
-
files_str.
|
41
|
+
files_str.each_line do |line|
|
33
42
|
filename, length, offset = line.split("\t")
|
34
|
-
@
|
43
|
+
@file_informations[filename] = [length.to_i, offset.to_i + pos]
|
35
44
|
end
|
36
|
-
@
|
45
|
+
@fullpath_files = @file_informations.transform_keys { |k| File.expand_path(k) }
|
37
46
|
end
|
38
47
|
|
39
48
|
def key=(key)
|
40
|
-
@xor
|
49
|
+
@xor ||= key.scan(/../).map { |a| a.to_i(16) }.pack("c*")
|
41
50
|
end
|
42
51
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
["", ".rb"].each do |ext|
|
48
|
-
tmp_path = path + feature + ext
|
49
|
-
filepath ||= tmp_path if exist_in_datafile?(tmp_path)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
return _neri_orig_require(feature) unless filepath
|
54
|
-
return false if $LOADED_FEATURES.index(filepath)
|
52
|
+
def virtual_directory=(path)
|
53
|
+
@virtual_directory = path
|
54
|
+
@virtual_files = @file_informations.transform_keys { |k| File.expand_path(k, path) }
|
55
|
+
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
def require(feature)
|
58
|
+
feature_path = Pathname.new(feature.encode(Encoding::UTF_8))
|
59
|
+
feature_path = feature_path.sub_ext(".rb") if feature_path.extname == ""
|
60
|
+
return neri_original_require(feature) if feature_path.extname == ".so"
|
61
|
+
|
62
|
+
path_str = if feature_path.absolute? || feature.start_with?(".")
|
63
|
+
path_in_datafile(feature_path)
|
64
|
+
else
|
65
|
+
search_in_load_path(feature_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
return neri_original_require(feature) unless path_str
|
69
|
+
return false if $LOADED_FEATURES.index(path_str)
|
70
|
+
|
71
|
+
code = load_code(path_str)
|
72
|
+
eval(code, TOPLEVEL_BINDING, path_str)
|
73
|
+
$LOADED_FEATURES.push(path_str)
|
59
74
|
true
|
60
75
|
end
|
61
76
|
|
62
77
|
def load(file, priv = false)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
paths.each do |path|
|
67
|
-
filepath ||= path + file if exist_in_datafile?(path + file)
|
68
|
-
end
|
78
|
+
file_path = Pathname.new(file.encode(Encoding::UTF_8))
|
79
|
+
path_str = search_in_load_path(file_path) if file_path.relative? && !file.start_with?(".")
|
80
|
+
path_str ||= path_in_datafile(file_path)
|
69
81
|
|
70
|
-
return
|
82
|
+
return neri_original_load(file, priv) unless path_str
|
71
83
|
|
72
|
-
code = load_code(
|
84
|
+
code = load_code(path_str)
|
73
85
|
if priv
|
74
|
-
Module.new.module_eval(code,
|
86
|
+
Module.new.module_eval(code, path_str)
|
75
87
|
else
|
76
|
-
eval(code, TOPLEVEL_BINDING,
|
88
|
+
eval(code, TOPLEVEL_BINDING, path_str)
|
77
89
|
end
|
78
90
|
true
|
79
91
|
end
|
@@ -84,32 +96,26 @@ module Neri
|
|
84
96
|
|
85
97
|
def file_read(filename, encoding = Encoding::BINARY)
|
86
98
|
filename = filename.encode(Encoding::UTF_8)
|
87
|
-
|
88
|
-
|
89
|
-
length, offset = fullpath_files[File.expand_path(filename)]
|
90
|
-
str = read(length, offset)
|
91
|
-
else
|
92
|
-
str = File.binread(filename)
|
93
|
-
end
|
99
|
+
length, offset = file_information(filename)
|
100
|
+
str = length ? read(length, offset) : File.binread(filename)
|
94
101
|
str.force_encoding(encoding)
|
95
102
|
end
|
96
103
|
|
97
104
|
def files
|
98
|
-
@
|
105
|
+
@file_informations.keys
|
99
106
|
end
|
100
107
|
|
101
108
|
def exist_in_datafile?(filename)
|
102
|
-
|
109
|
+
file_information(filename) != nil
|
103
110
|
end
|
104
111
|
|
105
112
|
private
|
106
113
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
@fullpath_files
|
114
|
+
def file_information(filename)
|
115
|
+
fullpath = File.expand_path(filename)
|
116
|
+
return @fullpath_files[fullpath] if @fullpath_files.key?(fullpath)
|
117
|
+
|
118
|
+
@virtual_files[File.expand_path(filename, @virtual_directory)]
|
113
119
|
end
|
114
120
|
|
115
121
|
def xor(str)
|
@@ -131,11 +137,21 @@ module Neri
|
|
131
137
|
xor(File.binread(@datafile, tmp_length, offset))[0, length]
|
132
138
|
end
|
133
139
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
140
|
+
def search_in_load_path(file_path)
|
141
|
+
$LOAD_PATH.each do |path_str|
|
142
|
+
load_path = Pathname.new(path_str.encode(Encoding::UTF_8))
|
143
|
+
candidate_path_str = path_in_datafile(load_path + file_path)
|
144
|
+
return candidate_path_str if candidate_path_str
|
145
|
+
end
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
|
149
|
+
def path_in_datafile(file_path)
|
150
|
+
fullpath = File.expand_path(file_path.to_s)
|
151
|
+
return fullpath if exist_in_datafile?(fullpath)
|
137
152
|
|
138
|
-
|
153
|
+
virtual_path = File.expand_path(file_path.to_s, @virtual_directory)
|
154
|
+
exist_in_datafile?(virtual_path) ? virtual_path : nil
|
139
155
|
end
|
140
156
|
|
141
157
|
def load_code(file)
|
data/lib/neri/version.rb
CHANGED
data/neri.gemspec
CHANGED
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nodai2hITC
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: win32api
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
11
|
+
date: 2021-12-29 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
27
13
|
description: Neri builds Windows batfile or exefile from Ruby script.
|
28
14
|
email:
|
29
15
|
- nodai2h.itc@gmail.com
|