您的位置:首页 > 编程语言

远程代码注入

2016-06-29 19:39 417 查看
除了通常的通过DLL注入来向其他进程插入代码,还有一种方法,就是直接想目标进程插入代码,此方法与前者相比之下有以下几个优点:

1、由于不用注入DLL,所以是目标进程占用的内存更小

2、由于没有注入DLL,也使得更不容易被检测到(比如有些检测手段通过对比进程运行前后的DLL来判断是否有DLL插入)

当然这种方法也有其缺点,它编程相对复杂,不适合大量代码注入,另外在提权操作中可能有失败的情况,我亲测本方法在win10环境中,提权会失败。

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;

if( !OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken) )
{
printf("OpenProcessToken error: %u\n", GetLastError());
return FALSE;
}

if( !LookupPrivilegeValue(NULL,           // lookup privilege on local system
lpszPrivilege,  // privilege to lookup
&luid) )        // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if( bEnablePrivilege )
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;

// Enable the privilege or disable all privileges.
if( !AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}

if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}

return TRUE;
}

typedef struct _THREAD_PARAM
{
FARPROC pFunc[2];//LoadlibraryA(),GetProAddress()
char szBuf[4][128];//"user32.dll","MessageBoxA"                     //"www.reversecore.com","RecerseCore"
}THREAD_PARAM,*PTHREAD_PARAM;

//LoadLibraryA()
typedef HMODULE (WINAPI *PFLOADLIBRARYA)
(
LPCSTR lpLibFileName
);
//GetProcAddress()
typedef FARPROC (WINAPI *PFGETPROCADDRESS)
(HMODULE  hModule,
LPCSTR lpProcName);
//MessageBox
typedef int(WINAPI *PFMESSAGEBOXA)
(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);

//Thread Procdure
DWORD WINAPI ThreadProc(LPVOID lParam)
{
PTHREAD_PARAM pParam   =(PTHREAD_PARAM)lParam;
HMODULE       hMod     =NULL;
FARPROC       pFunc    =NULL;

//LoadLibrary("user32.dll")
//pParam->pFunc[0]->kernel32!LoadLibraryA()
//pParam->szBuf[0]->"user32.dll"
hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);

//GetProcAddress("MessageBoxA")
//pParam->pFunc[1]->kernel32!GetProcAddress()
//pParam->szBuf[1]->"MessageBox"
pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod,pParam->szBuf[1]);

//MessageBoxA(NULL,"www.reversecore.com","ReverseCore",MB_OK)
//pParam->szBuf[2]->"www.reversecore.com"
//pParam->szBuf[3]->"ReverseCore"
((PFMESSAGEBOXA)pFunc)(NULL,pParam->szBuf[2],pParam->szBuf[3],MB_OK);

return 0;
}
BOOL InjectCode(DWORD dwPID)
{
HMODULE        hMod         =   NULL;
THREAD_PARAM   param        =   {0,};
HANDLE         hProcess     =   NULL;
HANDLE         hThread      =   NULL;
LPVOID         pRemoteBuf[2]=   {0,};
DWORD          dwSize       =   0;

hMod = GetModuleHandleA("kernel32.dll");

//set THREAD_PARAM
param.pFunc[0]  =  GetProcAddress(hMod,"LoadLibraryA");
param.pFunc[1]  =  GetProcAddress(hMod,"GetProcAddress");
strcpy_s(param.szBuf[0],"user32.dll");
strcpy_s(param.szBuf[1],"MessageBoxA");
strcpy_s(param.szBuf[2],"www.reversecore.com");
strcpy_s(param.szBuf[3],"RecerseCore");

//open Process
hProcess = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
dwPID
);
if(hProcess==NULL)
{
printf("open Process  failed %d\n",GetLastError());
}
//Allocation for THREAD_PARAM
dwSize = sizeof(THREAD_PARAM);
pRemoteBuf[0] = VirtualAllocEx(
hProcess,
NULL,
dwSize,       //dwSize
MEM_COMMIT,   //flAllocationType
PAGE_READWRITE);
if(pRemoteBuf[0]==NULL)
{
printf("Allocation for THREAD_PARAM  failed\n");
}

WriteProcessMemory(
hProcess,
pRemoteBuf[0],
(LPVOID)¶m,//lpBuffer
dwSize,
NULL);        //lpNumberOfByteWritten

//Allocation for ThreadProc
/*此处的长度计算有点难以理解,实际上它的长度是因为ThreadProc和 InjectCode是1、2的关系,函数名
代表了函数起始地址,同时在本程序编译Release版本的时候,
内存地址的顺序就是函数顺序,所以可以用2-1的方式,
试想此方法并非通用,当它失效的时候,可以找到的一种方法是
直接通过调试器查看内存,来确定该函数的大小*/
dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
pRemoteBuf[1] = VirtualAllocEx(hProcess,
NULL,
dwSize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if(pRemoteBuf[1]==NULL)
{
printf("Allocation for ThreadProc  failed\n");
}
WriteProcessMemory(
hProcess,
pRemoteBuf[1],
(LPVOID)ThreadProc,//lpBuffer
dwSize,
NULL);        //lpNumberOfByteWritten

hThread = CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)pRemoteBuf[1],//lpStartAddress
pRemoteBuf[0],//lpParameter
0,
NULL);
if(hThread==NULL)
{
printf("hThread==NULL injection failed\n");
printf("open hThread  failed %d\n",GetLastError());
}
WaitForSingleObject(hThread,INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);

return TRUE;

}
int main(int argc, char* argv[])
{
DWORD dwPID=0;
if(argc!=2)
{
printf("\n USAGE %s argv[0] pid\n");
return 1;
}

// change privilege
if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )
return 1;

//Code Injection
dwPID=(DWORD)atol(argv[1]);
InjectCode(dwPID);
return 0;
}


小结:

本程序虽然短小,但是注入思路简洁,将自定结构体作为参数和将写入远进程的缓冲区的起始地址作为创建远线程的参数的方法值得借鉴,原先让我这个不太懂编程的孩子是打破脑袋也想不到的,实为精妙,至于为什么在win10 64位运行失败,以后再来研究。

后续:

1、关于之前在WIN10上CreateRemoteThread失败返回失败码5放入情况,网上查看说是因为权限不够,32位程序在64位系统提权失败,实际上,我的提权函数也写过错误代码而并没有返回错误,说明不是提权失败,而是CreateRemoteThread这个函数在64位系统运行出错的问题,测试用此程序在自己创建的exe程序注入的时候并没有出现异常,猜想是win 10 64位对系统进程作了保护机制,究竟是什么,还是没弄清楚,待进一步查证。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: