Land #19105, add more mssql datatypes

This commit is contained in:
adfoster-r7 2024-04-19 14:47:29 +01:00 committed by GitHub
commit 92592f979b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 146 additions and 7 deletions

View File

@ -175,7 +175,6 @@ module ClientMixin
col[:utype] = data.slice!(0, 2).unpack('v')[0]
col[:flags] = data.slice!(0, 2).unpack('v')[0]
col[:type] = data.slice!(0, 1).unpack('C')[0]
case col[:type]
when 48
col[:id] = :tinyint
@ -195,6 +194,50 @@ module ClientMixin
col[:value_length] = data.slice!(0, 2).unpack('v')[0]
col[:value] = data.slice!(0, col[:value_length] * 2).gsub("\x00", '')
when 109
col[:id] = :float
col[:value_length] = data.slice!(0, 1).unpack('C')[0]
when 108
col[:id] = :numeric
col[:value_length] = data.slice!(0, 1).unpack('C')[0]
col[:precision] = data.slice!(0, 1).unpack('C')[0]
col[:scale] = data.slice!(0, 1).unpack('C')[0]
when 60
col[:id] = :money
when 110
col[:value_length] = data.slice!(0, 1).unpack('C')[0]
case col[:value_length]
when 8
col[:id] = :money
when 4
col[:id] = :smallmoney
else
col[:id] = :unknown
end
when 111
col[:value_length] = data.slice!(0, 1).unpack('C')[0]
case col[:value_length]
when 4
col[:id] = :smalldatetime
when 8
col[:id] = :datetime
else
col[:id] = :unknown
end
when 122
col[:id] = :smallmoney
when 59
col[:id] = :float
when 58
col[:id] = :smalldatetime
when 36
col[:id] = :guid
col[:value_length] = data.slice!(0, 1).unpack('C')[0]
@ -352,9 +395,85 @@ module ClientMixin
end
row << str
when :float
datalen = data.slice!(0, 1).unpack('C')[0]
case datalen
when 8
row << data.slice!(0, datalen).unpack('E')[0]
when 4
row << data.slice!(0, datalen).unpack('e')[0]
else
row << nil
end
when :numeric
varlen = data.slice!(0, 1).unpack('C')[0]
if varlen == 0
row << nil
else
sign = data.slice!(0, 1).unpack('C')[0]
raw = data.slice!(0, varlen - 1)
value = ''
case varlen
when 5
value = raw.unpack('L')[0]/(10**col[:scale]).to_f
when 9
value = raw.unpack('Q')[0]/(10**col[:scale]).to_f
when 13
chunks = raw.unpack('L3')
value = chunks[2] << 64 | chunks[1] << 32 | chunks[0]
value /= (10**col[:scale]).to_f
when 17
chunks = raw.unpack('L4')
value = chunks[3] << 96 | chunks[2] << 64 | chunks[1] << 32 | chunks[0]
value /= (10**col[:scale]).to_f
end
case sign
when 1
row << value
when 0
row << value * -1
end
end
when :money
datalen = data.slice!(0, 1).unpack('C')[0]
if datalen == 0
row << nil
else
raw = data.slice!(0, datalen)
rev = raw.slice(4, 4) << raw.slice(0, 4)
row << rev.unpack('q')[0]/10000.0
end
when :smallmoney
datalen = data.slice!(0, 1).unpack('C')[0]
if datalen == 0
row << nil
else
row << data.slice!(0, datalen).unpack('l')[0] / 10000.0
end
when :smalldatetime
datalen = data.slice!(0, 1).unpack('C')[0]
if datalen == 0
row << nil
else
days = data.slice!(0, 2).unpack('S')[0]
minutes = data.slice!(0, 2).unpack('S')[0] / 1440.0
row << DateTime.new(1900, 1, 1) + days + minutes
end
when :datetime
row << data.slice!(0, 8).unpack("H*")[0]
datalen = data.slice!(0, 1).unpack('C')[0]
if datalen == 0
row << nil
else
days = data.slice!(0, 4).unpack('l')[0]
minutes = data.slice!(0, 4).unpack('l')[0] / 1440.0
row << DateTime.new(1900, 1, 1) + days + minutes
end
when :rawint
row << data.slice!(0, 4).unpack('V')[0]

View File

@ -42,11 +42,31 @@ class MetasploitModule < Msf::Post
end
def test_datatypes
it "should support ntext TDS datatype" do
stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('foo' as ntext);"})}
ret = true
ret &&= stdout.buf.match?(/0 foo/)
ret
[
{query: "select cast('1990-01-02' as datetime);", expected: [[DateTime.new(1990, 1, 2)]]},
{query: "select cast(null as datetime);", expected: [[nil]]},
{query: "select cast('1990-01-02' as smalldatetime);", expected: [[DateTime.new(1990, 1, 2)]]},
{query: "select cast(null as smalldatetime);", expected: [[nil]]},
{query: "select cast('19900' as float);", expected: [[19900.0]]},
{query: "select cast(null as float);", expected: [[nil]]},
{query: "select cast('19900' as real);", expected: [[19900.0]]},
{query: "select cast(null as real);", expected: [[nil]]},
{query: "select cast('12.50' as money);", expected: [[12.5]]},
{query: "select cast(null as money);", expected: [[nil]]},
{query: "select cast('12.50' as smallmoney);", expected: [[12.5]]},
{query: "select cast(null as smallmoney);", expected: [[nil]]},
{query: "select cast('1999999900' as numeric(16, 6));", expected: [[1999999900.0]]},
{query: "select cast(null as numeric(16, 6));", expected: [[nil]]},
{query: "select cast('foo' as ntext);", expected: [['foo']]},
{query: "select cast(null as ntext);", expected: [[nil]]},
].each do |test|
it "should execute the query #{test[:query]} and return #{test[:expected].inspect}" do
console = session.console
result = console.client.query(test[:query])
ret = result[:rows] == test[:expected]
ret &&= result[:errors].empty?
ret
end
end
end