syspy 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/bytes.rb ADDED
@@ -0,0 +1,98 @@
1
+ require "bindata"
2
+
3
+ module Syspy
4
+ class Bytes
5
+ def self.uint(io)
6
+ BinData::Uint8.read(io).to_i
7
+ end
8
+
9
+ def self.uintle(io,length)
10
+ case length
11
+ when 1:
12
+ BinData::Uint8.read(io).to_i
13
+ when 2:
14
+ BinData::Uint16le.read(io).to_i
15
+ when 4:
16
+ BinData::Uint32le.read(io).to_i
17
+ else
18
+ raise ArgumentError.new("Invalid length")
19
+ end
20
+ end
21
+
22
+ def self.uint16le(io)
23
+ BinData::Uint16le.read(io).to_i
24
+ end
25
+
26
+ def self.uint32le(io)
27
+ BinData::Uint32le.read(io) .to_i
28
+ end
29
+
30
+ def self.uintbe(io,length)
31
+ case length
32
+ when 1:
33
+ BinData::Uint8.read(io).to_i
34
+ when 2:
35
+ BinData::Uint16be.read(io).to_i
36
+ when 4:
37
+ BinData::Uint32be.read(io).to_i
38
+ else
39
+ raise ArgumentError.new("Invalid length")
40
+ end
41
+ end
42
+
43
+ def self.uint16be(io)
44
+ BinData::Uint16be.read(io).to_i
45
+ end
46
+
47
+ def self.uint32be(io)
48
+ BinData::Uint32be.read(io).to_i
49
+ end
50
+
51
+ def self.int(io)
52
+ BinData::Int8.read(io).to_i
53
+ end
54
+
55
+ def self.intle(io,length)
56
+ case length
57
+ when 1:
58
+ BinData::Int8.read(io).to_i
59
+ when 2:
60
+ BinData::Int16le.read(io).to_i
61
+ when 4:
62
+ BinData::Int32le.read(io).to_i
63
+ else
64
+ raise ArgumentError.new("Invalid length")
65
+ end
66
+ end
67
+
68
+ def self.int16le(io)
69
+ BinData::Int16le.read(io).to_i
70
+ end
71
+
72
+ def self.int32le(io)
73
+ BinData::Int32le.read(io).to_i
74
+ end
75
+
76
+ def self.intbe(io,length)
77
+ case length
78
+ when 1:
79
+ BinData::Int8.read(io).to_i
80
+ when 2:
81
+ BinData::Int16be.read(io).to_i
82
+ when 4:
83
+ BinData::Int32be.read(io).to_i
84
+ else
85
+ raise ArgumentError.new("Invalid length")
86
+ end
87
+ end
88
+
89
+ def self.int16be(io)
90
+ BinData::Int16be.read(io).to_i
91
+ end
92
+
93
+ def self.int32be(io)
94
+ BinData::Int32be.read(io).to_i
95
+ end
96
+
97
+ end
98
+ end
data/lib/log.rb ADDED
@@ -0,0 +1,45 @@
1
+ require "logger"
2
+
3
+ module Syspy
4
+ class Log
5
+
6
+ LOG_FILE = "syspy.log"
7
+ LOGGERS = []
8
+
9
+ STDOUT_LOG = Logger.new(STDOUT)
10
+ STDOUT_LOG.level = Logger::INFO
11
+
12
+ #FILE_LOG = Logger.new(LOG_FILE)
13
+ #FILE_LOG.level = Logger::INFO
14
+
15
+ LOGGERS << STDOUT_LOG
16
+ #LOGGERS << FILE_LOG
17
+
18
+ def self.fatal(message)
19
+ self.log(Logger::FATAL,message)
20
+ end
21
+
22
+ def self.error(message)
23
+ self.log(Logger::ERROR,message)
24
+ end
25
+
26
+ def self.warn(message)
27
+ self.log(Logger::WARN,message)
28
+ end
29
+
30
+ def self.info(message)
31
+ self.log(Logger::INFO,message)
32
+ end
33
+
34
+ def self.debug(message)
35
+ self.log(Logger::DEBUG,message)
36
+ end
37
+
38
+ def self.log(severity,message)
39
+ LOGGERS.each(){|logger|
40
+ logger.log(severity,message)
41
+ }
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,39 @@
1
+ require "lib/bytes"
2
+
3
+ module Syspy
4
+
5
+ class ParseError < Exception
6
+ end
7
+
8
+ class TdsPackage
9
+
10
+ def read_uint(io)
11
+ Bytes.uint(io)
12
+ end
13
+
14
+ def read_uint32(io)
15
+ Bytes.uint32le(io)
16
+ end
17
+
18
+ def read_uint16(io)
19
+ Bytes.uint16le(io)
20
+ end
21
+
22
+ def read_int(io)
23
+ Bytes.int(io)
24
+ end
25
+
26
+ def read_int32(io)
27
+ Bytes.int32le(io)
28
+ end
29
+
30
+ def read_int16(io)
31
+ Bytes.int16le(io)
32
+ end
33
+
34
+ def read_text(io,length)
35
+ io.read(length)
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,121 @@
1
+ require "stringio"
2
+ require "thread"
3
+
4
+ require "lib/tds_types"
5
+ require "lib/tds_tokens"
6
+
7
+ module Syspy
8
+ class TdsPackageStream
9
+
10
+ def initialize(interface,dst,dst_port)
11
+ @interface = interface
12
+ @dst = dst
13
+ @dst_port = dst_port
14
+ @in,@out = IO.pipe()
15
+ end
16
+
17
+ def each_package()
18
+ Thread.abort_on_exception = true
19
+ @tcpdump_thread = Thread.new(){
20
+ IO.popen("tcpdump -q -y EN10MB -U -B #{1024 * 1024} -w - -i #{@interface} tcp and dst #{@dst} and dst port #{@dst_port} 2>/dev/null"){|io|
21
+ content = ""
22
+ loop(){
23
+ tcp_length = read_ip_header(io)
24
+ Log.debug "Got IP package: #{tcp_length}"
25
+ content_length = read_tcp_header(io,tcp_length)
26
+ Log.debug "Got TCP package: #{content_length}"
27
+
28
+ if(content_length > 0)
29
+ content = io.read(content_length)
30
+ @out.write(content)
31
+ @out.flush
32
+ end
33
+
34
+ Log.debug "Network package done"
35
+ }
36
+ }
37
+ }
38
+
39
+ content = ""
40
+ @in.each_byte(){|byte|
41
+ if(byte == 0x0F)
42
+ last_packet_indicator = Bytes.uint(@in)
43
+ length = Bytes.uint16be(@in)
44
+
45
+ # skip next 4 bytes of the header
46
+ if(Bytes.uint32be(@in) == 0x00)
47
+ content << @in.read(length - 8)
48
+
49
+ if(last_packet_indicator == 0x1)
50
+ begin
51
+ io = StringIO.new(content)
52
+ package = handle_package(io)
53
+ yield package if package
54
+ ensure
55
+ content = ""
56
+ end
57
+ end
58
+ end
59
+ end
60
+ }
61
+ end
62
+
63
+ def handle_package(io)
64
+ token = io.readchar()
65
+ token_class = TdsTokens.token_class(token)
66
+ if(token_class)
67
+ length = TdsTokens.fixed_length(token)
68
+ unless(length)
69
+ length_field_size = TdsTokens.length_field_size(token)
70
+ if(length_field_size)
71
+ length = Bytes.uintle(io,length_field_size)
72
+ end
73
+ end
74
+ Log.debug("Got #{TdsTokens.token_name(token)} of #{length} bytes")
75
+ package = token_class.new(io,length)
76
+ return package
77
+ end
78
+ nil
79
+ end
80
+
81
+ def read_ip_header(io)
82
+ count = 0
83
+ loop(){
84
+ network_type = Bytes.uint16be(io)
85
+ break if network_type == 0x800 and count >= 14
86
+ count += 1
87
+ }
88
+
89
+ # read IP version and header length
90
+ ver_len = io.readchar()
91
+ version = ver_len >> 4
92
+
93
+ raise "Invalid IP version: #{version}" unless version == 4 || version == 6
94
+
95
+ header_length = (ver_len & 0x0F) * 4
96
+
97
+ # skip TOS
98
+ io.readchar()
99
+
100
+ # get package length
101
+ content_length = Bytes.uint16be(io)
102
+
103
+ # consume remaining IP header
104
+ io.read(header_length - 4)
105
+ content_length - header_length
106
+ end
107
+
108
+ def read_tcp_header(io, ip_package_size)
109
+ # skip first 12
110
+ io.read(12)
111
+
112
+ # get header length
113
+ tcp_offset = (io.readchar() >> 4) * 4
114
+
115
+ # consume remaining tcp header
116
+ io.read(tcp_offset - 13)
117
+
118
+ ip_package_size - tcp_offset
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,32 @@
1
+ require "lib/tds_package"
2
+
3
+ module Syspy
4
+ class TdsLanguage < TdsPackage
5
+
6
+ attr_reader :status, :language_text, :tds_paramfmt, :tds_params
7
+
8
+ STATUS_PARAMETERIZED = 0x01
9
+
10
+ def initialize(io,length)
11
+ @status = read_uint(io)
12
+ @language_text = read_text(io,length - 1)
13
+ if(@status == 1 && !io.eof?)
14
+ token = read_uint(io)
15
+ if(token == TdsTokens::TDS_PARAMFMT || token == TdsTokens::TDS_PARAMFMT2)
16
+ paramfmt_length = Bytes.uintle(io,TdsTokens.length_field_size(token))
17
+ if(paramfmt_length < 1000000)
18
+ @tds_paramfmt = TdsTokens.token_class(token).new(io,paramfmt_length)
19
+ if(@tds_paramfmt.params_count > 0)
20
+ token = read_uint(io)
21
+ if(token == TdsTokens::TDS_PARAMS)
22
+ @tds_params = TdsParams.new(io,@tds_paramfmt)
23
+ end
24
+ end
25
+ else
26
+ Log.warn("Illegal paramfmt length: #{paramfmt_length}")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ module Syspy
2
+ class TdsParamfmt < TdsPackage
3
+
4
+ attr_reader :params_count, :parameters
5
+
6
+ def initialize(io,length)
7
+ @params_count = read_uint16(io)
8
+ puts "TdsParamfmt2: #{@params_count}"
9
+ @parameters = []
10
+ 1.upto(@params_count){
11
+
12
+ }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,50 @@
1
+ module Syspy
2
+ class TdsParamfmt2 < TdsPackage
3
+
4
+ attr_reader :params_count, :parameters
5
+
6
+ def initialize(io,length)
7
+ @params_count = read_uint16(io)
8
+ @parameters = []
9
+
10
+ 1.upto(@params_count){
11
+ parameter = {}
12
+ name_length = read_uint(io)
13
+ parameter[:name_length] = name_length
14
+ if(name_length > 0)
15
+ parameter[:param_name] = read_text(io,name_length)
16
+ end
17
+ parameter[:status] = read_uint32(io)
18
+ parameter[:user_type] = read_int32(io)
19
+ data_type = read_uint(io)
20
+ parameter[:data_type] = data_type
21
+
22
+ data_length = TdsTypes.fixed_length(data_type)
23
+
24
+ if(data_length == -5)
25
+ data_length = Bytes.int32le(io)
26
+ elsif(data_length == -4)
27
+ data_length = Bytes.int32le(io)
28
+ elsif(data_length == -2)
29
+ data_length = Bytes.int32le(io)
30
+ elsif(data_length == -1)
31
+ data_length = Bytes.uint(io)
32
+ end
33
+
34
+ parameter[:length] = data_length
35
+
36
+ if(TdsTypes.numeric?(data_type))
37
+ parameter[:precision] = read_uint(io)
38
+ parameter[:scale] = read_uint(io)
39
+ end
40
+
41
+ locale_length = read_uint(io)
42
+ parameter[:locale_length] = locale_length
43
+ if(locale_length > 0)
44
+ parameter[:locale_info] = read_text(io,locale_length)
45
+ end
46
+ @parameters << parameter
47
+ }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,70 @@
1
+ module Syspy
2
+ class TdsParams < TdsPackage
3
+
4
+ attr_reader :params_count, :parameters
5
+
6
+ def initialize(io,paramfmt)
7
+ @parameters = []
8
+ paramfmt.parameters.each(){|format|
9
+ @parameters << read_data(io,format)
10
+ }
11
+ end
12
+
13
+ def read_data(io,format)
14
+ data_type = format[:data_type]
15
+ case data_type
16
+ when TdsTypes::SYBINTN
17
+ len = read_int(io)
18
+ return Bytes.intle(io,len)
19
+ when TdsTypes::SYBINT1
20
+ return Bytes.int(io)
21
+ when TdsTypes::SYBINT2
22
+ return Bytes::int16le(io)
23
+ when TdsTypes::SYBINT4
24
+ return Bytes::int32le(io)
25
+ when TdsTypes::SYBCHAR, TdsTypes::SYBVARCHAR
26
+ len = read_uint(io)
27
+ if (len > 0)
28
+ val = read_text(io,len)
29
+ # In TDS 4/5 zero length varchars are stored as a
30
+ # single space to distinguish them from nulls.
31
+ if(len == 1 && data_type == TdsTypes::SYBVARCHAR)
32
+ return " " == val ? "" : val
33
+ end
34
+ return val
35
+ end
36
+ when TdsTypes::SYBDATETIME4, TdsTypes::SYBDATETIMN, TdsTypes::SYBDATETIME
37
+ read_datetime(io,data_type)
38
+ else
39
+ raise "Unhandled data type: #{TdsTypes.name(data_type)} (0x#{data_type.to_s(16)})"
40
+ end
41
+ end
42
+
43
+ TIME_DIFF = Time.at(0) - Time.local(1900,1,1)
44
+
45
+ def read_datetime(io,data_type)
46
+ if (data_type == TdsTypes::SYBDATETIMN)
47
+ len = read_uint(io)
48
+ elsif (data_type == TdsTypes::SYBDATETIME4)
49
+ len = 4;
50
+ else
51
+ len = 8;
52
+ end
53
+
54
+ gmt_offset = Time.new().gmt_offset
55
+
56
+ case len
57
+ when 0
58
+ return nil
59
+ when 8
60
+ days = read_int32(io)
61
+ time = read_int32(io)
62
+ return Time.at(days * 24 * 3600 - TIME_DIFF + time / 300 - gmt_offset)
63
+ when 4
64
+ days = read_int16le(io)
65
+ time = read_int16le(io)
66
+ return Time.at(days * 24 * 3600 + time * 60 - gmt_offset)
67
+ end
68
+ end
69
+ end
70
+ end
data/lib/tds_tokens.rb ADDED
@@ -0,0 +1,104 @@
1
+ module Syspy
2
+ class TdsTokens
3
+ TOKENS = [
4
+ ["TDS_ALTFMT", 0xA8, 2],
5
+ ["TDS_ALTNAME", 0xA7, 2],
6
+ ["TDS_ALTROW", 0xD3, nil],
7
+ ["TDS_CAPABILITY", 0xE2, 2],
8
+ ["TDS_COLINFO", 0xA5, 2],
9
+ ["TDS_COLINFO2", 0x20, 4],
10
+ ["TDS_CONTROL", 0xAE, 2],
11
+ ["TDS_CURCLOSE", 0x80, 2],
12
+ ["TDS_CURDECLARE", 0x86, 2],
13
+ ["TDS_CURDECLARE2", 0x23, 4],
14
+ ["TDS_CURDECLARE3", 0x10, 4],
15
+ ["TDS_CURDELETE", 0x81, 2],
16
+ ["TDS_CURFETCH", 0x82, 2],
17
+ ["TDS_CURINFO", 0x83, 2],
18
+ ["TDS_CURINFO2", 0x87, 2],
19
+ ["TDS_CURINFO3", 0x88, 2],
20
+ ["TDS_CUROPEN", 0x84, 2],
21
+ ["TDS_CURUPDATE", 0x85, 2],
22
+ ["TDS_DBRPC", 0xE6, 2],
23
+ ["TDS_DBRPC2", 0xE8, 2],
24
+ ["TDS_DONE", 0xFD, [8]],
25
+ ["TDS_DONEINPROC", 0xFF, [8]],
26
+ ["TDS_DONEPROC", 0xFE, [8]],
27
+ ["TDS_DYNAMIC", 0xE7, 2],
28
+ ["TDS_DYNAMIC2", 0x62, 4],
29
+ ["TDS_EED", 0xE5, 2],
30
+ ["TDS_ENVCHANGE", 0xE3, 2],
31
+ ["TDS_ERROR", 0xAA, 2],
32
+ ["TDS_EVENTNOTICE", 0xA2, 2],
33
+ ["TDS_INFO", 0xAB, 2],
34
+ ["TDS_KEY", 0xCA, nil],
35
+ ["TDS_LANGUAGE", 0x21, 4],
36
+ ["TDS_LOGINACK", 0xAD, 2],
37
+ ["TDS_LOGOUT", 0x71, [1]],
38
+ ["TDS_MSG", 0x65, 1, 1],
39
+ ["TDS_OFFSET", 0x78, [4]],
40
+ ["TDS_OPTIONCMD", 0xA6, 2],
41
+ ["TDS_ORDERBY", 0xA9, 2],
42
+ ["TDS_ORDERBY2", 0x22, 4],
43
+ ["TDS_PARAMFMT", 0xEC, 2],
44
+ ["TDS_PARAMFMT2", 0x20, 4],
45
+ ["TDS_PARAMS", 0xD7, nil],
46
+ ["TDS_RETURNSTATUS", 0x79, [4]],
47
+ ["TDS_RETURNVALUE", 0xAC, 2],
48
+ ["TDS_ROW", 0xD1, nil],
49
+ ["TDS_ROWFMT", 0xEE, 2],
50
+ ["TDS_ROWFMT2", 0x61, 4],
51
+ ["TDS_TABNAME", 0xA4, 2]
52
+ ]
53
+
54
+ NAMES = {}
55
+ FIXED_LENGTHS = {}
56
+ LENGTH_FIELD_SIZES = {}
57
+ STREAM_CLASSES = {}
58
+
59
+ TOKENS.each(){|values|
60
+ name = values[0]
61
+ token = values[1]
62
+ length = values[2]
63
+
64
+ self.const_set(name,token)
65
+
66
+ NAMES[token] = name
67
+ if(length)
68
+ if(length.instance_of?(Array))
69
+ FIXED_LENGTHS[token] = length.first
70
+ else
71
+ LENGTH_FIELD_SIZES[token] = length
72
+ end
73
+ end
74
+
75
+ class_file_name = name.downcase
76
+ if(File.exist?("lib/tds_packages/#{class_file_name}.rb"))
77
+ require "lib/tds_packages/#{class_file_name}"
78
+ class_name = class_file_name.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
79
+ cl = eval(class_name)
80
+ STREAM_CLASSES[token] = cl
81
+ end
82
+ }
83
+
84
+ def self.token?(token)
85
+ NAMES.include?(token)
86
+ end
87
+
88
+ def self.token_name(token)
89
+ NAMES[token]
90
+ end
91
+
92
+ def self.token_class(token)
93
+ STREAM_CLASSES[token]
94
+ end
95
+
96
+ def self.fixed_length(token)
97
+ FIXED_LENGTHS[token]
98
+ end
99
+
100
+ def self.length_field_size(token)
101
+ LENGTH_FIELD_SIZES[token]
102
+ end
103
+ end
104
+ end
data/lib/tds_types.rb ADDED
@@ -0,0 +1,94 @@
1
+ module Syspy
2
+ class TdsTypes
3
+ TYPES = [
4
+ [0x2f, "SYBCHAR" , "char" , -1, -1, 1, false, false, String ],
5
+ [0x27, "SYBVARCHAR" , "varchar" , -1, -1, 1, false, false, String ],
6
+ [0x26, "SYBINTN" , "int" , -1, 10, 11, true , false, Integer ],
7
+ [0x30, "SYBINT1" , "tinyint" , 1, 3, 4, false, false, Integer ],
8
+ [0x34, "SYBINT2" , "smallint" , 2, 5, 6, true , false, Integer ],
9
+ [0x38, "SYBINT4" , "int" , 4, 10, 11, true , false, Integer ],
10
+ [0x7f, "SYBINT8" , "bigint" , 8, 19, 20, true , false, Integer ],
11
+ [0x3e, "SYBFLT8" , "float" , 8, 15, 24, true , false, Float ],
12
+ [0x3d, "SYBDATETIME" , "datetime" , 8, 23, 23, false, false, Time ],
13
+ [0x32, "SYBBIT" , "bit" , 1, 1, 1, false, false, Integer ],
14
+ [0x23, "SYBTEXT" , "text" , -4, -1, -1, false, true , String ],
15
+ [0x63, "SYBNTEXT" , "ntext" , -4, -1, -1, false, true , String ],
16
+ [0xae, "SYBUNITEXT" , "unitext" , -4, -1, -1, false, true , String ],
17
+ [0x22, "SYBIMAGE" , "image" , -4, -1, -1, false, false, String ],
18
+ [0x7a, "SYBMONEY4" , "smallmoney" , 4, 10, 12, true , false, Integer ],
19
+ [0x3c, "SYBMONEY" , "money" , 8, 19, 21, true , false, Integer ],
20
+ [0x31, "SYBDATETIME4" , "smalldatetime" , 4, 16, 19, false, false, Time ],
21
+ [0x3b, "SYBREAL" , "real" , 4, 7, 14, true , false, Integer ],
22
+ [0x2d, "SYBBINARY" , "binary" , -1, -1, 2, false, false, String ],
23
+ [0x1f, "SYBVOID" , "void" , -1, 1, 1, false, false, nil ],
24
+ [0x25, "SYBVARBINARY" , "varbinary" , -1, -1, -1, false, false, String ],
25
+ [0xa7, "SYBNVARCHAR" , "nvarchar" , -1, -1, -1, false, false, String ],
26
+ [0x68, "SYBBITN" , "bit" , -1, 1, 1, false, false, Integer ],
27
+ [0x6c, "SYBNUMERIC" , "numeric" , -1, -1, -1, true , false, Integer ],
28
+ [0x61, "SYBDECIMAL" , "decimal" , -1, -1, -1, true , false, Integer ],
29
+ [0x6d, "SYBFLTN" , "float" , -1, 15, 24, true , false, Float ],
30
+ [0x6e, "SYBMONEYN" , "money" , -1, 19, 21, true , false, Integer ],
31
+ [0x6f, "SYBDATETIMN" , "datetime" , -1, 23, 23, false, false, Time ],
32
+ [0x31, "SYBDATE" , "date" , 4, 10, 10, false, false, Time ],
33
+ [0x33, "SYBTIME" , "time" , 4, 8, 8, false, false, Time ],
34
+ [0x7b, "SYBDATEN" , "date" , -1, 10, 10, false, false, Time ],
35
+ [0x93, "SYBTIMEN" , "time" , -1, 8, 8, false, false, Time ],
36
+ [0xaf, "XSYBCHAR" , "char" , -2, -1, -1, false, true , String ],
37
+ [0xa7, "XSYBVARCHAR" , "varchar" , -2, -1, -1, false, true , String ],
38
+ [0xe7, "XSYBNVARCHAR" , "nvarchar" , -2, -1, -1, false, true , String ],
39
+ [0xef, "XSYBNCHAR" , "nchar" , -2, -1, -1, false, true , String ],
40
+ [0xa5, "XSYBVARBINARY" , "varbinary" , -2, -1, -1, false, false, String ],
41
+ [0xad, "XSYBBINARY" , "binary" , -2, -1, -1, false, false, String ],
42
+ [0xe1, "SYBLONGBINARY" , "varbinary" , -5, -1, 2, false, false, String ],
43
+ [0x40, "SYBSINT1" , "tinyint" , 1, 2, 3, false, false, Integer ],
44
+ [0x41, "SYBUINT2" , "unsigned smallint", 2, 5, 6, false, false, Integer ],
45
+ [0x42, "SYBUINT4" , "unsigned int" , 4, 10, 11, false, false, Integer ],
46
+ [0x43, "SYBUINT8" , "unsigned bigint" , 8, 20, 20, false, false, Integer ],
47
+ [0x44, "SYBUINTN" , "unsigned int" , -1, 10, 11, true , false, Integer ],
48
+ [0x24, "SYBUNIQUE" , "uniqueidentifier" , -1, 36, 36, false, false, String ],
49
+ [0x62, "SYBVARIANT" , "sql_variant" , -5, 0, 8000, false, false, String ],
50
+ [0xbf, "SYBSINT8" , "bigint" , 8, 19, 20, true , false, Integer ],
51
+ [0xf1, "XML" , "xml" , -4, -1, -1, false, true , String ]
52
+ ]
53
+
54
+ NAMES = {}
55
+ RUBY_TYPES = {}
56
+ FIXED_LENGTHS = {}
57
+ SIGNED = {}
58
+
59
+ TYPES.each(){|type|
60
+ code = type[0]
61
+ name = type[1]
62
+ length = type[3]
63
+ signed = type[6]
64
+ ruby_type = type[8]
65
+
66
+ const_set(name,code)
67
+
68
+ NAMES[code] = name
69
+ FIXED_LENGTHS[code] = length
70
+ SIGNED[code] = signed
71
+ RUBY_TYPES[code] = ruby_type
72
+ }
73
+
74
+ def self.name(code)
75
+ NAMES[code]
76
+ end
77
+
78
+ def self.numeric?(code)
79
+ code == SYBNUMERIC || code == SYBDECIMAL
80
+ end
81
+
82
+ def self.fixed_length(code)
83
+ FIXED_LENGTHS[code]
84
+ end
85
+
86
+ def self.signed?(code)
87
+ SIGNED[code]
88
+ end
89
+
90
+ def self.ruby_type(code)
91
+ RUBY_TYPES[code]
92
+ end
93
+ end
94
+ end
data/syspy.rb ADDED
@@ -0,0 +1,63 @@
1
+ require "rubygems"
2
+ require "lib/log"
3
+ require "lib/tds_package_stream"
4
+ require "time"
5
+
6
+
7
+ module Syspy
8
+ if(__FILE__ == $0)
9
+ if(ARGV.size != 3)
10
+ puts "Usage: sudo ruby syspy.rb <interface> <destination_ip> <destination_port>"
11
+ exit(1)
12
+ end
13
+
14
+ if(`id -u`.strip != "0")
15
+ puts "Has to be run as root"
16
+ exit(2)
17
+ end
18
+
19
+ INTERFACE = ARGV[0]
20
+ DST = ARGV[1]
21
+ DST_PORT = ARGV[2]
22
+
23
+ # INTERFACE = "eth0"
24
+ # DST = "192.168.1.6"
25
+ # DST_PORT = "2048"
26
+
27
+ stream = TdsPackageStream.new(INTERFACE,DST,DST_PORT)
28
+ stream.each_package(){|package|
29
+ if(package.instance_of?(TdsLanguage))
30
+ statement = package.language_text
31
+ replaced_statement = "#{statement}"
32
+
33
+ index = 0
34
+ if(package.tds_params)
35
+ params = package.tds_params.parameters
36
+ statement.scan(/@sql\d+[^ ]+/){|match|
37
+ param = params[index]
38
+ if(param.instance_of?(String))
39
+ replaced_statement.gsub!(match,"\"#{param}\"")
40
+ elsif(param.kind_of?(Numeric))
41
+ replaced_statement.gsub!(match,param.to_s)
42
+ elsif(param.instance_of?(Time))
43
+ replaced_statement.gsub!(match,"\"#{param.strftime("%Y%m%d %H:%M:%S")}\"")
44
+ end
45
+ index += 1
46
+ }
47
+ end
48
+ Log.info("Replaced parameters: #{index}\n\n#{replaced_statement.gsub("\n","\r\n")}\n------------------------------------------------------")
49
+ end
50
+ }
51
+ end
52
+ end
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: syspy
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matthias Balmer
@@ -40,6 +40,17 @@ extensions: []
40
40
  extra_rdoc_files: []
41
41
 
42
42
  files:
43
+ - syspy.rb
44
+ - lib/bytes.rb
45
+ - lib/tds_types.rb
46
+ - lib/tds_tokens.rb
47
+ - lib/tds_package_stream.rb
48
+ - lib/tds_packages/tds_paramfmt2.rb
49
+ - lib/tds_packages/tds_params.rb
50
+ - lib/tds_packages/tds_paramfmt.rb
51
+ - lib/tds_packages/tds_language.rb
52
+ - lib/log.rb
53
+ - lib/tds_package.rb
43
54
  - bin/syspy
44
55
  homepage:
45
56
  licenses: []