Multiple Threads: New protection mechanism

Joined
Apr 4, 2009
Messages
898
Reaction score
157
Another idea I had for executable protection: an application relying on threads to modify registers to change the control and flow of an application.

For example, Thread 1 launches Thread 2; Thread 2 suspends Thread 1, then changes the EIP/RIP to point to a different function, and resumes; in this new function, Thread 1 executes some permutated/obfuscated code, then alters Thread 2 to execute in a similar manner.

CC?

EDIT:

Quick example:

Code:
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma comment( linker, "/SUBSYSTEM:WINDOWS" )
#pragma comment( linker, "/ENTRY:main" )

DWORD CurrentThread = 1;
HANDLE MainThreadHandle, SecondaryThreadHandle;
DWORD MainThreadId;

void Test( )
{
	MessageBox( 0, "Redirected", "", MB_OK );
}

void SecondaryThread( )
{
	CONTEXT ctx;
	ctx.ContextFlags = CONTEXT_FULL;
	MainThreadHandle = OpenThread( THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE, MainThreadId );
	GetThreadContext( MainThreadHandle, &ctx );
	ctx.Eip = ( DWORD_PTR ) Test;
	SuspendThread( MainThreadHandle );
	SetThreadContext( MainThreadHandle, &ctx );
	ResumeThread( MainThreadHandle );
	CloseHandle( MainThreadHandle );

	CurrentThread = 0;
}

void main( )
{
	MainThreadId = GetCurrentThreadId( );
	CreateThread( 0, 0, ( LPTHREAD_START_ROUTINE ) SecondaryThread, 0, 0, 0 );
	while( CurrentThread )
		Sleep( 10 );
}
 
Last edited:
well, it's certainly creative, but i think you're throwing practicality out the window

might be worthwhile to do it once at the beginning of your code to obfuscate entry, but writing a whole program like this would probably not be a worthwhile tradeoff for security, as the source code would be just as hard to read as the assembly

i suppose you could implement it as a macro or class of some sort to improve readability

going to take a closer look at this cause i'm really bored right now
 
well, it's certainly creative, but i think you're throwing practicality out the window

might be worthwhile to do it once at the beginning of your code to obfuscate entry, but writing a whole program like this would probably not be a worthwhile tradeoff for security, as the source code would be just as hard to read as the assembly

i suppose you could implement it as a macro or class of some sort to improve readability

going to take a closer look at this cause i'm really bored right now

You wouldn't necessarily write applications like this; rather, they'd be protected like this, for at least the initialization of your code.
 
You wouldn't necessarily write applications like this; rather, they'd be protected like this, for at least the initialization of your code.

well, that does sound like a good idea, but i wouldn't know how to implement it

here's the results of my experimentation (tested working, of course)

Code:
#include <stdio.h>
#include <windows.h>

typedef struct THREADID_AND_TARGET{
DWORD threadid;
DWORD target;
} THREAD_AND_TARGET;

void SetEIP(THREADID_AND_TARGET* A){
THREADID_AND_TARGET* a = (THREADID_AND_TARGET*)A;
HANDLE b = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE, a->threadid);
CONTEXT c;
c.ContextFlags = CONTEXT_FULL;
SuspendThread(b);
GetThreadContext(b, &c);
c.Eip = a->target;
SetThreadContext(b, &c);
ResumeThread(b);
CloseHandle(b);
}

#define CJmp(A) \
	{ \
	THREADID_AND_TARGET __THREADID_AND_TARGET = {GetCurrentThreadId(), (DWORD)A}; \
	CreateThread(0, 0, (LPTHREAD_START_ROUTINE)SetEIP, &__THREADID_AND_TARGET, 0, 0); \
	for(;;); \
	}

void print(){
printf("Hello, world!\n");
}

int main(){
_asm push retn_here
CJmp(print);
_asm retn_here:
return 0;
}
 
well, that does sound like a good idea, but i wouldn't know how to implement it

here's the results of my experimentation (tested working, of course)

Code:
#include <stdio.h>
#include <windows.h>

typedef struct THREADID_AND_TARGET{
DWORD threadid;
DWORD target;
} THREAD_AND_TARGET;

void SetEIP(THREADID_AND_TARGET* A){
THREADID_AND_TARGET* a = (THREADID_AND_TARGET*)A;
HANDLE b = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME, FALSE, a->threadid);
CONTEXT c;
c.ContextFlags = CONTEXT_FULL;
SuspendThread(b);
GetThreadContext(b, &c);
c.Eip = a->target;
SetThreadContext(b, &c);
ResumeThread(b);
CloseHandle(b);
}

#define CJmp(A) \
	{ \
	THREADID_AND_TARGET __THREADID_AND_TARGET = {GetCurrentThreadId(), (DWORD)A}; \
	CreateThread(0, 0, (LPTHREAD_START_ROUTINE)SetEIP, &__THREADID_AND_TARGET, 0, 0); \
	for(;;); \
	}

void print(){
printf("Hello, world!\n");
}

int main(){
_asm push retn_here
CJmp(print);
_asm retn_here:
return 0;
}

I don't really see why inline ASM is required there, when setjmp works, or dynamically linking.
 
I don't really see why inline ASM is required there, when setjmp works, or dynamically linking.

i went with inline asm because it was the easiest solution

setjmp would be harder to implement, but it might allow for a defined Call - going to give that a shot

how does dynamic linking work? no experience with that
 
i went with inline asm because it was the easiest solution

setjmp would be harder to implement, but it might allow for a defined Call - going to give that a shot

how does dynamic linking work? no experience with that

Linking against .ASM files, defined as functions that are declared during the linking process, using the extern keyword.

 
Back