undll32 0.2.0 → 0.3.4
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 +4 -4
- data/Gemfile.lock +21 -20
- data/LICENSE.txt +1 -1
- data/README.md +9 -3
- data/lib/undll32.rb +198 -23
- data/lib/undll32/version.rb +1 -1
- data/undll32.gemspec +2 -2
- metadata +10 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59acbe9b221095472b7f22916b35b3b1c704248c8c89a0434322e59f20d05435
|
4
|
+
data.tar.gz: 0dcb7e45987554109eb5160d22f93f974264df6e2d0296c37f586cddfc414523
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04f13a36ca8ac4eaeb8aa391e99dfd955ddff22b9a506af1ec2a591137ce7ec4ee85f7e8985bd37f7626111cf511af327d24850e2775f51236712dcf67890731
|
7
|
+
data.tar.gz: 37acf71e14b0eabcf9408d9c3ccc889891cf5a133c52123b1765f77fbac6ed76c3fc58fe7c3340bdc2e1c4f81e747e2540ee28687f681abb71262affabaf9407
|
data/Gemfile.lock
CHANGED
@@ -1,20 +1,21 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
undll32 (0.
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
rake (
|
10
|
-
|
11
|
-
PLATFORMS
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
undll32 (0.3.4)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
rake (13.0.3)
|
10
|
+
|
11
|
+
PLATFORMS
|
12
|
+
ruby
|
13
|
+
x64-mingw32
|
14
|
+
|
15
|
+
DEPENDENCIES
|
16
|
+
bundler (~> 2.2.9)
|
17
|
+
rake (~> 13.0)
|
18
|
+
undll32!
|
19
|
+
|
20
|
+
BUNDLED WITH
|
21
|
+
2.2.9
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -22,9 +22,15 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
-
|
26
|
-
|
27
|
-
|
25
|
+
- Command line:
|
26
|
+
```
|
27
|
+
undll32 User32,MessageBox 0 hello world 0
|
28
|
+
ruby -rundll32 -e Undll32.exe -- User32,MessageBox 0 hello world 0
|
29
|
+
```
|
30
|
+
- Program:
|
31
|
+
```ruby
|
32
|
+
Undll32.run('User32', 'MessageBox', 0, 'hello', 'world', 0)
|
33
|
+
```
|
28
34
|
|
29
35
|
## Development
|
30
36
|
|
data/lib/undll32.rb
CHANGED
@@ -1,13 +1,57 @@
|
|
1
1
|
require "undll32/version"
|
2
|
-
require '
|
2
|
+
require 'fiddle/import'
|
3
3
|
|
4
4
|
##
|
5
5
|
# Undll32
|
6
6
|
# replacement of Windows' rundll32.exe
|
7
7
|
module Undll32
|
8
8
|
|
9
|
+
class Win32API
|
10
|
+
DLL = {}
|
11
|
+
TYPEMAP = {
|
12
|
+
'0' => Fiddle::TYPE_VOID,
|
13
|
+
'S' => Fiddle::TYPE_VOIDP,
|
14
|
+
'I' => Fiddle::TYPE_LONG,
|
15
|
+
}
|
16
|
+
POINTER_TYPE =
|
17
|
+
Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
|
18
|
+
WIN32_TYPES = 'VPpNnLlIi'
|
19
|
+
DL_TYPES = '0SSI'
|
20
|
+
|
21
|
+
def initialize(dllname, func, import, export = '0', calltype = :stdcall)
|
22
|
+
@proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1')
|
23
|
+
import = @proto.chars.map { |e| TYPEMAP[e.tr(WIN32_TYPES, DL_TYPES)] }
|
24
|
+
export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)]
|
25
|
+
calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype]
|
26
|
+
handle = DLL[dllname] ||=
|
27
|
+
begin
|
28
|
+
Fiddle.dlopen(dllname)
|
29
|
+
rescue Fiddle::DLError
|
30
|
+
raise unless File.extname(dllname).empty?
|
31
|
+
Fiddle.dlopen("#{dllname}.dll")
|
32
|
+
end
|
33
|
+
@func = Fiddle::Function.new(handle[func], import, export, calltype)
|
34
|
+
rescue Fiddle::DLError => e
|
35
|
+
raise LoadError, e.message, e.backtrace
|
36
|
+
end
|
37
|
+
|
38
|
+
def call(*args)
|
39
|
+
import = @proto.split('')
|
40
|
+
args.each_with_index do |x, i|
|
41
|
+
if import[i] == 'S'
|
42
|
+
args[i], = [x == 0 ? nil : x].pack('p').unpack(POINTER_TYPE)
|
43
|
+
end
|
44
|
+
args[i], = [x].pack('I').unpack('i') if import[i] == 'I'
|
45
|
+
end
|
46
|
+
ret, = @func.call(*args)
|
47
|
+
ret || 0
|
48
|
+
end
|
49
|
+
|
50
|
+
alias Call call
|
51
|
+
end
|
52
|
+
|
9
53
|
##
|
10
|
-
# represents a string/struct
|
54
|
+
# represents a string/struct.
|
11
55
|
# Buffer.new({ :x => :L, :y => 4 })
|
12
56
|
# Buffer.new([ :L, 4 ])
|
13
57
|
# Buffer.new(:L)
|
@@ -15,6 +59,8 @@ module Undll32
|
|
15
59
|
# buffer.buffer => "\0\0\0\0"
|
16
60
|
# buffer.unpack => 0
|
17
61
|
class Buffer
|
62
|
+
attr_accessor :struct
|
63
|
+
|
18
64
|
def initialize struct
|
19
65
|
case struct
|
20
66
|
when Hash, Array, Symbol, Integer
|
@@ -33,22 +79,63 @@ module Undll32
|
|
33
79
|
_unpack @struct
|
34
80
|
end
|
35
81
|
|
36
|
-
def
|
82
|
+
def load v
|
83
|
+
@_i = 0
|
84
|
+
_load @struct, v
|
85
|
+
unpack
|
86
|
+
end
|
87
|
+
|
88
|
+
def _load x, v
|
37
89
|
case x
|
38
90
|
when Integer
|
39
|
-
|
91
|
+
return @_i += x if v.nil?
|
92
|
+
unless String === v
|
93
|
+
raise ArgumentError, "expected str, got #{v}"
|
94
|
+
end
|
95
|
+
x = [x, v.length].min
|
96
|
+
buffer[(@_i += x) - x, x] = v[0, x]
|
40
97
|
when Symbol
|
41
98
|
n = { C: 1, S: 2, L: 4, Q: 8 }[x]
|
42
99
|
if n.nil?
|
43
100
|
raise ArgumentError, "expected CSLQ, got #{x}"
|
44
101
|
end
|
102
|
+
return @_i += n if v.nil?
|
103
|
+
unless Integer === v
|
104
|
+
raise ArgumentError, "expected int, got #{v}"
|
105
|
+
end
|
106
|
+
buffer[(@_i += n) - n, n] = [v].pack("#{x}")
|
107
|
+
when Array
|
108
|
+
return x.each { |a| _load a, nil } if v.nil?
|
109
|
+
unless Array === v and v.size == x.size
|
110
|
+
raise ArgumentError, "expected array[#{x.size}], got #{v}"
|
111
|
+
end
|
112
|
+
x.zip(v) { |a, b| _load a, b }
|
113
|
+
when Hash
|
114
|
+
return x.each { |k, y| _load y, nil } if v.nil?
|
115
|
+
unless Hash === v
|
116
|
+
raise ArgumentError, "expected hash, got #{v}"
|
117
|
+
end
|
118
|
+
x.each { |k, y| _load y, v[k] }
|
119
|
+
else
|
120
|
+
raise ArgumentError, "expected hash, array, sym, int, got #{x}"
|
121
|
+
end
|
122
|
+
ensure
|
123
|
+
$@.shift if $@
|
124
|
+
end
|
125
|
+
|
126
|
+
def _unpack x
|
127
|
+
case x
|
128
|
+
when Integer
|
129
|
+
buffer[(@_i += x) - x, x].sub(/\0+$/, '')
|
130
|
+
when Symbol
|
131
|
+
n = { C: 1, S: 2, L: 4, Q: 8 }[x]
|
45
132
|
buffer[(@_i += n) - n, n].unpack1("#{x}")
|
46
133
|
when Array
|
47
134
|
x.map { |e| _unpack e }
|
48
135
|
when Hash
|
49
136
|
Hash[x.map { |k, v| [k, _unpack(v)] }]
|
50
137
|
else
|
51
|
-
raise ArgumentError, "expected hash, array, sym, int, got #{
|
138
|
+
raise ArgumentError, "expected hash, array, sym, int, got #{x}"
|
52
139
|
end
|
53
140
|
ensure
|
54
141
|
$@.shift if $@
|
@@ -69,50 +156,135 @@ module Undll32
|
|
69
156
|
when Hash
|
70
157
|
_buffer x.values
|
71
158
|
else
|
72
|
-
raise ArgumentError, "expected hash, array, sym, int, got #{
|
159
|
+
raise ArgumentError, "expected hash, array, sym, int, got #{x}"
|
73
160
|
end
|
74
161
|
ensure
|
75
162
|
$@.shift if $@
|
76
163
|
end
|
164
|
+
|
165
|
+
def self.from_array code
|
166
|
+
unless code =~ /^\[[CSLQ]+\]$/
|
167
|
+
raise ArgumentError, "expected [CSLQ], got #{code}"
|
168
|
+
end
|
169
|
+
return new(code[1..-2].chars.map(&:to_sym))
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.from_size code
|
173
|
+
m = code.match(/^\:(?<size>[^=]+)=?(?<value>.+)?$/)
|
174
|
+
if m.nil?
|
175
|
+
raise ArgumentError, "expected <number> or CSLQ, got #{code}"
|
176
|
+
end
|
177
|
+
if m[:size] =~ /^[CSLQ]+$/
|
178
|
+
s = m[:size].chars.map(&:to_sym)
|
179
|
+
if s.size == 1
|
180
|
+
return new(s[0]).tap { |b| b.load(m[:value].to_i) if m[:value] }
|
181
|
+
else
|
182
|
+
b = new(s)
|
183
|
+
b.load(m[:value].split(':').map(&:to_i)) if m[:value]
|
184
|
+
return b
|
185
|
+
end
|
186
|
+
end
|
187
|
+
if (n = m[:size].to_i)
|
188
|
+
return new(n).tap { |b| b.load(m[:value]) if m[:value] }
|
189
|
+
end
|
190
|
+
raise ArgumentError, "expected <number> or CSLQ, got #{code}"
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.next_placeholder
|
194
|
+
@_placeholder_counter ||= 0
|
195
|
+
"__#{@_placeholder_counter += 1}__"
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.from_struct code
|
199
|
+
default = {}
|
200
|
+
# code := '{' [name] [:type] [=value] [,...] '}'
|
201
|
+
env, keys, key = [], [], ''
|
202
|
+
seq = code.scan /\w+|\:[[:digit:]]+|\:[CSLQ:]+|=[^,\}]+|./
|
203
|
+
ret = while (token = seq.shift)
|
204
|
+
case token[0]
|
205
|
+
when '{'
|
206
|
+
keys.push(key.to_sym) unless key.empty?
|
207
|
+
env.push({})
|
208
|
+
key = ''
|
209
|
+
when '}'
|
210
|
+
env[-1][key.to_sym] = :L unless key.empty?
|
211
|
+
x = env.pop
|
212
|
+
break x if env.empty?
|
213
|
+
env[-1][keys.pop] = x
|
214
|
+
key = ''
|
215
|
+
when ':'
|
216
|
+
token << seq.shift if seq.first&.start_with?('=')
|
217
|
+
b = from_size(token)
|
218
|
+
key = next_placeholder if key.empty?
|
219
|
+
env[-1][key.to_sym] = b.struct
|
220
|
+
d = default
|
221
|
+
keys.each { |k| d[k] ||= {}; d = d[k] }
|
222
|
+
d[key.to_sym] = b.unpack
|
223
|
+
key = ''
|
224
|
+
when '='
|
225
|
+
e = token[1..-1]
|
226
|
+
e = Integer(e) rescue nil
|
227
|
+
type = Integer === e ? :L : (e.length + 1)
|
228
|
+
env[-1][key.to_sym] = type
|
229
|
+
d = default
|
230
|
+
keys.each { |k| d[k] ||= {}; d = d[k] }
|
231
|
+
if Integer === type
|
232
|
+
e = "\"#{e}\"".undump rescue e.undump
|
233
|
+
end
|
234
|
+
d[key.to_sym] = e
|
235
|
+
key = ''
|
236
|
+
when ','
|
237
|
+
next if key.empty?
|
238
|
+
env[-1][key.to_sym] = :L
|
239
|
+
key = ''
|
240
|
+
else
|
241
|
+
key << token
|
242
|
+
end
|
243
|
+
end
|
244
|
+
if ret.nil?
|
245
|
+
raise ArgumentError, 'expected }, got end-of-input'
|
246
|
+
end
|
247
|
+
new(ret).tap { |b| b.load(default) }
|
248
|
+
end
|
249
|
+
|
250
|
+
def self.from code
|
251
|
+
return from_array(code) if code.start_with?('[')
|
252
|
+
return from_size(code) if code.start_with?(':')
|
253
|
+
code = "{#{code}}" unless code.start_with?('{')
|
254
|
+
return from_struct(code)
|
255
|
+
end
|
77
256
|
end
|
78
257
|
|
79
258
|
# Undll32.run 'user32', 'MessageBox', 0, 'hello', 'world', 0
|
259
|
+
# Undll32.run 'user32', 'GetCursorPos', Buffer.new({:x => :L, :y => :L})
|
260
|
+
# Undll32.run 'user32', 'GetCursorPos', Buffer.from('x,y')
|
80
261
|
def self.run(dll, func, *args)
|
81
262
|
types = args.map { |e| Integer === e ? 'L' : 'p' }
|
82
263
|
input = args.map { |e| Buffer === e ? e.buffer : e }
|
83
264
|
Win32API.new(dll, func, types, 'i').call(*input)
|
84
265
|
end
|
85
266
|
|
86
|
-
def self.parse xs
|
87
|
-
case x = xs.shift
|
88
|
-
when ':' then Buffer.new xs.shift.to_i
|
89
|
-
when '[' then Buffer.new xs.shift.chars.map(&:to_sym)
|
90
|
-
when '{'
|
91
|
-
x = Hash[xs.each_slice(4).map { |k, _, v, _| [k.to_sym, v.to_sym] }]
|
92
|
-
Buffer.new x
|
93
|
-
else
|
94
|
-
raise ArgumentError, "expected : [ {, got #{x}"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
267
|
def self.exe(argv=ARGV)
|
99
268
|
return help if ARGV.include? '-h' or ARGV.include? '--help'
|
100
269
|
dllfunc, *args = argv
|
101
270
|
return help if dllfunc.nil?
|
102
271
|
dll, func = dllfunc.split(',')
|
103
272
|
return help if func.nil?
|
104
|
-
|
273
|
+
dll += '.dll' unless dll.end_with? '.dll'
|
274
|
+
realpath = File.expand_path dll
|
275
|
+
dll = realpath if File.exist? realpath
|
276
|
+
args.map! do |e|
|
105
277
|
e = e.dup
|
106
278
|
if e.start_with?('+')
|
107
279
|
e.slice!(0)
|
108
280
|
next e if e.start_with?('+')
|
109
|
-
|
281
|
+
Buffer.from(e)
|
110
282
|
else
|
111
283
|
n = Integer(e) rescue nil
|
112
284
|
next n if n
|
113
285
|
e
|
114
286
|
end
|
115
|
-
|
287
|
+
end
|
116
288
|
ret = run(dll, func, *args)
|
117
289
|
args.each { |e| pp e.unpack if Buffer === e }
|
118
290
|
ret
|
@@ -126,10 +298,10 @@ module Undll32
|
|
126
298
|
EXAMPLE
|
127
299
|
undll32 user32,MessageBox 0 hello world 0
|
128
300
|
undll32 user32,GetCursorPos +[LL]
|
129
|
-
undll32 user32,GetCursorPos +
|
301
|
+
undll32 user32,GetCursorPos +x,y
|
130
302
|
undll32 user32,GetCursorPos +:8 # will be converted to string
|
131
303
|
|
132
|
-
|
304
|
+
ARGUMENTS
|
133
305
|
0 => (Integer) 0
|
134
306
|
str => 'str'
|
135
307
|
+0 => '0'
|
@@ -138,6 +310,9 @@ module Undll32
|
|
138
310
|
+{x:L,y:L} => Buffer.new({:x => :L, :y => :L})
|
139
311
|
+:256 => Buffer.new(256)
|
140
312
|
|
313
|
+
VERSION
|
314
|
+
#{VERSION}
|
315
|
+
|
141
316
|
USAGE
|
142
317
|
end
|
143
318
|
end
|
data/lib/undll32/version.rb
CHANGED
data/undll32.gemspec
CHANGED
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ["lib"]
|
25
25
|
|
26
|
-
spec.add_development_dependency "bundler", "~>
|
27
|
-
spec.add_development_dependency "rake", "~>
|
26
|
+
spec.add_development_dependency "bundler", "~> 2.2.9"
|
27
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
28
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: undll32
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hyrious
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.2.9
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.2.9
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '13.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '13.0'
|
41
41
|
description: undll32 User32,MessageBoxA 0 hello world 0
|
42
42
|
email:
|
43
43
|
- hyrious@outlook.com
|
@@ -62,7 +62,7 @@ homepage: https://github.com/hyrious/undll32
|
|
62
62
|
licenses:
|
63
63
|
- MIT
|
64
64
|
metadata: {}
|
65
|
-
post_install_message:
|
65
|
+
post_install_message:
|
66
66
|
rdoc_options: []
|
67
67
|
require_paths:
|
68
68
|
- lib
|
@@ -77,9 +77,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
77
|
- !ruby/object:Gem::Version
|
78
78
|
version: '0'
|
79
79
|
requirements: []
|
80
|
-
|
81
|
-
|
82
|
-
signing_key:
|
80
|
+
rubygems_version: 3.2.9
|
81
|
+
signing_key:
|
83
82
|
specification_version: 4
|
84
83
|
summary: Windows rundll32 replacement.
|
85
84
|
test_files: []
|