Spontaneous Open Source Initiative

by Josh Patterson 23. July 2011 17:41

After nearly 15 years of hammering out tons of code on my personal time and guarding it like it was some sort of valuable trade secrete. My pet project (NetworkDLS) has decided to go open source.

How open source? Well, how about the full source code, installer scripts, documentation code, supplimental build tools and build instructions for each and evey one of our projects - under the MIT licence. You can sell it, compile it, customize and imbed it.

All official release will still be made to NetworkDLS.com, but the development process, nug tracking and change sets will be made publicly available at CodePlex.

Please, do me a huge favor and find some use in this effort!

>> NetworkDLS CodePlex <<

 

Tags: , , ,

SQL and SQL only: Identifying Page Splits

by Josh Patterson 7. September 2010 10:37

Today, I read a comprehensive article by Nagaraj Venkatesan related to getting a handle on SQL Server Page Splits. If you manage any SQL servers than I strongly recommend that you read this article... simply fantastic!

 

SQL and SQL only: Identifying Page Splits - by Nagaraj Venkatesan

Tags: , ,

Miscellaneous

A tribute to Jacob Navia and my favorite compiler: LCC-Win32

by Josh Patterson 3. August 2010 12:14

It seems like more than a decade that I've been going back to that Virginia University page for a copy of lcc-win32. What's more is the fact that I have totally read and nearly memorized the copy of the "Windows API documentation" whose link is now defunct.


The simplicity of the build process was beautiful, the size of the created executables remains still to this day the smallest I've ever seen. If only the compiler and linker utilized better optimizing algorithms, I'd probably still be using it to this day for production coding.

Batch Build process:

lcc -O -unused -c Test.C
lcclnk -s -subsystem:console -o Test.Exe Test.obj

It should be noted, that I still use this compiler for hobbyist applications and still have hundreds of applications that compile flawlessly using both GCC and lcc-Win32!

Tags: , , ,

Miscellaneous

Exploited antique code warning, not for the faint of heart!!

by Josh Patterson 2. August 2010 12:12

In case you are not following, I’ll reiterate: This is old code so don’t give me grief. How old is the code?? I’m not sure exactly, but I was in Jr. High at the time. So again, no jabbing me for "crap code"!

Ok, the main() function has been fudged to show the purpose and functionality of the vulnerable procedure: "ParseRequest(...)"

The idea was to search for different parameters that were being passed over from an anonymous TCP/IP connection and then parse off the parameter text which would always be terminated by a line feed character (or optional carriage return character).

Can you spot the vulnerabilities? This code makes many assumptions about the "perfectly trustworthy" and "completely bug free" remote peer. This is a prime example of bad code.

We have potential underflows, overflows, and injection possibilities, potential out-of-bounds memory reading and writing, ect, ect... or to put it in layman's terms: this application would only have been "safe" if it were run on a machine with no networking capabilities period!

//-----------------------------------------------------------------------
char *ParseRequest(const char *sInput, char *sOutput)
{
 size_t iLen = strlen(sInput);
 size_t r = 0; //Read position.
 size_t w = 0; //Write position.
 
 //Skip the parameter marker.
 while(r == 0 || sInput[(r == 0 ? 1 : r) - 1] != ' ')
 {
  r++;
 }
 
 //Parse the parameter value.
 while(r < iLen && sInput[r] != '\r' && sInput[r] != '\n')
 {
  sOutput[w++] = sInput[r++];
 }
 
 sOutput[w] = 0; //NULL terminator.
 
 return sOutput;
}
 
//-----------------------------------------------------------------------
 
int main(int argc, char *argv[])
{
 char input[1024];
 char output[255];
 
 strcpy(input,
  "/P1 Param text 1\n"
  "/P2 Param text 2\n"
  "/P3 Param text 3\n"
  "/P4 Param text 4\n");
 
 for(size_t i = 0; i < strlen(input); i++)
 {
  if(input[i] == '/')
  {
   ParseRequest(input + i, output);
   printf("%s\n", output);
  }
 }
 
 return 0;
}
 
//-----------------------------------------------------------------------

 

Hints:

  1. What would happen if the input wasn’t null nor carriage-return / line feed terminated?
  2. What would happen if the input or any one of the parameter values were greater than 255 characters?
  3. What would happen if the input contained no spaces between the parameter name (/P1) and its value (Param Text 1).
  4. What if there were no spaces in the param text in conjunction with a missing space between the parameter name and its value?

The answer to all four questions? Hopefully a program crash! Otherwise malicious code could easily be injected for your happy application to execute!

Tags: , , ,

Miscellaneous

