首页
论坛
课程
招聘
用进程注入来实现一个壳
2004-6-2 13:26 7577

用进程注入来实现一个壳

2004-6-2 13:26
7577
用进程注入来实现一个壳(原理)

作者: Simonzh2000[US]

感谢 too2y , 老王.
这是我在学习老王的壳后, 参考网上的一些例子做的。
比老王的壳差的太远, 希望各位不要见笑.
如果各位写出了类似的加壳器, 希望发一个给我。

启动前先启动 Calc.exe, 改一下, 用 Explorer.exe 也可以。

#define UNICODE
#define _UNICODE
                          
#include <windows.h>
#include <tchar.h>
#include <conio.h>
#include <psapi.h>

typedef struct _remoteparameter
{
	DWORD       rpwinexec;
	DWORD       rpcreatemutex;
	DWORD       rpsleep;
	DWORD       rpclosehandle;

	char        rpwinexecname[MAX_PATH];
    HANDLE      rphMutex;
    TCHAR       rpMutex[30];
	
}REMOTEPARAMETER, *PREMOTEPARAMETER;

DWORD   WINAPI remote(LPVOID);
DWORD   processtopid(TCHAR*);  
HANDLE  createremote(PTSTR);     


TCHAR             cMutex[8];


int main()
{
 	TCHAR             ExeName[MAX_PATH];
	HANDLE            hRemoteThread;
	HANDLE            hMutex;
	int               ret; 

    _tcscpy(cMutex,_T("simonzh"));
	hMutex = OpenMutex(SYNCHRONIZE, TRUE, cMutex );
	if (hMutex == NULL)
	{
		ret=GetModuleFileName(NULL,ExeName,MAX_PATH);
		if(ret==0)
		{
			OutputDebugString(_T("GetModuleFileName Error\n"));
			getche();              
			return -1;
		}

 
		if((hRemoteThread=createremote(ExeName))==NULL)   
		{
			OutputDebugString(_T("CreateRemote Error\n"));
			getche();              
    		return -1;
		}
        
		return 0;
	}

	CloseHandle(hMutex);
   
	// 上面相当于一个壳的 Loader 
           // 下面相当于被加壳的原程序.
	_tprintf(_T("---[ This is not me.   HaHaHa... ]---\n"));   
	getche();
	return 0;
}
		

DWORD processtopid(TCHAR *processname)
{
	DWORD    lpidprocesses[1024],cbneeded,cprocesses;
	HANDLE   hprocess;
	HMODULE  hmodule;
	UINT     i;
	TCHAR    normalname[MAX_PATH]=_T("UnknownProcess");
    
	if(!EnumProcesses(lpidprocesses,sizeof(lpidprocesses),&cbneeded))
	{
		OutputDebugString(_T("EnumProcesses Error\n"));
		return -1;  
	}

	cprocesses=cbneeded/sizeof(DWORD);
	
	for(i=0;i<cprocesses;i++)
	{
		hprocess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,lpidprocesses[i]);
		if(hprocess)
		{
			if(EnumProcessModules(hprocess,&hmodule,sizeof(hmodule),&cbneeded))
			{
				GetModuleBaseName(hprocess,hmodule,normalname,sizeof(normalname));
				if(!_tcsicmp(normalname,processname))  
				{
					CloseHandle(hprocess);
					return (lpidprocesses[i]);
				}
			}
		}

	}

	CloseHandle(hprocess);
	return 0;
}


