Skip to content

Commit

Permalink
Fix improper use of host-endian or signed pack/unpack
Browse files Browse the repository at this point in the history
Note that there are some cases of host-endian left, these
are intentional because they operate on host-local memory
or services.

When in doubt, please use:

```
ri pack
```
  • Loading branch information
HD Moore committed Jun 30, 2014
1 parent 255e792 commit c9b6c05
Show file tree
Hide file tree
Showing 26 changed files with 65 additions and 65 deletions.
2 changes: 1 addition & 1 deletion lib/bit-struct/octet-field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def add_accessors_to(cl, attr = name) # :nodoc:
old_writer = "#{attr_chars}="

define_method "#{attr}=" do |val|
data = val.split(sep).map{|s|s.to_i(base)}.pack("c*")
data = val.split(sep).map{|s|s.to_i(base)}.pack("C*")
send(old_writer, data)
end
end
Expand Down
3 changes: 1 addition & 2 deletions lib/msf/core/exploit/afp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,7 @@ def parse_info_response(response)
end

def parse_header(packet)
header = packet.unpack('CCnNNN') #ruby 1.8.7 don't support unpacking signed integers in big-endian order
header[3] = packet[4..7].reverse.unpack("l").first
header = packet.unpack('CCnNNN')
return header
end

Expand Down
2 changes: 1 addition & 1 deletion lib/msf/core/post/windows/accounts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def check_dir_perms(dir, token)

#define generic mapping structure
gen_map = [0,0,0,0]
gen_map = gen_map.pack("L")
gen_map = gen_map.pack("V")
buffer_size = 500

#get Security Descriptor for the directory
Expand Down
4 changes: 2 additions & 2 deletions lib/msf/core/post/windows/ldap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,15 @@ def query_ldap(session_handle, base, scope, filter, fields)
# @param pEntry [Fixnum] Pointer to the Entry
# @return [Array] Entry data structure
def get_entry(pEntry)
return client.railgun.memread(pEntry,41).unpack('LLLLLLLLLSCCC')
return client.railgun.memread(pEntry,41).unpack('VVVVVVVVVvCCC')
end

# Get BER Element data structure from LDAPMessage
#
# @param msg [String] The LDAP Message from the server
# @return [String] The BER data structure
def get_ber(msg)
ber = client.railgun.memread(msg[2],60).unpack('L*')
ber = client.railgun.memread(msg[2],60).unpack('V*')

# BER Pointer is different between x86 and x64
if client.platform =~ /x64/
Expand Down
2 changes: 1 addition & 1 deletion lib/msf/core/post/windows/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ def service_status(name, server=nil)
raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{handle["GetLastError"]}")
end

vals = status['lpServiceStatus'].unpack('L*')
vals = status['lpServiceStatus'].unpack('V*')
adv.CloseServiceHandle(handle["return"])

ret = {
Expand Down
4 changes: 2 additions & 2 deletions lib/msf/util/exe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,8 @@ def self.replace_msi_buffer(pe, opts)
msi = fd.read(fd.stat.size)
}

section_size = 2**(msi[30..31].unpack('s<')[0])
sector_allocation_table = msi[section_size..section_size*2].unpack('l<*')
section_size = 2**(msi[30..31].unpack('v')[0])
sector_allocation_table = msi[section_size..section_size*2].unpack('V*')

buffer_chain = []
current_secid = 5 # This is closely coupled with the template provided and ideally
Expand Down
2 changes: 1 addition & 1 deletion lib/rex/encoder/ndr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def NDR.short(string)
# use to encode:
# byte element_1;
def NDR.byte(string)
return [string].pack('c')
return [string].pack('C')
end

# Encode a byte array
Expand Down
4 changes: 2 additions & 2 deletions lib/rex/ole/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,15 @@ def self.pack8(value)


def self.getUnicodeString(buf)
buf = buf.unpack('S*').pack('C*')
buf = buf.unpack('v*').pack('C*')
if (idx = buf.index(0x00.chr))
buf.slice!(idx, buf.length)
end
buf
end

def self.putUnicodeString(buf)
buf = buf.unpack('C*').pack('S*')
buf = buf.unpack('C*').pack('v*')
if (buf.length < 0x40)
buf << "\x00" * (0x40 - buf.length)
end
Expand Down
4 changes: 2 additions & 2 deletions lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,9 @@ def read_data(type, position, buffer = nil)
# Both on x86 and x64, DWORD is 32 bits
return raw.unpack('V').first
when :BOOL
return raw.unpack('l').first == 1
return raw.unpack('V').first == 1
when :LONG
return raw.unpack('l').first
return raw.unpack('V').first
end