What to hack, what to crack? I said we'd go over exploits!

by Josh Patterson 1. August 2010 12:10

Interestingly enough, just a week after I posted to my blog about the possibility of an entry about exploits, I receive an email about an exploit of one of my oldest (and most embarrassing) socket applications: "Finger Server". If you're under 20 years old at the time of this posting then you may need to perform a search for the term "finger Protocol".

I do not really care much for this application anymore but I'm not going to leave a utility with a known vulnerability available via a security website. That wouldn't seem right.

So, what's the exploit? What might one gain from exploiting the server? How can I fix it?

Fortunately, these are all pretty easy to answer when it comes to this application, mainly, because I have the source code and secondly because the heart of the program is only roughly 50 lines of C code. Yea, that'll be easy to patch up!

Tags:

Miscellaneous

Updates... Updates... Updates...

by Josh Patterson 26. June 2010 12:09

The replication issues may be comming to a close. Errors are now being skipped as well as erroneous LSNs.

I have already started on my next technical post so it shouldn't be long now.

Tags: ,

Miscellaneous

Replication Woes

by Josh Patterson 22. June 2010 11:58

I haven't forgotten about you, I'm suffering from a potentially fatal case of the "MSSQL Replication Woes".

Tags:

So I'm masochistic, whats your problem?

by Josh Patterson 18. June 2010 11:53

While I enjoy programming (and posting tons of source code), I promise to delve into something less technical in the me-centric kind of way. Tell you what: next week I'll go technical in the exploit-centric kind of way. What do you want to destroy?
 
Though... the though process: "Exploit" to "Buffer Overrun" to "Denial of Service" to "Distributed Denial of Service" does have me leaning towards an article on distributed computing... which is of course my gravy.
 
We'll see what next week brings!

Tags:

Sockets: The foundation of a computer's social life