HANDLE createremote(PTSTR ExeName)
{
    HANDLE            ethread;
	HANDLE            rphandle;
	TCHAR             name[15];
	TCHAR             *remotethr;
	TCHAR             *remotepar;
	DWORD             remotepid;
	int               cb;
	HINSTANCE         hkernel32;
	REMOTEPARAMETER   rp;

	_tcscpy(name,_T("Calc.exe"));

	
	while(1)
	{
		remotepid=processtopid(name); 
		
		if(remotepid==-1)
		{
			return NULL;
		}
		else if(remotepid==0)
		{
			OutputDebugString(_T("Remote Process isn't running\n")); 
			Sleep(1000);
			continue;
		}


    	rphandle=OpenProcess(PROCESS_CREATE_THREAD |     
	      	                 PROCESS_VM_OPERATION  |     
		       				 PROCESS_VM_WRITE,           
			    			 FALSE,remotepid);
    	if(rphandle==NULL)
		{
	    	Sleep(1000);
			continue;
		}
		else
		{
			break; 
		}
	}

	cb=sizeof(TCHAR)*4*1024;
	remotethr=(PTSTR)VirtualAllocEx(rphandle,NULL,cb,MEM_COMMIT,PAGE_EXECUTE_READWRITE); 
	if(remotethr==NULL)
	{
		OutputDebugString(_T("VirtualAllocEx for Thread Error\n"));
        CloseHandle(rphandle);       
		return NULL;
	}

    if(WriteProcessMemory(rphandle,remotethr,(LPVOID)remote,cb,NULL)==FALSE)
	{
		OutputDebugString(_T("WriteProcessMemory for Thread Error\n"));
        CloseHandle(rphandle);
		return NULL;
	}

	{   
		memset(&rp,0,sizeof(rp));
        _tcscpy(rp.rpMutex, cMutex);
		WideCharToMultiByte(CP_ACP,0,ExeName,-1,rp.rpwinexecname,_tcslen(ExeName),NULL,NULL);
		
		hkernel32=GetModuleHandle(_T("kernel32.dll"));
		rp.rpwinexec=(DWORD)GetProcAddress(hkernel32,"WinExec");
		rp.rpcreatemutex=(DWORD)GetProcAddress(hkernel32,"CreateMutexW");
		rp.rpsleep=(DWORD)GetProcAddress(hkernel32,"Sleep");
		rp.rpclosehandle=(DWORD)GetProcAddress(hkernel32,"CloseHandle");
	}   
	
	cb=sizeof(TCHAR)*sizeof(rp);
	remotepar=(PTSTR)VirtualAllocEx(rphandle,NULL,cb,MEM_COMMIT,PAGE_READWRITE);
	if(remotepar==NULL)
	{
		OutputDebugString(_T("VirtualAllocEx for Parameter Error\n"));
		CloseHandle(rphandle);
		return NULL;
	}

	if(WriteProcessMemory(rphandle,remotepar,(LPVOID)&rp,cb,NULL)==FALSE)
	{
		OutputDebugString(_T("WriteProcessMemory for Parameter Error:"));
		CloseHandle(rphandle);
		return NULL;
	}
    
	
	ethread=CreateRemoteThread(rphandle,NULL,0,(LPTHREAD_START_ROUTINE)remotethr,(LPVOID)remotepar,0,NULL);
	if(ethread==NULL)
	{
		OutputDebugString(_T("CreateRemoteThread Error\n"));
		CloseHandle(rphandle);
		return NULL;
	}

	return ethread;
}


DWORD WINAPI remote(LPVOID pvparam)
{
	PREMOTEPARAMETER erp=(PREMOTEPARAMETER)pvparam;

  	typedef UINT   (WINAPI *EWinExec)(LPCSTR, UINT);
	typedef HANDLE (WINAPI *ECreateMutex)(LPSECURITY_ATTRIBUTES , BOOL, LPCTSTR);
 	typedef VOID   (WINAPI *ESleep)(DWORD);
    typedef BOOL   (WINAPI *ECloseHandle)(HANDLE);
	
	EWinExec             tWinExec;
    ECreateMutex         tCreateMutex;
  	ESleep               tSleep;
	ECloseHandle         tCloseHandle;

	tWinExec=(EWinExec)erp->rpwinexec;
	tCreateMutex=(ECreateMutex)erp->rpcreatemutex;
	tSleep=(ESleep)erp->rpsleep;
	tCloseHandle=(ECloseHandle)erp->rpclosehandle;

	erp->rphMutex=tCreateMutex(NULL, TRUE, erp->rpMutex);

	if(tWinExec(erp->rpwinexecname, SW_SHOW)<=31)             
	{
		return -1;
	}
    
	tSleep(4000);
	tCloseHandle(erp->rphMutex);
	return 0;
}