#If nothing worked thus far, return it raw
Expand Down
2 changes: 1 addition & 1 deletion lib/rex/proto/dcerpc/ndr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def self.short(string)
# byte element_1;
def self.byte(string)
warn 'should be using Rex::Encoder::NDR'
return [string].pack('c')
return [string].pack('C')
end

# Encode a byte array
Expand Down
6 changes: 3 additions & 3 deletions lib/rex/proto/natpmp/packet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def self.external_address_request
# Parse a NAT-PMP external address response +resp+.
# Returns the decoded parts of the response as an array.
def self.parse_external_address_response(resp)
(ver, op, result, epoch, addr) = resp.unpack("CCSLN")
(ver, op, result, epoch, addr) = resp.unpack("CCvVN")
[ ver, op, result, epoch, Rex::Socket::addr_itoa(addr) ]
end

Expand All @@ -31,13 +31,13 @@ def self.map_port_request(lport, rport, protocol, lifetime)
lport,
rport,
lifetime
].pack("ccnnnN")
].pack("CCnnnN")
end

# Parse a NAT-PMP mapping response +resp+.
# Returns the decoded parts as an array.
def self.parse_map_port_response(resp)
resp.unpack("CCSLnnN")
resp.unpack("CCvVnnN")
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/rex/registry/lfkey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class LFHashRecord
attr_accessor :nodekey_offset, :nodekey_name_verification

def initialize(hive_blob, offset)
@nodekey_offset = hive_blob[offset, 4].unpack('l').first
@nodekey_offset = hive_blob[offset, 4].unpack('V').first
@nodekey_name_verification = hive_blob[offset+0x04, 4].to_s
end

Expand Down
20 changes: 10 additions & 10 deletions lib/rex/registry/nodekey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ def initialize(hive, offset)
return
end

@timestamp = hive[offset+0x04, 8].unpack('q').first
@parent_offset = hive[offset+0x10, 4].unpack('l').first
@subkeys_count = hive[offset+0x14, 4].unpack('l').first
@lf_record_offset = hive[offset+0x1c, 4].unpack('l').first
@value_count = hive[offset+0x24, 4].unpack('l').first
@value_list_offset = hive[offset+0x28, 4].unpack('l').first
@security_key_offset = hive[offset+0x2c, 4].unpack('l').first
@class_name_offset = hive[offset+0x30, 4].unpack('l').first
@name_length = hive[offset+0x48, 2].unpack('c').first
@class_name_length = hive[offset+0x4a, 2].unpack('c').first
@timestamp = hive[offset+0x04, 8].unpack('Q').first
@parent_offset = hive[offset+0x10, 4].unpack('V').first
@subkeys_count = hive[offset+0x14, 4].unpack('V').first
@lf_record_offset = hive[offset+0x1c, 4].unpack('V').first
@value_count = hive[offset+0x24, 4].unpack('V').first
@value_list_offset = hive[offset+0x28, 4].unpack('V').first
@security_key_offset = hive[offset+0x2c, 4].unpack('V').first
@class_name_offset = hive[offset+0x30, 4].unpack('V').first
@name_length = hive[offset+0x48, 2].unpack('C').first
@class_name_length = hive[offset+0x4a, 2].unpack('C').first
@name = hive[offset+0x4c, @name_length].to_s

windows_time = @timestamp
Expand Down
10 changes: 5 additions & 5 deletions lib/rex/registry/valuekey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ def initialize(hive, offset)
return
end

@name_length = hive[offset+0x02, 2].unpack('c').first
@length_of_data = hive[offset+0x04, 4].unpack('l').first
@data_offset = hive[offset+ 0x08, 4].unpack('l').first
@value_type = hive[offset+0x0C, 4].unpack('c').first
@name_length = hive[offset+0x02, 2].unpack('C').first
@length_of_data = hive[offset+0x04, 4].unpack('V').first
@data_offset = hive[offset+ 0x08, 4].unpack('V').first
@value_type = hive[offset+0x0C, 4].unpack('C').first

