Skip to content

Commit 255e792

Browse files
author
HD Moore
committed
Fix host-endian related pack errors. See below for details.
Ruby treats endianess in pack operators in the opposite way of python. For example, using pack('<I') actually ignores the endianess specifier. These need to be 'I<' or better yet, 'V'. The endian specify must occur after the pack specifier and multiple instances in meterpreter and exe generation were broken in thier usage. The summary: Instead of I/L or I< use V Instead of I/L or I> use N For Q, you need to always use Q< (LE) or Q> (BE) For c/s/l/i and other lowercase variants, you probably dont need or want a *signed* value, so stick with vV nN and cC.
1 parent a60dfda commit 255e792

File tree

5 files changed

+25
-25
lines changed

5 files changed

+25
-25
lines changed

lib/msf/util/exe.rb

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -340,22 +340,22 @@ def self.to_winpe_only(framework, code, opts={}, arch="x86")
340340

341341
# look for section with entry point
342342
sections_header.each do |sec|
343-
virtualAddress = sec[1][virtualAddress_offset,0x4].unpack('L')[0]
344-
sizeOfRawData = sec[1][sizeOfRawData_offset,0x4].unpack('L')[0]
345-
characteristics = sec[1][characteristics_offset,0x4].unpack('L')[0]
343+
virtualAddress = sec[1][virtualAddress_offset,0x4].unpack('V')[0]
344+
sizeOfRawData = sec[1][sizeOfRawData_offset,0x4].unpack('V')[0]
345+
characteristics = sec[1][characteristics_offset,0x4].unpack('V')[0]
346346

347347
if (virtualAddress...virtualAddress+sizeOfRawData).include?(addressOfEntryPoint)
348-
importsTable = pe.hdr.opt.DataDirectory[8..(8+4)].unpack('L')[0]
348+
importsTable = pe.hdr.opt.DataDirectory[8..(8+4)].unpack('V')[0]
349349
if (importsTable - addressOfEntryPoint) < code.length
350350
#shift original entry point to prevent tables overwritting
351351
addressOfEntryPoint = importsTable - (code.length + 4)
352352

353353
entry_point_offset = pe._dos_header.v['e_lfanew'] + entryPoint_offset
354-
exe[entry_point_offset,4] = [addressOfEntryPoint].pack('L')
354+
exe[entry_point_offset,4] = [addressOfEntryPoint].pack('V')
355355
end
356356
# put this section writable
357357
characteristics |= 0x8000_0000
358-
newcharacteristics = [characteristics].pack('L')
358+
newcharacteristics = [characteristics].pack('V')
359359
exe[sec[0],newcharacteristics.length] = newcharacteristics
360360
end
361361
end
@@ -572,20 +572,20 @@ def self.to_win32pe_service(framework, code, opts={})
572572
"\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
573573
"\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" +
574574
"\x26\x07\xFF\xD5"+pushed_service_name+"\x89\xE1" +
575-
"\x8D\x85"+[svcmain_code_offset].pack('<I')+"\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
575+
"\x8D\x85"+[svcmain_code_offset].pack('V')+"\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
576576
"\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" +
577577
"\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" +
578-
[hash_code_offset].pack('<I')+pushed_service_name+"\x89\xE1\x8D" +
579-
"\x85"+[svcctrlhandler_code_offset].pack('<I')+"\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
578+
[hash_code_offset].pack('V')+pushed_service_name+"\x89\xE1\x8D" +
579+
"\x85"+[svcctrlhandler_code_offset].pack('V')+"\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
580580
"\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" +
581581
"\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" +
582582
"\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" +
583583
"\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" +
584584
"\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" +
585585
"\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" +
586-
"\x40\x68\x00\x10\x00\x00\x68"+[code.length].pack('<I')+"\x57\x51\x68\xAE\x87" +
586+
"\x40\x68\x00\x10\x00\x00\x68"+[code.length].pack('V')+"\x57\x51\x68\xAE\x87" +
587587
"\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" +
588-
[shellcode_code_offset].pack('<I')+"\x54\x68"+[code.length].pack('<I') +
588+
[shellcode_code_offset].pack('V')+"\x54\x68"+[code.length].pack('V') +
589589
"\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" +
590590
"\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" +
591591
"\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" +
@@ -654,8 +654,8 @@ def self.replace_msi_buffer(pe, opts)
654654
msi = fd.read(fd.stat.size)
655655
}
656656

