首页
社区
课程
招聘
hidethread.c
发表于: 2007-8-14 13:25 3417

hidethread.c

2007-8-14 13:25
3417
#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;
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 398
活跃值: (343)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
2
明明是Injcet,哪是什么hide
2007-8-14 13:56
0
雪    币: 427
活跃值: (412)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
实现代码简洁所以转了。远程线程注入
2007-8-14 19:01
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
代码很普通
2007-8-14 21:06
0
雪    币: 233
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
试试效果
2007-8-15 13:45
0
雪    币: 538
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
对我等菜菜来说,还是2个字,学习
2007-8-15 19:38
0
游客
登录 | 注册 方可回帖
返回
//