第五届安全开发者峰会(SDC 2021)议题征集正式开启!

收藏
点赞0
打赏
分享
最新回复 (12)
雪    币: 202
活跃值: 活跃值 (16)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
vcasm 活跃值 1 2004-6-2 13:41
2
0
算是一个演示吧,离实用还有些距离,至少考虑9X的系统的远程线程载入,建议加入9X下的0环代码实现
雪    币: 207
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
simonzh2000 活跃值 24 2004-6-2 13:44
3
0
我只是给个原理而已,也很简单,实用的找老王。

这个贴子好象不够资格置顶, 请版主把他放下来吧。
雪    币: 5536
活跃值: 活跃值 (51)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
forgot 活跃值 26 2004-6-2 14:58
4
0
9x呢?
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
StudentII 活跃值 2004-6-2 15:13
5
0
最初由 forgot 发布
9x呢?


9x用老王的方法呀,Hook注入dll,这是经典的方法
雪    币: 202
活跃值: 活跃值 (16)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
vcasm 活跃值 1 2004-6-2 15:28
6
0
其实也可以用这种方法 直接建立一块映射内存 将代码写入映射内存 然后枚举所有进程--->挂起--->修改EIP处代码--->恢复执行--->挂起--->恢复EIP处代码--->恢复执行
上面的方法9X 2000都能有
雪    币: 200
活跃值: 活跃值 (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
二点 活跃值 1 2004-6-2 18:41
7
0
up!
雪    币: 225
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
老王 活跃值 1 2004-6-2 19:49
8
0
最初由 vcasm 发布
其实也可以用这种方法 直接建立一块映射内存 将代码写入映射内存 然后枚举所有进程--->挂起--->修改EIP处代码--->恢复执行--->挂起--->恢复EIP处代码--->恢复执行
上面的方法9X 2000都能有


不同进程得到的映射内存地址不一定一样吧?
雪    币: 225
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
老王 活跃值 1 2004-6-2 20:00
9
0
其实我的壳用进程注入并不是为了建立调试器,调试器完全可以利用双进程的方式。因为我的壳本身就有一个DLL,而DLL正好方便注入,而注入可以用来在别的进程建立调试器,还有一个好处就是HOOK重要的API,比如用来防DUMP什么的。
雪    币: 5536
活跃值: 活跃值 (51)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
forgot 活跃值 26 2004-6-2 20:00
10
0
直接保存目标进程代码,写入执行你的代码再还原不就行了
雪    币: 207
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
simonzh2000 活跃值 24 2004-6-2 21:20
11
0
最初由 老王 发布
其实我的壳用进程注入并不是为了建立调试器,调试器完全可以利用双进程的方式。因为我的壳本身就有一个DLL,而DLL正好方便注入,而注入可以用来在别的进程建立调试器,还有一个好处就是HOOK重要的API,比如用来防DUMP什么的。


我在跟踪过程中发现 OpenProcess 好象被你 HOOK 了.
雪    币: 202
活跃值: 活跃值 (16)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
vcasm 活跃值 1 2004-6-2 21:45
12
0
最初由 老王 发布


不同进程得到的映射内存地址不一定一样吧?


不需要绝对地址 直接读映射文件 当然需要通过异常结构找出KERNEL32.dll和需要的几个API

呵呵 说到这就能引出2个结果 如果功能代码不大 完全能够放到载入的执行体里面实现 如果不好实现再放入映射空间
雪    币: 225
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
老王 活跃值 1 2004-6-2 23:52
13
0
最初由 simonzh2000 发布


我在跟踪过程中发现 OpenProcess 好象被你 HOOK 了.


你说的对!不过后来改了!
游客
登录 | 注册 方可回帖
返回