欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ShellCode注入

程序员文章站 2024-02-12 10:40:46
...

注意点:

1. 不能有全局变量

2. 不能使用常量字符串 ,可以使用这种形式 szTitle = {'a', 'b', 'c', 0};

3. 不能使用系统调用,比如不能直接使用MessageBox,因为生成的汇编是 Call [0xxxxxx],这个0xxxxx是导入表的地址,注入的程序导入表地址不同而且导入表中不一定有这个函数,可以使用LoadLibrary配合GetProcAddress,但是LoadLibrary和GetProcAddress也是系统调用,也依赖导入表需要通过PEB的模块链,找到Kernel32.dll的模块句柄,然后找到Kernel32.dll的导出表,然后找到LoadLibrary和GetProcAddress的函数地址

4. 不能嵌套调用其他函数,注入后函数地址变化了

 

头文件,结构体定义

#pragma once

#include <windows.h>

typedef struct _UNICODE_STR
{
	USHORT Length;
	USHORT MaximumLength;
	PWSTR pBuffer;
} UNICODE_STR, *PUNICODE_STR;

typedef struct _RTL_USER_PROCESS_PARAMETERS {
	BYTE			Reserved1[16];
	PVOID			Reserved2[10];
	UNICODE_STR		ImagePathName;
	UNICODE_STR		CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

typedef struct _LDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
	PVOID DllBase;
	PVOID EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STR FullDllName;
	UNICODE_STR BaseDllName;
	ULONG Flags;
	SHORT LoadCount;
	SHORT TlsIndex;
	LIST_ENTRY HashTableEntry;
	ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

typedef struct _PEB_LDR_DATA
{
	DWORD dwLength;						//结构体大小
	DWORD dwInitialized;				//进程是否初始化完成
	LPVOID lpSsHandle;
	LIST_ENTRY InLoadOrderModuleList;
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
	LPVOID lpEntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

//PEB
typedef struct __PEB
{
	BYTE Reserved1[2];
	BYTE BeingDebugged;
#ifdef _WIN64
	BYTE Reserved2[21];
#else
	BYTE Reserved2[9];
#endif
	PPEB_LDR_DATA pLdr;
	PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
	BYTE Reserved3[520];
	BYTE Reserved4[136];
	ULONG SessionId;
} _PEB, *_PPEB;

cpp文件

#include "ShellCode.h"

typedef PVOID(__stdcall *MyGetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
typedef HMODULE(__stdcall *MyLoadLibraryA)(LPCSTR lpLibFileName);
typedef int (__stdcall *MyMessageBoxA)(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType);

void ShellCode()
{
	//获取peb地址  fs:[0x30]
#ifdef _WIN64
	DWORD64 dwPeb = __readgsqword(0x60);
#else
	DWORD dwPeb = __readfsdword(0x30);
#endif

	//unicode格式
	wchar_t szKernel32[] = { L'K', L'E', L'R', L'N' , L'E' , L'L' , L'3' , L'2' , L'.', L'D', L'L', L'L', 0, 0 };
	char szUser32[] = { 'U', 'S', 'E', 'R', '3', '2', '.', 'D', 'L', 'L', 0 };

	char szGetProcAddr[] = { 'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', 0 };
	char szLoadLibrary[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', 0 };
	char szMessageBox[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'B', 'o', 'x', 'A', 0 };

	PVOID pKernelBase = nullptr;
	MyGetProcAddress pMyGetProcAddress = nullptr;
	
	//遍历Dll模块
	PLDR_DATA_TABLE_ENTRY pDataTable = (PLDR_DATA_TABLE_ENTRY)((PPEB_LDR_DATA)((_PPEB)dwPeb)->pLdr)->InMemoryOrderModuleList.Flink;
	while (pDataTable)
	{
		//找到kernel32模块
		LPTSTR lpDllName = (LPTSTR)pDataTable->BaseDllName.pBuffer;
		wchar_t*  pTemp = szKernel32;
		while (*pTemp && *pTemp == *lpDllName)
		{
			pTemp++;
			lpDllName++;
		}
		if (*pTemp == 0)
		{
			pKernelBase = pDataTable->DllBase;
			break;
		}

		//双向链表的下一个
		pDataTable = (PLDR_DATA_TABLE_ENTRY)pDataTable->InMemoryOrderModuleList.Flink;
	}

	if (pKernelBase == nullptr)
	{
		return;
	}

	//定位到PE指纹
	UINT_PTR pSignature = (UINT_PTR)pKernelBase + ((PIMAGE_DOS_HEADER)pKernelBase)->e_lfanew;
	//定位到导出表
	UINT_PTR pExportTable = (UINT_PTR)&((PIMAGE_NT_HEADERS)pSignature)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
	pExportTable = (UINT_PTR)pKernelBase + ((PIMAGE_DATA_DIRECTORY)pExportTable)->VirtualAddress;
	
	//函数名表
	UINT_PTR pNameArray = (UINT_PTR)pKernelBase + ((PIMAGE_EXPORT_DIRECTORY)pExportTable)->AddressOfNames;
	//函数地址表
	UINT_PTR pAddressArray = (UINT_PTR)pKernelBase + ((PIMAGE_EXPORT_DIRECTORY)pExportTable)->AddressOfFunctions;
	//函数序号表
	UINT_PTR pNameOrdinals = (UINT_PTR)pKernelBase + ((PIMAGE_EXPORT_DIRECTORY)pExportTable)->AddressOfNameOrdinals;
	//导出函数个数
	DWORD dwExportFunCount = ((PIMAGE_EXPORT_DIRECTORY)pExportTable)->NumberOfNames;
	//遍历导出函数
	for (int i = 0; i < dwExportFunCount; i++)
	{
		//导出函数名
		char* pFunName = (char*)((UINT_PTR)pKernelBase + ((UINT_PTR*)pNameArray)[i]);
		//找到GetProcAddress
		char* pTemp = szGetProcAddr;
		while (*pTemp && *pTemp == *pFunName)
		{
			pTemp++;
			pFunName++;
		}
		if (*pTemp == 0)
		{
			//从序号表中取出地址表中的索引
			unsigned int nIndex = ((unsigned short*)pNameOrdinals)[i];
			//根据索引获取函数地址
			pMyGetProcAddress = MyGetProcAddress((UINT_PTR)pKernelBase + ((UINT_PTR*)pAddressArray)[nIndex]);
			break;
		}
	}

	//用GetProcAddress获取到LoadLibraryA的地址
	MyLoadLibraryA pMyLoadLibraryA = (MyLoadLibraryA)pMyGetProcAddress((HMODULE)pKernelBase, szLoadLibrary);

	HMODULE hUser32 = pMyLoadLibraryA(szUser32);
	MyMessageBoxA pMyMessageBox = (MyMessageBoxA)pMyGetProcAddress(hUser32, szMessageBox);
	pMyMessageBox(0, 0, 0, 0);
}

int main()
{
	ShellCode();
}
 

 

相关标签: ****