Skip to content

Commit

Permalink
add more datatypes
Browse files Browse the repository at this point in the history
  • Loading branch information
zgoldman-r7 committed Apr 17, 2024
1 parent 2cf8ea3 commit b4e9bf2
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 2 deletions.
124 changes: 122 additions & 2 deletions lib/rex/proto/mssql/client_mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ def mssql_parse_tds_reply(data, info)
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
Expand All @@ -195,6 +194,50 @@ def mssql_parse_tds_reply(data, info)
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]
Expand Down Expand Up @@ -328,8 +371,85 @@ def mssql_parse_tds_row(data, info)
end
row << str.gsub("\x00", '')

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]
Expand Down
51 changes: 51 additions & 0 deletions test/modules/post/test/mssql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,57 @@ def test_console_query
end
end

def test_datatypes
it "should support datetime TDS datatype" do
stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('1990-01-02' as datetime);"})}
ret = true
ret &&= stdout.buf.match?(/1990-01-02T00:00:00/)
ret
end

it "should support smalldatetime TDS datatype" do
stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('1990-01-02' as smalldatetime);"})}
ret = true
ret &&= stdout.buf.match?(/1990-01-02T00:00:00/)
ret
end

it "should support float TDS datatype" do
stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('19900' as float);"})}
ret = true
ret &&= stdout.buf.match?(/19900.0/)
ret
end

it "should support real TDS datatype" do
stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('19900' as real);"})}
ret = true
ret &&= stdout.buf.match?(/19900.0/)
ret
end

it "should support money TDS datatype" do
stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('12.50' as money);"})}
ret = true
ret &&= stdout.buf.match?(/12.5/)
ret
end

it "should support smallmoney TDS datatype" do
stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('12.50' as smallmoney);"})}
ret = true
ret &&= stdout.buf.match?(/12.5/)
ret
end

it "should support numeric TDS datatype" do
stdout = with_mocked_console(session) {|console| console.run_single(%{ query "select cast('1999999900' as numeric(16, 6));"})}
ret = true
ret &&= stdout.buf.match?(/1999999900.0/)
ret
end
end

def test_console_help
it "should support the help command" do
stdout = with_mocked_console(session) { |console| console.run_single("help") }
Expand Down

0 comments on commit b4e9bf2

Please sign in to comment.