if @value_type == 1
@readable_value_type = "Unicode character string"
Expand All @@ -34,7 +34,7 @@ def initialize(hive, offset)
@readable_value_type = "Multiple unicode strings separated with '\\x00'"
end

flag = hive[offset+0x10, 2].unpack('c').first
flag = hive[offset+0x10, 2].unpack('C').first

if flag == 0
@name = "Default"
Expand Down
2 changes: 1 addition & 1 deletion lib/rex/registry/valuelist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def initialize(hive, offset, number_of_values)
valuekey_offset = hive[offset + inner_offset, 4]
next if !valuekey_offset

valuekey_offset = valuekey_offset.unpack('l').first
valuekey_offset = valuekey_offset.unpack('V').first
@values << ValueKey.new(hive, valuekey_offset + 0x1000)
inner_offset = inner_offset + 4
end
Expand Down
1 change: 1 addition & 0 deletions lib/rex/socket/ip.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def sendto(gram, peerhost, flags = 0)
Rex::Compat.is_macosx
)
gram=gram.dup
# Note that these are *intentionally* host order for BSD support
gram[2,2]=gram[2,2].unpack("n").pack("s")
gram[6,2]=gram[6,2].unpack("n").pack("s")
end
Expand Down
2 changes: 1 addition & 1 deletion lib/sshkey/lib/sshkey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def ssh_public_key_conversion

SSH_CONVERSION[type].each do |method|
byte_array = to_byte_array(key_object.public_key.send(method).to_i)
out += encode_unsigned_int_32(byte_array.length).pack("c*")
out += encode_unsigned_int_32(byte_array.length).pack("C*")
out += byte_array.pack("C*")
end

Expand Down
2 changes: 1 addition & 1 deletion lib/windows_console_color_support.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def flush
def setcolor(color)
csbi = 0.chr * 24
@GetConsoleScreenBufferInfo.Call(@hConsoleHandle,csbi)
wAttr = csbi[8,2].unpack('S').first
wAttr = csbi[8,2].unpack('v').first

case color
when 0 # reset
Expand Down
2 changes: 1 addition & 1 deletion modules/exploits/windows/fileformat/ms14_017_rtf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def exploit
exploit_data << rop_chain
exploit_data << payload.encoded
exploit_data << make_nops(exploit_data.length % 2)
exploit_data = exploit_data.unpack("S<*")
exploit_data = exploit_data.unpack("v*")
exploit_data = exploit_data.map { |word| " ?\\u-#{0x10000 - word}" }
exploit_data = exploit_data.join

Expand Down
14 changes: 7 additions & 7 deletions modules/exploits/windows/local/ms11_080_afdjoinleaf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def find_sys_base(drvname)
session.railgun.add_function('psapi', 'EnumDeviceDrivers', 'BOOL', [ ["PBLOB", "lpImageBase", "out"], ["DWORD", "cb", "in"], ["PDWORD", "lpcbNeeded", "out"]])
session.railgun.add_function('psapi', 'GetDeviceDriverBaseNameA', 'DWORD', [ ["LPVOID", "ImageBase", "in"], ["PBLOB", "lpBaseName", "out"], ["DWORD", "nSize", "in"]])
results = session.railgun.psapi.EnumDeviceDrivers(4096, 1024, 4)
addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("L*")
addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("V*")

addresses.each do |address|
results = session.railgun.psapi.GetDeviceDriverBaseNameA(address, 48, 48)
Expand Down Expand Up @@ -172,7 +172,7 @@ def exploit
irpstuff << rand_text_alpha(231)

if not this_proc.memory.writable?(0x1000)
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ base_addr ].pack("L"), nil, [ 0x1000 ].pack("L"), "MEM_COMMIT | MEM_RESERVE", "PAGE_EXECUTE_READWRITE")
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ base_addr ].pack("V"), nil, [ 0x1000 ].pack("V"), "MEM_COMMIT | MEM_RESERVE", "PAGE_EXECUTE_READWRITE")
end
if not this_proc.memory.writable?(0x1000)
print_error('Failed to properly allocate memory')
Expand Down Expand Up @@ -202,10 +202,10 @@ def exploit
halDispatchTable0x8 = halDispatchTable + 0x8

