远线程注入
每个进程都有自己的虚拟地址空间,对32位进程来说,这个地址空间的大小为4GB。因为每个进程都有自己专有的地址空间,当进程的各个线程运行的时候,它们只能够访问属于自己进程的内存。这样做的一个好处是维护系统的安全,防止进程的私有空间被入侵。世界上有了矛就有了盾,windows也撕开了一个小口,提供了一些函数来让其它进程对另一个进程进行操作,当然亦邪亦正,全在于你。大名鼎鼎的CreateRemoteThread就是属于这样的函数。
远线程注入的基本原理就是通过在另一个进程中创建远程线程的方法进入目标进程的内存地址空间。使用插入到目标进程中的远程线程将该DLL插入到目标进程的地址空间,即利用该线程通过调用Windows API LoadLibrary函数来加载DLL,从而实现获取目标进程空间的使用权。如下摘自ReactOS 3.14的代码所示,CreateRemoteThread实际实现的功能就是调用NtCreateThread创建一个属于目标进程的线程。
HANDLE
WINAPI
CreateRemoteThread(HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId)
{
/* Clear the Context */
RtlZeroMemory(&Context, sizeof(CONTEXT));
/* Write PID */
ClientId.UniqueProcess = hProcess;
/* Create the Stack */
Status = BaseCreateStack(hProcess,
dwStackSize,
dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
dwStackSize : 0,
&InitialTeb);
/* Create Initial Context */
BaseInitializeContext(&Context,
lpParameter,
lpStartAddress,
InitialTeb.StackBase,
1);
/* initialize the attributes for the thread object */
ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes,
lpThreadAttributes,
NULL);
//前面部分都是在初始化新线程的环境,紧接着就是创建线程了
/* Create the Kernel Thread Object */
Status = NtCreateThread(&hThread,
THREAD_ALL_ACCESS,
ObjectAttributes,
hProcess,
&ClientId,
&Context,
&InitialTeb,
TRUE);
//...............其它操作
}
HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess, //新线程所属的进程句柄
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress, //新线程函数指针
__in LPVOID lpParameter, //新线程函数所需传入的参数
__in DWORD dwCreationFlags,
__out LPDWORD lpThreadId
);
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hSnapshot == NULL )
{
cout<<"Create Snapshot false."<<endl;
cin.get();
return;
}
PROCESSENTRY32 stProcessEntry32 = {0};
stProcessEntry32.dwSize = sizeof(PROCESSENTRY32);
Process32First( hSnapshot, &stProcessEntry32 );
bool bFind = false;
do
{
if( strncmp( stProcessEntry32.szExeFile, "explorer.exe", strlen("explorer.exe") ) == 0 )
{
bFind = true;
break;
}
}while( Process32Next( hSnapshot, &stProcessEntry32 ) );
CloseHandle( hSnapshot );
if( !bFind )
{
cout<<"查找explorer进程失败."<<endl;
cin.get();
return;
}
DWORD dwPId = stProcessEntry32.th32ProcessID;
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, false, dwPId );
if( hProcess == NULL )
{
cout<<"打开explorer进程失败."<<endl;
cin.get();
return;
}
char lpDllName[100] = {0};
GetCurrentDirectory( 100, lpDllName );
strcat( lpDllName, "\\InjectProcessDll.dll" );
LPVOID lpDllNameAddr = VirtualAllocEx( hProcess, NULL, strlen(lpDllName)+1, MEM_COMMIT, PAGE_READWRITE );
if( lpDllNameAddr == NULL )
{
cout<<"explorer进程中申请内存失败."<<endl;
CloseHandle(hProcess);
cin.get();
return;
}
cout<<"在目标进程:"<<stProcessEntry32.szExeFile<<"中申请的空间地址:"<<hex<<lpDllNameAddr<<endl;
DWORD dwRes = 0;
bool bRet = WriteProcessMemory( hProcess, lpDllNameAddr, lpDllName, strlen(lpDllName), &dwRes );
if( !bRet )
{
cout<<"explorer进程写信息失败."<<endl;
VirtualFreeEx( hProcess, lpDllNameAddr, strlen(lpDllName)+1, MEM_DECOMMIT );
CloseHandle(hProcess);
cin.get();
return;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课