Skip to content

Commit 0177e51

Browse files
committed
Finish obfu specs and use rig
1 parent 6ab8502 commit 0177e51

File tree

2 files changed

+134
-38
lines changed

2 files changed

+134
-38
lines changed

lib/rex/exploitation/powershell/obfu.rb

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,6 @@ module Powershell
99

1010
module Obfu
1111

12-
#
13-
# Create hash of string substitutions
14-
#
15-
# @param strings [Array] array of strings to generate unique names
16-
#
17-
# @return [Hash] map of strings with new unique names
18-
def sub_map_generate(strings)
19-
map = {}
20-
strings.flatten.each do |str|
21-
@rig.init_var(str)
22-
map[str] = @rig[str]
23-
end
24-
25-
map
26-
end
27-
2812
#
2913
# Remove comments
3014
#
@@ -34,6 +18,8 @@ def strip_comments
3418
code.gsub!(/<#(.*?)#>/m,'')
3519
# Single line
3620
code.gsub!(/^\s*#(?!.*region)(.*$)/i,'')
21+
22+
code
3723
end
3824

3925
#
@@ -45,6 +31,8 @@ def strip_empty_lines
4531
code.gsub!(/[\r\n]+/,"\r\n")
4632
# UNIX EOL
4733
code.gsub!(/[\n]+/,"\n")
34+
35+
code
4836
end
4937

5038
#
@@ -54,6 +42,8 @@ def strip_empty_lines
5442
# @return [String] code with whitespace stripped
5543
def strip_whitespace
5644
code.gsub!(/\s+/,' ')
45+
46+
code
5747
end
5848

5949
#
@@ -62,11 +52,11 @@ def strip_whitespace
6252
# @return [String] code with variable names replaced with unique values
6353
def sub_vars
6454
# Get list of variables, remove reserved
65-
vars = get_var_names
66-
# Create map, sub key for val
67-
sub_map_generate(vars).each do |var,sub|
68-
code.gsub!(var,sub)
55+
get_var_names.each do |var,sub|
56+
code.gsub!(var, "$#{@rig.init_var(var)}")
6957
end
58+
59+
code
7060
end
7161

7262
#
@@ -76,10 +66,11 @@ def sub_vars
7666
# values
7767
def sub_funcs
7868
# Find out function names, make map
79-
# Sub map keys for values
80-
sub_map_generate(get_func_names).each do |var,sub|
81-
code.gsub!(var,sub)
69+
get_func_names.each do |var, sub|
70+
code.gsub!(var, @rig.init_var(var))
8271
end
72+
73+
code
8374
end
8475

8576
#
@@ -88,7 +79,7 @@ def sub_funcs
8879
# @return [String] code with standard substitution methods applied
8980
def standard_subs(subs = %w{strip_comments strip_whitespace sub_funcs sub_vars} )
9081
# Save us the trouble of breaking injected .NET and such
91-
subs.delete('strip_whitespace') unless string_literals.empty?
82+
subs.delete('strip_whitespace') unless get_string_literals.empty?
9283
# Run selected modifiers
9384
subs.each do |modifier|
9485
self.send(modifier)

spec/lib/rex/exploitation/powershell/obfu_spec.rb

Lines changed: 119 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@
1010
function Find-4624Logons
1111
{
1212
13+
<#
14+
15+
multiline_comment
16+
17+
#>
18+
\r\n\r\n\r\n
19+
\r\n
20+
21+
lots \t of whitespace
22+
23+
\n\n\n\n\n
24+
\n\n
25+
26+
27+
# single_line_comment1
28+
# single_line_comment2
29+
#
30+
# single_line_comment3
1331
if (-not ($NewLogonAccountDomain -cmatch \"NT\\sAUTHORITY\" -or $NewLogonAccountDomain -cmatch \"Window\\sManager\"))
1432
{
1533
$Key = $AccountName + $AccountDomain + $NewLogonAccountName + $NewLogonAccountDomain + $LogonType + $WorkstationName + $SourceNetworkAddress + $SourcePort
@@ -48,6 +66,25 @@
4866
"""
4967
function Find-4624Logons
5068
{
69+
70+
<#
71+
72+
multiline_comment
73+
74+
#>
75+
\r\n\r\n\r\n
76+
\r\n
77+
78+
lots \t of whitespace
79+
80+
\n\n\n\n\n
81+
\n\n
82+
83+
84+
# single_line_comment1
85+
# single_line_comment2
86+
#
87+
# single_line_comment3
5188
$some_literal = @\"
5289
using System;
5390
using System.Runtime.InteropServices;
@@ -104,24 +141,92 @@
104141
Rex::Exploitation::Powershell::Script.new(example_script_without_literal)
105142
end
106143

107-
describe "::sub_map_generate" do
108-
it 'should return some unique variable names' do
109-
map = subject.sub_map_generate(['blah','parp'])
110-
map.should be
111-
map.should be_kind_of Hash
112-
map.empty?.should be_false
113-
map.should eq map.uniq
144+
describe "::strip_comments" do
145+
it 'should strip a multiline comment' do
146+
subject.strip_comments
147+
subject.code.should be
148+
subject.code.should be_kind_of String
149+
subject.code.include?('comment').should be_false
114150
end
115151

116-
it 'should not match upper or lowercase reserved names' do
117-
initial_vars = subject.get_var_names
118-
subject.code << "\r\n$SHELLID"
119-
subject.code << "\r\n$ShellId"
120-
subject.code << "\r\n$shellid"
121-
after_vars = subject.get_var_names
122-
initial_vars.should eq after_vars
152+
it 'should strip a single line comment' do
153+
subject.strip_comments
154+
subject.code.should be
155+
subject.code.should be_kind_of String
156+
subject.code.include?('#').should be_false
123157
end
124158
end
125159

160+
describe "::strip_empty_lines" do
161+
it 'should strip extra windows new lines' do
162+
subject.strip_empty_lines
163+
subject.code.should be
164+
subject.code.should be_kind_of String
165+
res = (subject.code =~ /\r\n\r\n/)
166+
res.should be_false
167+
end
168+
169+
it 'should strip extra unix new lines' do
170+
subject.strip_empty_lines
171+
subject.code.should be
172+
subject.code.should be_kind_of String
173+
res = (subject.code =~ /\n\n/)
174+
res.should be_false
175+
end
176+
end
177+
178+
describe "::strip_whitespace" do
179+
it 'should strip additional whitespace' do
180+
subject.strip_whitespace
181+
subject.code.should be
182+
subject.code.should be_kind_of String
183+
subject.code.include?('lots of whitespace').should be_true
184+
end
185+
end
186+
187+
describe "::sub_vars" do
188+
it 'should replace variables with unique names' do
189+
subject.sub_vars
190+
subject.code.should be
191+
subject.code.should be_kind_of String
192+
subject.code.include?('$kernel32').should be_false
193+
subject.code.include?('$Logon').should be_false
194+
end
195+
end
196+
197+
describe "::sub_funcs" do
198+
it 'should replace functions with unique names' do
199+
subject.sub_funcs
200+
subject.code.should be
201+
subject.code.should be_kind_of String
202+
subject.code.include?('Find-4624Logons').should be_false
203+
end
204+
end
205+
206+
describe "::standard_subs" do
207+
it 'should run all substitutions on a script with no literals' do
208+
subject_no_literal.standard_subs
209+
subject_no_literal.code.should be
210+
subject_no_literal.code.should be_kind_of String
211+
subject_no_literal.code.include?('Find-4624Logons').should be_false
212+
subject_no_literal.code.include?('lots of whitespace').should be_true
213+
subject_no_literal.code.include?('$kernel32').should be_false
214+
subject_no_literal.code.include?('comment').should be_false
215+
res = (subject_no_literal.code =~ /\r\n\r\n/)
216+
res.should be_false
217+
end
218+
219+
it 'should run all substitutions except strip whitespace when literals are present' do
220+
subject.standard_subs
221+
subject.code.should be
222+
subject.code.should be_kind_of String
223+
subject.code.include?('Find-4624Logons').should be_false
224+
subject.code.include?('lots of whitespace').should be_false
225+
subject.code.include?('$kernel32').should be_false
226+
subject.code.include?('comment').should be_false
227+
res = (subject.code =~ /\r\n\r\n/)
228+
res.should be_false
229+
end
230+
end
126231
end
127232

0 commit comments

Comments
 (0)