657-
section_size = 2**(msi[30..31].unpack('s')[0])
658-
sector_allocation_table = msi[section_size..section_size*2].unpack('l*')
657+
section_size = 2**(msi[30..31].unpack('s<')[0])
658+
sector_allocation_table = msi[section_size..section_size*2].unpack('l<*')
659659

660660
buffer_chain = []
661661
current_secid = 5 # This is closely coupled with the template provided and ideally
@@ -841,8 +841,8 @@ def self.to_exe_elf(framework, opts, template, code, big_endian=false)
841841
elf[0x60,8] = [elf.length].pack('Q>') #p_filesz
842842
elf[0x68,8] = [elf.length + code.length].pack('Q>') #p_memsz
843843
else # little endian
844-
elf[0x60,8] = [elf.length].pack('Q') #p_filesz
845-
elf[0x68,8] = [elf.length + code.length].pack('Q') #p_memsz
844+
elf[0x60,8] = [elf.length].pack('Q<') #p_filesz
845+
elf[0x68,8] = [elf.length + code.length].pack('Q<') #p_memsz
846846
end
847847
else
848848
raise RuntimeError, "Invalid ELF template: EI_CLASS value not supported"

lib/rex/arch.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def self.pack_addr(arch, addr)
4949
when ARCH_X86
5050
[addr].pack('V')
5151
when ARCH_X86_64
52-
[addr].pack('Q')
52+
[addr].pack('Q<')
5353
when ARCH_MIPS # ambiguous
5454
[addr].pack('N')
5555
when ARCH_MIPSBE

lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ def self.pack_pointer(pointer, platform)
2727

2828
case platform
2929
when PlatformUtil::X86_64
30-
# XXX: Only works if attacker and victim are like-endianed
31-
[pointer].pack('Q')
30+
# Assume little endian
31+
[pointer].pack('Q<')
3232
when PlatformUtil::X86_32
3333
[pointer].pack('V')
3434
else
@@ -40,8 +40,8 @@ def self.pack_pointer(pointer, platform)
4040
def self.unpack_pointer(packed_pointer, platform)
4141
case platform
4242
when PlatformUtil::X86_64
43-
# XXX: Only works if attacker and victim are like-endianed
44-
packed_pointer.unpack('Q').first
43+
# Assume little endian
44+
packed_pointer.unpack('Q<').first
4545
when PlatformUtil::X86_32
4646
packed_pointer.unpack('V').first
4747
else

lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ def initialize(railgun, platform)
324324
#
325325
def unpack_pointer(packed_pointer)
326326
if is_64bit
327-
# XXX: Only works if attacker and victim are like-endianed
328-
packed_pointer.unpack('Q')[0]
327+
# Assume little endian
328+
packed_pointer.unpack('Q<')[0]
329329
else
330330
packed_pointer.unpack('V')[0]
331331
end

lib/rex/post/meterpreter/packet.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def to_r
251251
elsif (self.type & TLV_META_TYPE_UINT == TLV_META_TYPE_UINT)
252252
raw = [value].pack("N")
253253
elsif (self.type & TLV_META_TYPE_QWORD == TLV_META_TYPE_QWORD)
254-
raw = [ self.htonq( value.to_i ) ].pack("Q")
254+
raw = [ self.htonq( value.to_i ) ].pack("Q<")
255255
elsif (self.type & TLV_META_TYPE_BOOL == TLV_META_TYPE_BOOL)
256256
if (value == true)
257257
raw = [1].pack("c")
@@ -312,7 +312,7 @@ def from_r(raw)
312312
elsif (self.type & TLV_META_TYPE_UINT == TLV_META_TYPE_UINT)
313313
self.value = raw.unpack("NNN")[2]
314314
elsif (self.type & TLV_META_TYPE_QWORD == TLV_META_TYPE_QWORD)
315-
self.value = raw.unpack("NNQ")[2]
315+
self.value = raw.unpack("NNQ<")[2]
316316
self.value = self.ntohq( self.value )
317317
elsif (self.type & TLV_META_TYPE_BOOL == TLV_META_TYPE_BOOL)
318318
self.value = raw.unpack("NNc")[2]
@@ -335,7 +335,7 @@ def htonq( value )
335335
if( [1].pack( 's' ) == [1].pack( 'n' ) )
336336
return value
337337
end
338-
return [ value ].pack( 'Q' ).reverse.unpack( 'Q' ).first
338+
return [ value ].pack( 'Q<' ).reverse.unpack( 'Q<' ).first
339339
end
340340

341341
def ntohq( value )

0 commit comments

Comments
 (0)