CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/payloads/singles/windows/messagebox.rb
Views: 11765
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
module MetasploitModule
7
8
CachedSize = 272
9
10
include Msf::Payload::Windows
11
include Msf::Payload::Single
12
13
def initialize(info = {})
14
super(merge_info(info,
15
'Name' => 'Windows MessageBox',
16
'Description' => 'Spawns a dialog via MessageBox using a customizable title, text & icon',
17
'Author' =>
18
[
19
'corelanc0d3r <peter.ve[at]corelan.be>', # original payload module
20
'jduck' # some ruby factoring
21
],
22
'License' => MSF_LICENSE,
23
'Platform' => 'win',
24
'Arch' => ARCH_X86
25
))
26
27
# Register MessageBox options
28
register_options(
29
[
30
OptString.new('TITLE', [ true, "Messagebox Title (max 255 chars)", "MessageBox" ], max_length: 255),
31
OptString.new('TEXT', [ true, "Messagebox Text (max 255 chars)", "Hello, from MSF!" ], max_length: 255),
32
OptString.new('ICON', [ true, "Icon type can be NO, ERROR, INFORMATION, WARNING or QUESTION", "NO" ])
33
])
34
end
35
36
#
37
# Construct the payload
38
#
39
def generate(_opts = {})
40
41
strTitle = datastore['TITLE'] + "X"
42
if (strTitle.length < 1)
43
raise ArgumentError, "You must specify a title"
44
end
45
46
strText = datastore['TEXT'] + "X"
47
if (strText.length < 1)
48
raise ArgumentError, "You must specify the text of the MessageBox"
49
end
50
51
# exitfunc process or thread ?
52
stackspace = "0x04"
53
funchash = ""
54
doexitseh = ""
55
case datastore['EXITFUNC'].upcase.strip
56
when 'PROCESS'
57
stackspace = "0x08"
58
funchash = "0x73E2D87E"
59
when 'THREAD'
60
stackspace = "0x08"
61
funchash = "0x60E0CEEF"
62
end
63
64
# create exit routine for process / thread
65
getexitfunc = <<EOS
66
;base address of kernel32 will be at esp,
67
mov ebx,#{funchash}
68
xchg ebx, dword [esp]
69
push edx
70
call find_function
71
;store function address at ebx+08
72
mov [ebp+0x8],eax
73
EOS
74
75
doexit = <<EOS
76
xor eax,eax ;zero out eax
77
push eax ;put 0 on stack
78
call [ebp+8] ;ExitProcess/Thread(0)
79
EOS
80
81
# if exit is set to seh or none, overrule
82
if datastore['EXITFUNC'].upcase.strip == "SEH"
83
# routine to exit via exception
84
doexit = <<EOS
85
xor eax,eax
86
call eax
87
EOS
88
getexitfunc = ''
89
elsif datastore['EXITFUNC'].upcase.strip == "NONE"
90
doexit = <<-EOS
91
nop
92
EOS
93
getexitfunc = ''
94
end
95
96
# Generate code to get ptr to Title
97
marker_idx = strTitle.length - 1
98
strPushTitle = string_to_pushes(strTitle, marker_idx)
99
# generate code to write null byte
100
strWriteTitleNull = "xor ebx,ebx\n\tmov [esp+0x#{marker_idx.to_s(16)}],bl\n\tmov ebx,esp\n\t"
101
102
#================Process Text===============================
103
marker_idx = strText.length - 1
104
strPushText = string_to_pushes(strText, marker_idx)
105
strWriteTextNull = "xor ecx,ecx\n\tmov [esp+0x#{marker_idx.to_s(16)}],cl\n\tmov ecx,esp\n\t"
106
107
# generate code to set messagebox icon
108
setstyle = "push edx\n\t"
109
case datastore['ICON'].upcase.strip
110
#default = NO
111
when 'ERROR'
112
setstyle = "push 0x10\n\t"
113
when 'QUESTION'
114
setstyle = "push 0x20\n\t"
115
when 'WARNING'
116
setstyle = "push 0x30\n\t"
117
when 'INFORMATION'
118
setstyle = "push 0x40\n\t"
119
end
120
121
#create actual payload
122
payload_data = <<EOS
123
;getpc routine
124
fldpi
125
fstenv [esp-0xc]
126
xor edx,edx
127
mov dl,0x77 ;offset to start_main
128
129
;get kernel32
130
xor ecx,ecx
131
mov esi, [fs:ecx + 0x30]
132
mov esi, [esi + 0x0C]
133
mov esi, [esi + 0x1C]
134
next_module:
135
mov eax, [esi + 0x08]
136
mov edi, [esi + 0x20]
137
mov esi, [esi]
138
cmp [edi + 12*2], cl
139
jne next_module
140
141
pop ecx
142
add ecx,edx
143
jmp ecx ;jmp start_main
144
145
find_function:
146
pushad ;save all registers
147
mov ebp, [esp + 0x24] ;put base address of module that is being loaded in ebp
148
mov eax, [ebp + 0x3c] ;skip over MSDOS header
149
mov edx, [ebp + eax + 0x78] ;go to export table and put relative address in edx
150
add edx, ebp ;add base address to it.
151
;edx = absolute address of export table
152
mov ecx, [edx + 0x18] ;set up counter ECX
153
;(how many exported items are in array ?)
154
mov ebx, [edx + 0x20] ;put names table relative offset in ebx
155
add ebx, ebp ;add base address to it.
156
;ebx = absolute address of names table
157
158
find_function_loop:
159
jecxz find_function_finished ;if ecx=0, then last symbol has been checked.
160
;(should never happen)
161
;unless function could not be found
162
dec ecx ;ecx=ecx-1
163
mov esi, [ebx + ecx * 4] ;get relative offset of the name associated
164
;with the current symbol
165
;and store offset in esi
166
add esi, ebp ;add base address.
167
;esi = absolute address of current symbol
168
169
compute_hash:
170
xor edi, edi ;zero out edi
171
xor eax, eax ;zero out eax
172
cld ;clear direction flag.
173
;will make sure that it increments instead of
174
;decrements when using lods*
175
176
compute_hash_again:
177
lodsb ;load bytes at esi (current symbol name)
178
;into al, + increment esi
179
test al, al ;bitwise test :
180
;see if end of string has been reached
181
jz compute_hash_finished ;if zero flag is set = end of string reached
182
ror edi, 0xd ;if zero flag is not set, rotate current
183
;value of hash 13 bits to the right
184
add edi, eax ;add current character of symbol name
185
;to hash accumulator
186
jmp compute_hash_again ;continue loop
187
188
compute_hash_finished:
189
190
find_function_compare:
191
cmp edi, [esp + 0x28] ;see if computed hash matches requested hash
192
; (at esp+0x28)
193
;edi = current computed hash
194
;esi = current function name (string)
195
jnz find_function_loop ;no match, go to next symbol
196
mov ebx, [edx + 0x24] ;if match : extract ordinals table
197
;relative offset and put in ebx
198
add ebx, ebp ;add base address.
199
;ebx = absolute address of ordinals address table
200
mov cx, [ebx + 2 * ecx] ;get current symbol ordinal number (2 bytes)
201
mov ebx, [edx + 0x1c] ;get address table relative and put in ebx
202
add ebx, ebp ;add base address.
203
;ebx = absolute address of address table
204
mov eax, [ebx + 4 * ecx] ;get relative function offset from its ordinal
205
;and put in eax
206
add eax, ebp ;add base address.
207
;eax = absolute address of function address
208
mov [esp + 0x1c], eax ;overwrite stack copy of eax so popad
209
;will return function address in eax
210
find_function_finished:
211
popad ;restore original registers.
212
;eax will contain function address
213
ret
214
215
start_main:
216
mov dl,#{stackspace}
217
sub esp,edx ;allocate space on stack
218
mov ebp,esp ;set ebp as frame ptr for relative offset
219
mov edx,eax ;save base address of kernel32 in edx
220
221
push 0xEC0E4E8E ;get LoadLibrary function ptr
222
push edx
223
call find_function
224
;put function address on stack (ebx+04)
225
mov [ebp+0x4],eax
226
#{getexitfunc} ;optionally get selected exit function ptr
227
228
;put pointer to string user32.dll to stack
229
push 0x41206c6c
230
push 0x642e3233
231
push 0x72657375 ;user32.dll
232
xor bl,bl ;make sure we have a null byte
233
mov [esp+0xA],bl ;null byte
234
mov esi,esp ;put pointer to string on top of stack
235
push esi
236
call [ebp+0x4] ;call LoadLibrary
237
; base address of user32.dll is now in eax (if loaded correctly)
238
mov edx,eax ;put ptr in edx
239
push eax ;put it on stack as well
240
;find the MessageBoxA function
241
mov ebx, 0xBC4DA2A8
242
xchg ebx, dword [esp] ;esp = base address of user32.dll
243
push edx
244
call find_function
245
;function address should be in eax now
246
;we'll keep it there
247
;get pointer to title
248
#{strPushTitle}
249
#{strWriteTitleNull} ;ebx will point to title
250
;get pointer to text
251
#{strPushText}
252
#{strWriteTextNull} ;ecx will point to text
253
254
;now push parameters to the stack
255
xor edx,edx ;zero out edx
256
#{setstyle} ;set button/iconstyle on stack
257
push ebx ;put pointer to Title on stack
258
push ecx ;put pointer to Text on stack
259
push edx ;put 0 on stack (hWnd)
260
call eax ;call MessageBoxA(hWnd,Text,Title,Style)
261
262
;EXITFUNC
263
#{doexit}
264
EOS
265
self.assembly = payload_data
266
super
267
end
268
269
#
270
# Turn the provided string into a serious of pushes
271
#
272
def string_to_pushes(str, marker_idx)
273
# Align string to 4 bytes
274
rem = (marker_idx+1) % 4
275
if (rem > 0)
276
str << " " * (4 - rem)
277
end
278
279
# string is now 4 byte aligned and ends with 'X' at index 'marker_idx'
280
281
# push string to stack, starting at the back
282
pushes = ''
283
while (str.length > 0)
284
four = str.slice!(-4, 4)
285
dw = four.unpack('V').first
286
pushes << "push 0x%x\n\t" % dw
287
end
288
289
pushes
290
end
291
end
292
293