The following is the source code to the Sybase version- grabbing tool mentioned earlier in this chapter. It is written for the Windows platform.
// sybaseversion.cpp // Chris Anley [chris@ngssoftware.com] #include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock.h> #include <time.h> int syntax() { printf("syntax: sybaseversion <host> <port>\n"); return 1; } int err( char *psz ) { printf("%s\n", psz ); return 0; } int init_sockets() { int ret=0; WORD wVersionRequested; WSADATA wsaData; // Initialise Winsock in this thread wVersionRequested = MAKEWORD( 2, 0 ); ret = WSAStartup( wVersionRequested, &wsaData ); if ( ret != 0 ) return err( "Couldn't start sockets" ); if ( LOBYTE( wsaData.wVersion ) != 2 HIBYTE( wsaData.wVersion ) != 0 ) return err( "Wrong version of sockets" ); return 1; } int create_tcp_socket() { return (int)socket( AF_INET, SOCK_STREAM, 0 ); } int set_timeout( int socket, int timeout_milliseconds ) { if ( setsockopt( socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout_milliseconds, sizeof( int ) ) != 0 ) return 0; if ( setsockopt( socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout_milliseconds, sizeof( int ) ) != 0 ) return 0; return 1; } int bind_to_port( int socket, int port ) { struct sockaddr_in sa; int ret; sa.sin_port = htons( (short)port ); sa.sin_family=AF_INET; sa.sin_addr.s_addr = INADDR_ANY; ret = bind( socket, (struct sockaddr *)&sa, sizeof( struct sockaddr ) ); if ( ret != 0 ) return err("Couldn't bind to port. Maybe something is already" " using it?"); return 1; } int set_listen( int socket ) { if ( listen( socket, SOMAXCONN ) != 0 ) return 0; return 1; } int get_new_connection_socket( int socket, unsigned int *connectinghost, int *ps ) { int sc; struct sockaddr_in client; sc = (int)accept( socket, (struct sockaddr *)&client, NULL ); if ( sc == INVALID_SOCKET ) { //ret = WSAGetLastError(); return err( "Error immediately after receiving" "connection\n" ); } *connectinghost = (unsigned int)client.sin_addr.S_un.S_addr; *ps = sc; return 1; } int connect_to( int socket, char *host, unsigned short port ) { struct sockaddr_in sa; int i, len, alpha = 0; struct hostent *he; unsigned long addr; len = (int)strlen( host ); for( i = 0; i < len; i++ ) { if( isalpha(host[i]) ) { alpha = 1; break; } } if( alpha ) { he = gethostbyname(host); if ( he == NULL) return 0; } else { if ( len > 16 ) // xxx.xxx.xxx.xxx return 0; // just use the ip address addr = inet_addr( host ); if ( addr == INADDR_NONE ) return 0; he = gethostbyaddr( (char *)&addr, 4, AF_INET ); sa.sin_addr.s_addr = addr; } sa.sin_family=AF_INET; sa.sin_port = htons( port ); if ( connect( socket, (struct sockaddr *)&sa, sizeof( struct sockaddr ) ) == SOCKET_ERROR ) return 0; return 1; } int receive_data( int socket, char *buffer, int length, int *bytes ) { int ret; ret = recv( socket, buffer, length, 0 ); *bytes = ret; if ( ret > 0 ) return 1; return 0; } int send_data( int socket, char *buffer, int length, int *bytes ) { int ret = send( socket, buffer, length, 0 ); *bytes = ret; if ( ret == 0 ) return 0; return 1; } int close_socket( int socket ) { closesocket( socket ); return 1; } int dump_buff( unsigned char *psz, int bytes, int file_no ) { for( int i = 0; i < bytes; i++ ) { printf("\x%02x", psz[i] ); } printf("\n\n"); return 1; } int main( int argc, char * argv[] ) { unsigned char auth[] = "\x02" // packet type = TDS 4.2 or 5.0 login packet "\x01" // last packet indicator = 1 : last packet "\x02\x00" // packet size: 512 bytes "\x00\x00\x00\x00" // 4 bytes; purpose unknown "XXXXXXX\x00\x00\x00" // 30 bytes: Host name (XXXXXXX) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x07" // host name length "XX\x00\x00\x00\x00\x00\x00\x00\x00" // 30 bytes: User name "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x02" // user name length "XXXXXXXXXX" // 30 bytes: password "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x0a" // password length // 30 bytes: process "\x31\x31\x35\x32\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x04" // process length "\x03\x01\x06\x0a\x09\x01" // 6 bytes of mystery stuff "\x01" // bulk copy = 1 "\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 9 bytes "SQL_Advant" "age\x00\x00\x00\x00\x00\x00\x00" // 30 bytes: app name "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x0d" // app name length "XXXXXXX\x00\x00\x00" // 30 bytes: server name "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x07" // server name length "\x00" // 1 mystery byte "\x0a" // password2 length "XXXXXXXXXX" // 30 bytes: password 2 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // 223 bytes of null (?) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00" // end 223 null bytes "\x0c" // password2 length + 2 "\x05\x00" // TDS Major version = 5 "\x00\x00" // TDS Minor version = 0 "CT-Library" // Library name "\x0a" // Library name length "\x05\x00" // program major version = 5 "\x00\x00" // program minor version = 0 "\x00\x0d\x11" // Magic 3 bytes // language 30 bytes... except we truncate "\x00s_english" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00"; int s, sent, received, i; char buff[ 8192 ]; memset( buff, 0, sizeof( buff ) ); if( !init_sockets() ) return err("Couldn't initialise sockets"); s = create_tcp_socket(); if (!connect_to( s, argv[1], atoi( argv[2]) )) return err("Couldn't connect"); if( !send_data( s, (char *)auth, sizeof( auth ), &sent )) return err("Couldn't send auth packet"); if( !receive_data( s, buff, 8180, &received )) return err("No data received"); if( !close_socket( s )) return err("Error closing socket"); dump_buff( (unsigned char *)buff, received, 0 ); for( i = 0; i < received; i++ ) { if( strnicmp( &(buff[i]), "SQL Server", strlen("SQL Server")) == 0 ) { i += (int)strlen( "SQL Server" ); printf("Sybase Version: %d.%d.%d.%d\n", buff[i], buff[i+1], buff[i+2], buff[i+3] ); break; } } return 0; }