TIPS
1.
之前写进程隐藏的时候写了个dll注入工具,这个工具会想目标进程写入dll名称,然后利用loadlirary加载dll。如何让那个程序调用loadlirary的呢?是用了CreateRemoteThread这个函数,翻译过来就是创建远程线程,为什么微软要提供一个这样的函数呢?其实并不是微软特地提供的给我们注入的API,这个API的实际作用其实是创建远程线程,创建的线程原型是DWORD WINAPI ThreadProc(LPVOID lparam),只有一个参数,且参数是指向任意内容的指针,而loadlirary函数的原型是HMODULE WINAPI LoadLibrary( LPCTSTR lpFileName),可以看出来他们两个非常接近,都是1个参数,那个参数都是指针,所以这个函数就被开发为注入dll的API,且不会出错,符合语法,但是运行的线程函数被替换为LoadLibrary函数,然后运行线程=加载dll,随后dllmain里面运行各种代码。
2.
但其实这种方式不够隐蔽,因为你在程序中加载了DLL,这么大的动静被检测的几率就会很大,而且你既然有dll实体那么被云端响应的速度也会很快,换句话说,这种注入dll的方式很容易被拦截
3.
其实我们可以利用CreateRemoteThread函数的原本的功能,即直接运行ThreadProc,而这个ThreadProc函数的代码通过WriteProcessMemory的方式写入,函数的参数lparam所指向的内容也采用同样的方式写入即可,这样调用CreateRemoteThread就会直接运行我们写入的ThreadProc函数
4.
在ThreadProc函数中调用API的时候我们不确定我们注入的程序有没有加载含有这个API的DLL,所以我们一般需要调用什么API都要给他加入LoadLibrary,去加载这个api的dll
5.
逆向工程核心原理中的ThreadProc有LoadLibrary加上调用GetprocAddress之后再动态调用MessageBoxA这一步,感觉又复杂又没啥必要,直接给他传入MessageBoxA的地址即可,经测试没有问题
6.
调用重要API的时候有一个参数需要知道ThreadProc整个函数的大小,这里巧妙地使用(DWORD)ThreadProc-(DWORD)Code_Inject计算得到,可以想象一下,这两个函数是紧挨着的,且编写的时候ThreadProc在Code_Inject后面,是不是这样就能得到ThreadProc的大小了?如果还是不知道的话调试一下即可
CodeInject.h
#include "windows.h"
#include <iostream>
using namespace std;
//*******************************Params定义*****************************************
typedef struct _THREAD_PARAM{
FARPROC pFunc[2];
char szbuf[2][128];
}THREAD_PARAM,*PTHREAD_PARAM;
//*******************************Windows API定义*****************************************
typedef HMODULE (WINAPI *PFLOADLIBRARY)(LPCSTR lpLibFileName); //LoadLibrary()
typedef int (WINAPI *PFMESSAGEBOXA)(HWND hwnd,LPCSTR lptext,LPCSTR lpcaption,UINT utype); //MessageBoxA()
DWORD WINAPI ThreadProc(LPVOID lparam); //injected-thread
BOOL EnableDebugPrivilege(); //提权函数
void Code_Inject(); //代码注入函数
CodeInject.cpp
#include "CodeInject.h"
DWORD Inject_Pid=0;
THREAD_PARAM param={0,};
int main(){
cout<<"plz input pid you want to inject"<<endl;
cin>>Inject_Pid;
LoadLibraryA("user32.dll");
//****************************设置Params参数*********************************
HMODULE hmod1=GetModuleHandleA("kernel32.dll");
HMODULE hmod2=GetModuleHandleA("user32.dll");
param.pFunc[0]=GetProcAddress(hmod1,"LoadLibraryA"); //确保user32.dll已加载
param.pFunc[1]=GetProcAddress(hmod2,"MessageBoxA"); //调用MessageBoxA
strcpy_s(param.szbuf[0],"user32.dll"); //LoadLibraryA的参数
strcpy_s(param.szbuf[1],"Injected"); //MessageBoxA的参数
//****************************设置Params完成*********************************
Code_Inject();
return 0;
}
void Code_Inject(){
if(!EnableDebugPrivilege()){ //提权
cout<<"EnableDebugPrivilege Failed";
system("pause");
return;
}
HANDLE hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,Inject_Pid); //获取进程句柄
LPVOID param_address=VirtualAllocEx(hprocess,NULL,sizeof(THREAD_PARAM),MEM_COMMIT,PAGE_READWRITE); //申请存放param的空间
LPVOID ThreadProc_address=VirtualAllocEx(hprocess,NULL,(DWORD)ThreadProc-(DWORD)Code_Inject,MEM_COMMIT,PAGE_READWRITE);//申请存放ThreadProc的空间,ThreadProc大小通过Code_Inject-ThreadProc取得(注意这里不能为负数?)
WriteProcessMemory(hprocess,param_address,(LPVOID)¶m,sizeof(THREAD_PARAM),NULL); //写入param
WriteProcessMemory(hprocess,ThreadProc_address,(LPVOID)ThreadProc,(DWORD)ThreadProc-(DWORD)Code_Inject,NULL); //写入ThreadProc
HANDLE hthread=CreateRemoteThread(hprocess,NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc_address,param_address,0,NULL); //创建ThreadProc线程
WaitForSingleObject(hthread,INFINITE);
CloseHandle(hthread);
CloseHandle(hprocess);
}
DWORD WINAPI ThreadProc(LPVOID lparam){
PTHREAD_PARAM pParam=(PTHREAD_PARAM)lparam;
((PFLOADLIBRARY)pParam->pFunc[0])(pParam->szbuf[0]); //LoadLibraryA("user32.dll")
((PFMESSAGEBOXA)pParam->pFunc[1])(NULL,pParam->szbuf[1],pParam->szbuf[1],NULL); //MessageBoxA(NULL,"Injected","Injected",NULL);
return 0;
}
BOOL EnableDebugPrivilege(){
HANDLE hToken;
BOOL fOk=FALSE;
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken)){ //Get Token
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount=1;
if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid))//Get Luid
cout<<"Can't lookup privilege value"<<endl;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;//这一句很关键,修改其属性为SE_PRIVILEGE_ENABLED
if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL))//Adjust Token
cout<<"Can't adjust privilege value"<<endl;
fOk=(GetLastError()==ERROR_SUCCESS);
CloseHandle(hToken);
hToken=NULL;
}
return fOk;
}