2009
03.19

Multithreading

Hi people,
As some of you may know, I’ve been working on SSH Cr4x0r.
SSH stands for Secure shell.
It is a server which provides remote terminal/command line access.
It usually requests a username/password combination.
The program I made launches an attack against a single server,
trying to login with all the possible passwords and users provided by the user.
What makes this cracker ‘good’ is multi-threading!

Making an application multithreaded means having several threads,
several functions running at the same time. This may look simple,
and not complicated, but there are certain ‘problems’ that could appear.
The most important factor of multithreading is synchronization!
Syncronizing threads means making them organize operations on shared resources.
Shared resources are often global variables or a variable which is pointed
to by many pointers, each used by a single thread, or a file, etc.
So you think “I can just make this:”

//Globally define
char i = 0;
 
void myThread()
{
	FILE *f;
 
	while(i)		// While resources are being used
		Sleep(10);	// Wait
	i = 1;			// Lock resources so they can't be accessed by other threads
	if(f = fopen("bla.txt", "wb"))	// Access resources
		fclose(f);			// Access resources
	i = 0; // Unlock resources so other threads can access them
}

But NO!
This cannot be used in threads. Threads CANNOT synchronize by themselves.
The reason is simple.
A thread is waiting to access the resource. In the moment i becomes 0,
the thread proceeds to the next line of code. However, in the way that the OS manages threads,
The current thread may be stopped for a while to let another thread work.
The other thread also finds i to be 0.
In this point both threads are at the same code line:
i = 1;
So this second thread executes fopen, and there is where execution stops for the first thread to resume.
The resource is already accessed by the second thread, so when the first thread executes fopen, BANG, it wont access “bla.txt”
because it is already being written by the second thread.
This could be fixed with a ‘synchronizer’ thread, and a stack.
Here is a basic scheme:

// The stack is made of char pointers (char *)
// When the pointers value *p is set to 1 (from 0),
// the thread that has *p is allowed to access the resource.
 
void syncThread()
{
	while(TRUE) {
		// if there are any requests in stack
		if(!is_stack_empty()) {
			char *p = stack_pop();
 
			if(p == NULL) // If stack_pop returned NULL, continue with the loop
				continue;
			*p = 1; // Set *p to 1 (let the thread access the resource)
			while(*p) // Wait for *p to become 0 again, when *p becomes 0 it indicates that the thread has finished accessing the resource.
				Sleep(10);
			*p = 1; // Verify that usage of resources ending has been understood
		}
	}
}
 
void myThread()
{
	FILE *f;
	char local_p = 0;
 
	stack_push(&local_p); // Add request to the stack
	while(!local_p)		// Wait for syncThread to allow usage of resources
		Sleep(10);
	if(f = fopen("bla.txt", "wb"))	// Access resources
		fclose(f);	// Access resources
	local_p = 0; // Set local_p to 0
	while(!local_p) // Wait for syncThread to verify that it has understood that myThread has finished using the resources
		Sleep(10);
}

And that’s it, a simple, yet working synchronizing system.
And it’s crossplatform too.
But we’re using windows… It already provides these functions.
There are three ways in windows for complete synchronization.
1. Semaphores
2. Mutexes
3. Critical sections
I will be using mutexes.
The functions used are CreateMutex, CloseHandle, WaitForSingleObject and ReleaseMutex.
Please refer to the documentation if you want to know the details of these functions.
First of all, we must have a thread creator thread. I prefer to do this in another thread when I’m using GUI’s, so I don’t block the redrawing & refreshing of the window.

HANDLE g_hMutex = NULL;
void initProc()
{
	// First, create the mutex
	if((g_lock = CreateMutex(NULL, TRUE, "MYMUTEX__22123")) == NULL) {
		// Handle error
		goto cleanup;
	}
	//Since bInitialOwner is TRUE we must release the mutex, so the new created threads can use it.
	ReleaseMutex(g_lock);
 
	// ...
 
cleanup:
	if(g_lock != NULL)
		CloseHandle(g_lock);
}

Alright, so we got ourselves a mutex ready to synchronize the threads.
I’ve made these two macros for easiness:

#define __xlock() { \
	if(g_lock != NULL) \
		WaitForSingleObject(g_lock, INFINITE); \
}
 
#define __xrelease() { \
	if(g_lock != NULL) \
		ReleaseMutex(g_lock); \
}

__xlock() tries to get ownership of g_lock
If another thread owns g_lock, WaitForSingleObject waits for the thread to release it, and then it gets the ownership.
INFINITE means that it will wait infinitely for the other thread to release the mutex.

__xrelease() simply releases the mutex.

Well, this ends it i think. Here is a basic skeleton for multithreading:

#define MY_MUTEX_NAME "MYMUTEX__22123"
#define __xlock() { \
	if(g_lock != NULL) \
		WaitForSingleObject(g_lock, INFINITE); \
}
 
#define __xrelease() { \
	if(g_lock != NULL) \
		ReleaseMutex(g_lock); \
}
 
HANDLE g_lock = NULL;
 
void myThread()
{
	FILE *f;
 
	__xlock();
	if(f = fopen("bla.txt", "wb"))	// Access resources
		fclose(f);			// Access resources
	__xrelease();
cleanup:
	CloseHandle(GetCurrentThread());
}
 
void initProc()
{
	if((g_lock = CreateMutex(NULL, TRUE, MY_MUTEX_NAME)) == NULL) {
		MessageBox(0, "Could not create mutex.", "Error!", MB_OK | MB_ICONERROR);
		goto cleanup;
	}
	ReleaseMutex(g_lock);
 
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)myThread,
		0, 0, NULL);
 
cleanup:
	if(g_lock != NULL)
		CloseHandle(g_lock);
}
 
int main(void)
{
	initProc();
	return 0;
}

Remember:
* When modifying GUI controls always synchronize threads.
* When modifying files (reading does not count) always synchronize threads.
* When freeing and allocating memory and storing the address in the same pointer always synchronize threads.
* When using global variables always synchronize threads.
* When you see it necessary always synchronize threads. :p

I hope you enjoyed it :)
Feel free to ask/correct about anything.
[edit] Sorry comments’ indentation got a bit messed up

3 comments so far

Add Your Comment
  1. I read your blog in a regular manner, and your way of writing is just awesome.
    Please keep going, smile
    your sierra

  2. Hi, gr8 post thanks for posting. Information is useful!

  3. I have been looking for this everywhere, thanks!