restore_ptrs = "\x31\xc0"
restore_ptrs << "\xb8" + [ halpSetSystemInformation ].pack("L")
restore_ptrs << "\xa3" + [ halDispatchTable0x8 ].pack("L")
restore_ptrs << "\xb8" + [ haliQuerySystemInformation ].pack("L")
restore_ptrs << "\xa3" + [ halDispatchTable0x4 ].pack("L")
restore_ptrs << "\xb8" + [ halpSetSystemInformation ].pack("V")
restore_ptrs << "\xa3" + [ halDispatchTable0x8 ].pack("V")
restore_ptrs << "\xb8" + [ haliQuerySystemInformation ].pack("V")
restore_ptrs << "\xa3" + [ halDispatchTable0x4 ].pack("V")

tokenstealing = "\x52"
tokenstealing << "\x53"
Expand Down Expand Up @@ -241,7 +241,7 @@ def exploit
this_proc.memory.write(shellcode_address_nodep, shellcode)
this_proc.memory.protect(0x00020000)

addr = [ 2, 4455, 0x7f000001, 0, 0 ].pack("s!S!L!L!L!")
addr = [ 2, 4455, 0x7f000001, 0, 0 ].pack("vvVVV")
result = session.railgun.ws2_32.connect(socket, addr, addr.length)
if result['return'] != 0xffffffff
print_error("The socket is not in the correct state")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ def upload(fname, data)
# op code
req = "\xD0\x07\x00\x00"
# filename length
req << "#{[fname.length].pack('l')}"
req << "#{[fname.length].pack('V')}"
# file name
req << "#{fname}"
# data length
req << "#{[data.length].pack('l')}"
req << "#{[data.length].pack('V')}"
# data
req << "#{data}"
connect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def make_bcls
exe = generate_payload_exe
# Padding to be sure we're aligned to 4 bytes.
exe << "\x00" until exe.length % 4 == 0
longs = exe.unpack("l*")
longs = exe.unpack("V*")
offset = 0

# gefebt.exe isn't able to handle (on my test environment) long
Expand Down
2 changes: 1 addition & 1 deletion modules/payloads/stagers/windows/reverse_https_proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def generate
jmphost_loc = p.index("\x68\x3a\x56\x79\xa7\xff\xd5") + 8 # push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" ) ; call ebp
p[jmphost_loc, 4] = [p[jmphost_loc, 4].unpack("V")[0] - jmp_offset].pack("V")
#patch call Internetopen
p[p.length - 4, 4] = [p[p.length - 4, 4].unpack("l")[0] + jmp_offset].pack("V")
p[p.length - 4, 4] = [p[p.length - 4, 4].unpack("V")[0] + jmp_offset].pack("V")

# patch the LPORT
lport = datastore['LPORT']
Expand Down
10 changes: 5 additions & 5 deletions modules/post/windows/gather/credentials/enum_cred_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def pack_add(data)
if is_86
addr = [data].pack("V")
else
addr = [data].pack("Q")
addr = [data].pack("Q<")
end
return addr
end
Expand Down Expand Up @@ -95,7 +95,7 @@ def decrypt_blob(daddr, dlen, type)
len,add = ret["pDataOut"].unpack("V2")
else
ret = c32.CryptUnprotectData("#{len}#{addr}",16,"#{elen}#{eaddr}",nil,nil,0,16)
len,add = ret["pDataOut"].unpack("Q2")
len,add = ret["pDataOut"].unpack("Q<2")
end

#get data, and return it
Expand Down Expand Up @@ -177,14 +177,14 @@ def get_creds
#read array of addresses as pointers to each structure
raw = read_str(p_to_arr[0], arr_len, 2)
pcred_array = raw.unpack("V*") if is_86
pcred_array = raw.unpack("Q*") unless is_86
pcred_array = raw.unpack("Q<*") unless is_86

#loop through the addresses and read each credential structure
pcred_array.each do |pcred|
cred = {}
raw = read_str(pcred, 52,2)
cred_struct = raw.unpack("VVVVQVVVVVVV") if is_86
cred_struct = raw.unpack("VVQQQQQVVQQQ") unless is_86
cred_struct = raw.unpack("VVVVQ<VVVVVVV") if is_86
cred_struct = raw.unpack("VVQ<Q<Q<Q<Q<VVQ<Q<Q<") unless is_86
cred["flags"] = cred_struct[0]
cred["type"] = cred_struct[1]
cred["targetname"] = read_str(cred_struct[2],512, 1)
Expand Down
Loading

0 comments on commit c9b6c05

Please sign in to comment.