by Josh Patterson 17. June 2010 12:05
From experience, sockets in C/C++ can be very off-putting. This is "not so" in the case of (near post-modern) languages with a greater level of abstraction (Python, C#, VB.NET, ect, ect) but for good ol' Win32 – you've got your work cut out for you.
 
All this work is not without its rewards! You can create blocking mode clients, asynchronous load-balanced services, super-high throughput applications and seriously reliable programs using only a few simple functions in WinSock.
 
As a side note, it should be known that "WinSock" should seriously be called BSDSock as it was an outright copy from BSD – the windows source code even bears the BSD copyright notices (though I've heard through the grape-vine that Microsoft has rewritten the IP-Stack while in the process of building up support for IPv6 – but that is only speculation on my end).
 
I've highly commented and trimmed down this not-so-fully featured web server for your enjoyment!
#include "windows.h"
#include "winsock.h"
#include "stdio.h"

//be sure to include the linker library: wsock32.lib

#define MAX_CONNECTIONS 25
#define MAX_RECV_SIZE 8120

int main(int argc, char *argv[])
{
 SOCKET listenSocket = NULL; //The socket that will listen for new connections.
 SOCKET peerSockets[MAX_CONNECTIONS];
 SOCKET peerBytesSent[MAX_CONNECTIONS];

 struct timeval tTimeOut; // The TimeOut structure.
 tTimeOut.tv_sec = 1;
 tTimeOut.tv_usec = 0;

 //These are used to identify if a socket is ready
 // for reading, writing or is experiencing an exception.
 fd_set fdRead;
 fd_set fdWrite;
 fd_set fdExcept;

 WORD WSARequiredVersion = 0x0101; // Version 1.1
 WSADATA WSAData;
 WSADATA *WSAPointerData = &WSAData;
 if(WSAStartup(WSARequiredVersion, WSAPointerData) != 0)
 {
  printf("Failed to initialize WinSock: %d\n", WSAGetLastError());
  return 1;
 }

 // Fill In The Address Structure For Local Server
 SOCKADDR_IN localSockAddress; // Socket address of local server
 localSockAddress.sin_family      = AF_INET;    // Address Family.
 localSockAddress.sin_addr.s_addr = INADDR_ANY; // Library assigned address.
 localSockAddress.sin_port   = htons(80);  // Port Number.

 // Create A TCP/IP Stream Socket To "Listen" with.
 if((listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
 {
  printf("Failed to create socket: %d\n", WSAGetLastError());
  WSACleanup();
  return 1;
 }

 // Bind The Name To The Socket.
 if(bind(listenSocket, (SOCKADDR*)&localSockAddress, sizeof(struct sockaddr)) == SOCKET_ERROR)
 {
  printf("Bind failed: %d\n", WSAGetLastError());
  closesocket(listenSocket);
  WSACleanup();
  return 1;
 }

 // Set The Socket To Listen.
 if(listen(listenSocket, MAX_CONNECTIONS) == SOCKET_ERROR)
 {
  printf("Listen failed: %d\n", WSAGetLastError());
  closesocket(listenSocket);
  WSACleanup();
  return 1;
 }

 memset(&peerSockets, 0, sizeof(SOCKET) * MAX_CONNECTIONS);
 memset(&peerBytesSent, 0, sizeof(int) * MAX_CONNECTIONS);

 //---------------------------------------------------------

 while(true)
 {
  // Zero the Read, Write and Except descriptors.
  FD_ZERO(&fdRead);
  FD_ZERO(&fdWrite);
  FD_ZERO(&fdExcept);

  //Add the listen socket to the descriptor array.
  FD_SET(listenSocket, &fdRead);
  FD_SET(listenSocket, &fdExcept);

  //Add all connected sockets to the descriptor array.
  for(int i = 0; i < MAX_CONNECTIONS; i++)
  {
   if(peerSockets[i])
   {
    FD_SET(peerSockets[i], &fdRead);
    FD_SET(peerSockets[i], &fdWrite);
    FD_SET(peerSockets[i], &fdExcept);
   }
  }

  //Socket Select. This will figure out the disposition
  // of all the sockets in the descriptor array.
  if(select(-1, &fdRead, &fdWrite, &fdExcept, &tTimeOut) == SOCKET_ERROR)
  {
   printf("Select failed: %d\n", WSAGetLastError());
   closesocket(listenSocket);
   break;
  }

  //Are there any waiting connections?
  if(FD_ISSET(listenSocket, &fdRead))
  {
   int iLength = 0;
   SOCKET peerSocket = 0;

   SOCKADDR_IN remoteSockAddr;
   int iAddressLength = sizeof(SOCKADDR);

   //Accept the connection.
   peerSocket = accept(listenSocket, (SOCKADDR*)&remoteSockAddr, &iAddressLength);

   if(peerSocket == SOCKET_ERROR)
   {
    printf("Accept failed: %d\n", WSAGetLastError());
    closesocket(listenSocket);
    break;
   }
   else if(peerSocket == 0)
   {
    printf("Accept failed (gracefully): %d\n", WSAGetLastError());
    closesocket(listenSocket);
    break;
   }

   bool bFoundFreeSocket = false;

   //Find a free socket in the socket array.
   for(int i = 0; i < MAX_CONNECTIONS; i++)
   {
    if(peerSockets[i] == NULL)
    {
     peerSockets[i] = peerSocket;
     bFoundFreeSocket = true;
     break;
    }
   }

   if(!bFoundFreeSocket)
   {
    printf("No free sockets\n");
    closesocket(listenSocket);
   }
  } //if(FD_ISSET(listenSocket, &fdRead))
  
  //Check the disposition of each connected socket.
  for(int i = 0; i < MAX_CONNECTIONS; i++)
  {
   if(peerSockets[i])
   {
    //Is data waiting to be received?
    if(FD_ISSET(peerSockets[i], &fdRead))
    {
     char recvBuffer[MAX_RECV_SIZE];
     int recvLength = recv(peerSockets[i],
      recvBuffer, sizeof(recvBuffer), 0);

     if(recvLength == SOCKET_ERROR)
     {
      //Disconnect the socket.
      closesocket(peerSockets[i]);
      peerSockets[i] = NULL;
      peerBytesSent[i] = 0;
     }
     else if(recvLength == 0) // Gracefull disconnect.
     {
      //Disconnect the socket.
      closesocket(peerSockets[i]);
      peerSockets[i] = NULL;
      peerBytesSent[i] = 0;
     }
     else{
      recvBuffer[recvLength] = '\0';
      printf("Received %d bytes: \"%s\"\n", recvLength, recvBuffer);
     }
    }

    //Is the socket ready to accept data?
    if(FD_ISSET(peerSockets[i], &fdWrite))
    {
     //Send some data back to the connected peer.

     char *sendBuffer = "Hello World";

     int bytesSent = send(peerSockets[i], sendBuffer, strlen(sendBuffer), 0);
     if(bytesSent == SOCKET_ERROR)
     {
      int iLastError = WSAGetLastError();
      if(iLastError == WSAEWOULDBLOCK || iLastError == WSAEINPROGRESS)
      {
       //Do nothing, try to send again on the the next go-round.
      }
      else{
       //Disconnect the socket.
       closesocket(peerSockets[i]);
       peerSockets[i] = NULL;
       peerBytesSent[i] = 0;
      }
     }
     else if(bytesSent == 0)
     {
      //Disconnect the socket.
      closesocket(peerSockets[i]);
      peerSockets[i] = NULL;
      peerBytesSent[i] = 0;
     }
     else {
      //Data was sent successfully!

      //Keep track of how much data we sent to each socket.
      peerBytesSent[i] += bytesSent;


      //Disconnect after sending more than 1KB od data.
      if(peerBytesSent[i] > 1024)
      {
       //Disconnect the socket.
       closesocket(peerSockets[i]);
       peerSockets[i] = NULL;
       peerBytesSent[i] = 0;
      }
     }
    }

    //Is the socket in an error state?
    if(FD_ISSET(peerSockets[i], &fdExcept))
    {
     //Disconnect the socket.
     closesocket(peerSockets[i]);
     peerSockets[i] = NULL;
     peerBytesSent[i] = 0;
    }
   }
  }

  Sleep(1); //Give the CPU some breathing time.
 }

 //---------------------------------------------------------

 //Stop listening.
 closesocket(listenSocket);

 if(WSACleanup() == SOCKET_ERROR)
 {
  printf("Failed to cleanup WinSock: %d\n",
   WSAGetLastError());
  return 1;
 }

 return 0;
}

Now clearly there are more to sockets than this post covers (such as non-blocking asynchronous sockets) but trust me, this is 10 fold more than my first socket application.

Tags: , , , ,

Miscellaneous

Memory leaks? Track those allocations and plug the hole(s)!

by Josh Patterson 16. June 2010 12:05

I've written applications that were bad and I’ve written some that were perfect, though it took me years to figure out why a few of the perfect applications were chewing 75% of my RAM. No matter, their still perfect to me...
 
On a serious note, have you ever written any C or C++ code? Yes? Good - Then you are already familiar with memory leaks!
 
Memory leaks occur when you allocate RAM and do not free it. On modern OS's these memory leaks are only potentially detrimental for the lifetime of the running application, that is, the badly managed resources are cleaned up after the leaky application is closed (or unexpectedly terminated). That said, memory leaks really begin to haunt you when writing long running applications or more specifically: services.
 
These leaks can be more than frustrating, I've turned my back on applications that I've dedicated years to because the manor of the memory's escaped was just too elusive (e.g. I've written bad applications).
 
How can we solve such a problem? Well, you can either attempt to be perfect and (on near certain failure) dump five times the development time into debugging or… use some manner of memory tracker.
 
I developed one of these "memory trackers" that I now include in all of my C++ projects – yes, even the small ones – you never know what they’ll grow into.
 
I call this magic tool: CMemoryPool (though, it's not really a memory pool).
 
How's it work? Well it’s simple really - it has 4 modes which are set by defining preprocessors.
 
Modes of Operation:

Disabled
In disabled mode, the memory tracker code is collapsed down to calls to your native malloc(), calloc(), and realloc(). Fully optimized - this mode is for the final release of your product.
 
General
In general mode, the memory tracker will keep track of the allocations that your program makes and raise a debug break when the class is deconstructed if all of the allocations that it witnessed were not cleaned up properly. This mode is faster than the following modes and that's pretty much the end of its advantages.
 
Advanced
In advanced mode (which should have been called "default mode"), the memory tracker will keep track of each allocation that your application makes as well as the number of bytes per allocation and the source code file name and the line number in the source file that the allocation originated from. Much like the previous mode, the class will trigger a debug break when the class is deconstructed if your application has not been well behaved.
 
Verbose
Verbose mode is slow. It's actually more than slow but I don’t want to appear dramatic by telling you that it's "insanely slow" or "near unusable" - despite the fact that these statements would be true. This mode functions exactly like the previous mode (Advanced) but it additionally opens a console (if you didn’t already open one) and prints verbose information about every memory allocation, reallocation and free to the console. Yea, you think memory allocation is slow now – try Verbose mode!
 
One last thing that should be noted about the memory tracker is that it is multi-thread safe – very multi-tread safe. It’s even safe to use with non-multi-thread safe standard libraries. This functionality can be disabled when running in the final "disabled" mode for your final release by ensuring that the "Sequential When Optimized" preprocessor is not defined in the class header.
 
You're not still reading are you? ....I call B.S.
 
Well, if your that interested, grab a copy of the CMemPool and start saving time!!

 

Tags: , , ,

Miscellaneous

About the author

My goal is to expand my horizons and to seek knowledge wherever it may lie. I am motivated by sheer yearning and interest in the technical & complex.

Please note however; that "interest" does not necessarily imply understanding.

Month List

Page List