sdckey

Endpoint Investigator and Bookmarking Example

Dec 1st, 2020 (edited)
698
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.   EnCase Endpoint Investigator EnScript example.
  3.  
  4.   Tested on EnCase 20.4.0.120.
  5.  
  6.   Report bugs to:
  7.  
  8.   Simon Key <skey@opentext.com>
  9.  
  10.   1st December 2020
  11. */
  12.  
  13. class MainClass {
  14.  
  15.   SafeClass                                                                                         Safe;                              // Object to connect to SAFE
  16.  
  17.   RoleClass                                                                                         RoleRoot,                          // List of all roles for a given user
  18.                                                                                                     Role;                              // Role user choose to take
  19.  
  20.   NetworkClass                                                                                      SweepNet;                          // List of remote nodes to connect to
  21.  
  22.   String                                                                                            NetText,                           // Textual list of remote nodes
  23.                                                                                                     ClientReturnAddress,               // For NODECLIENT connection options
  24.                                                                                                     StatusBarName,                     // Name to be displayed in the status bar
  25.                                                                                                     SuccessfulLabel,                   // Snapshot and bookmark label for successful connections
  26.                                                                                                     FailedLabel;                       // Snapshot and bookmark label for failed connections
  27.  
  28.   int                                                                                               NumConnections,                    // Number of SAFE connections to use
  29.                                                                                                     ConnectOptions;                    // Connection Options: INDIRECT, CLIENTNODELOCAL, CLIENTNODESAFE, NODECLIENT
  30.                                                                                                    
  31.   BookmarkClass                                                                                     RootBMFolder,                      // Top-level bookmark folder for script output                
  32.                                                                                                     SuccessfulConnectionsBMFolder,     // Bookmark folder for successful connections
  33.                                                                                                     FailedConnectionsBMFolder;         // Bookmark folder for failed connections
  34.                                                                                                    
  35.   SnapshotClass                                                                                     SuccessfulSnapshots,               // Snapshot container for successful connections
  36.                                                                                                     FailedSnapshots;                   // Snapshot container for failed connections
  37.  
  38.  
  39.   MainClass() :
  40.     Safe(),
  41.     RoleRoot(),
  42.     Role(),
  43.     SweepNet(),
  44.     NumConnections = 20, //can be changed depending on workload
  45.     ConnectOptions = ConnectionClass::CLIENTNODESAFE,
  46.     StatusBarName = "Encase Agent Connectivity Test", //can be changed depending on organizational input
  47.     SuccessfulLabel = "Successful Connections",
  48.     FailedLabel = "Failed Connections",
  49.     SuccessfulSnapshots(null, SuccessfulLabel),
  50.     FailedSnapshots(null, FailedLabel)
  51.   {
  52.   }
  53.  
  54.   /**
  55.   Entry point of the Enscript
  56.   **/
  57.   void Main(CaseClass c)
  58.   {
  59.     if (c)
  60.     {
  61.       SystemClass::ClearConsole();
  62.       if (Safe.Logon(null) && ShowDiag() == SystemClass::OK)
  63.       {
  64.         RootBMFolder = new BookmarkClass(c.BookmarkRoot(), String::Format("{0} Results", StatusBarName), NodeClass::FOLDER);
  65.         SuccessfulConnectionsBMFolder = new BookmarkClass(RootBMFolder, SuccessfulLabel, NodeClass::FOLDER),
  66.         FailedConnectionsBMFolder = new BookmarkClass(RootBMFolder, FailedLabel, NodeClass::FOLDER),
  67.        
  68.         Sweep();
  69.        
  70.         BookmarkSnapshots(SuccessfulConnectionsBMFolder, SuccessfulSnapshots, SuccessfulLabel);
  71.         BookmarkSnapshots(FailedConnectionsBMFolder, FailedSnapshots, FailedLabel);
  72.        
  73.         SystemClass::Message(ICONINFORMATION, "Success", String::Format("{0}: Completed successfully!", StatusBarName));
  74.       }
  75.     }
  76.     else
  77.     {
  78.       SystemClass::Message(ICONSTOP, "Error", "Need an open case so that the results can be bookmarked!");
  79.     }
  80.   }
  81.  
  82.   /**
  83.   Bookmark the resultant snapshots
  84.   **/
  85.  
  86.   void BookmarkSnapshots(BookmarkClass folder, SnapshotClass snap, const String &name)
  87.   {
  88.     BookmarkDataClass data(folder, name);
  89.     data.SetRoot(snap);
  90.   }
  91.  
  92.   /**
  93.   This method contains the logic we want to apply to each node on the network
  94.   **/
  95.  
  96.   void Process(ConnectionClass conn, SnapshotClass ss, const String &name)
  97.   {
  98.     Console.WriteLine("Attempting to determine PATH environment variable for {0} ({1}).", name, ss.IPAddress());
  99.     String path_environment_variable;
  100.     String comment;
  101.     if (conn.ResolveVariable("PATH", path_environment_variable))
  102.     {
  103.       comment = String::Format("PATH environment variable on {0}:\n\n{1}\n", name, path_environment_variable);
  104.     }
  105.     else
  106.     {
  107.       comment = String::Format("Can't resolve PATH environment variable on {0}.", name);  
  108.     }
  109.     Console.WriteLine(comment);
  110.     BookmarkClass sub(SuccessfulConnectionsBMFolder, name, NodeClass::FOLDER),
  111.                   note(sub, String::Format("PATH Environment Variable on {0}", name));
  112.     sub.SetComment(String::Format("Processing results for {0}.", name));
  113.     note.SetComment(comment);
  114.   }
  115.  
  116.   /**
  117.   Display dialogs
  118.   **/
  119.  
  120.   int ShowDiag()
  121.   {
  122.     RoleRoot = Safe.RoleRoot();
  123.     DialogClass diag();
  124.     new NetTextDialogClass(diag, this);
  125.     return diag.Wizard();
  126.   }
  127.  
  128.   /**
  129.   Create a note-bookmark for a connection , failed or otherwise
  130.   **/
  131.  
  132.   void BookmarkConnection(BookmarkClass folder, const String &name, const String &comment)
  133.   {
  134.     BookmarkClass note(folder, name);
  135.     note.SetComment(comment);
  136.   }
  137.  
  138.   /**
  139.   Code to remove trailing newline characters from certain SAFE
  140.   error messages.
  141.   **/
  142.  
  143.   String RemoveTrailingNewLine(const String &value)
  144.   {
  145.     String retval = value;
  146.     retval.Trim("\n", TRIMEND);
  147.     return retval;
  148.   }
  149.  
  150.   /**
  151.   Code that gets connection and snapshot
  152.   **/
  153.  
  154.   void ReadNetwork(BatchClass batch)
  155.   {
  156.     String message,
  157.            name,
  158.            comment;
  159.     do
  160.     {
  161.       ConnectionClass conn;
  162.       SnapshotClass ss();
  163.       message = "";
  164.       BatchClass::ConnectionTypes reply = batch.GetConnection(conn, ss, name, message, 0);
  165.       if (reply == BatchClass::BATCHCONNECT) //successfully connected to remote node
  166.       {
  167.         comment = String::Format("Got connection to {0}.", name);
  168.         Console.WriteLine(comment);
  169.         SuccessfulSnapshots.Insert(ss);
  170.         Process(conn, ss, name);
  171.         SystemClass::StatusInc(1);
  172.        
  173.       }
  174.       else if (reply == BatchClass::BATCHERROR) //could not connect to remote node. ss object will have the state of the node
  175.       {
  176.         comment = String::Format("Could not connect to {0}. SAFE error message: {1}.", name, RemoveTrailingNewLine(message));
  177.         Console.WriteLine(comment);
  178.         FailedSnapshots.Insert(ss);
  179.         BookmarkConnection(FailedConnectionsBMFolder, name, comment);
  180.         SystemClass::StatusInc(1);
  181.       }
  182.       else if (reply == BatchClass::BATCHWAIT)
  183.       {
  184.         SystemClass::Sleep(100);
  185.       }
  186.       else if (reply == BatchClass::BATCHFATAL)
  187.       {
  188.         String err = SystemClass::LastError();
  189.         Console.WriteLine("The SAFE is not responding: {0}. This EnScript will terminate.", RemoveTrailingNewLine(err));
  190.         return;
  191.       }
  192.     } while (reply != BatchClass::BATCHDONE);
  193.   }
  194.  
  195.   /**
  196.   Code that creates a batchclass
  197.   **/
  198.  
  199.   void Sweep()
  200.   {
  201.     DateClass now;
  202.     BatchClass batch(Safe, Role, NumConnections, ConnectionClass::SNAPALL);
  203.     if (batch.Add(SweepNet)) {
  204.       batch.SetMode(ConnectionClass::Options::Convert(ConnectOptions), ClientReturnAddress);
  205.       if (batch.Start()) {
  206.         uint machines = batch.TotalMachines();
  207.         Console.WriteLine("Scanning {0} using {1}.", Plural("node", machines), Plural("connection", batch.ConnectionsUsed()));
  208.         SystemClass::StatusRange(StatusBarName, machines);
  209.         uint start;
  210.         now.Now();
  211.         start = now.GetUnix();
  212.         ReadNetwork(batch);
  213.         now.Now();
  214.         Console.WriteLine("Scan completed in {0} seconds.", (now.GetUnix() - start));
  215.       }
  216.       else {
  217.         SystemClass::Message(ICONSTOP, "BatchClass error.", SystemClass::LastError());
  218.       }
  219.     }
  220.     else {
  221.       SystemClass::Message(ICONSTOP, "BatchClass Error", "Unable to add any IPs to the sweep.");
  222.     }
  223.   }
  224.  
  225.   String Plural(const String &str, uint n)
  226.   {
  227.     return String::Format("{0} {1}{2}", n, str, n == 1 ? "" : "s");
  228.   }
  229.  
  230.   /**
  231.    Turn a string of text into networkclass objects
  232.   **/
  233.  
  234.   bool ParseText(String t)
  235.   {
  236.     SweepNet.Close();
  237.     bool ret = false;
  238.     while (t)
  239.     {
  240.       ret = true;
  241.       int    end  = t.Find("\n");
  242.       String line = end < 0 ? t : t.SubString(0, end);
  243.       int    dash = line.Find("-");
  244.       if (dash > 0) {
  245.         IPClass ip1(ExtractIP(line.SubString(0, dash))),
  246.                 ip2(ExtractIP(line.SubString(dash+1, -1)));
  247.         if (ip1 && ip2) {
  248.           NetworkClass n(SweepNet, "IP Range", NodeClass::SELECTED);
  249.           n.SetStart(ip1);
  250.           n.SetStop(ip2);
  251.         }
  252.         else
  253.           NetworkClass n(SweepNet, line, NodeClass::SELECTED);
  254.       }
  255.       else if (line != "")  {
  256.         NetworkClass n(SweepNet, line, NodeClass::SELECTED);
  257.       }
  258.       if (end > 0)
  259.         t.Delete(0, end+1);
  260.       else
  261.         break;
  262.     }
  263.     return ret;
  264.   }
  265.  
  266.   /**
  267.    Check for IPs in nettext
  268.   **/
  269.  
  270.   String ExtractIP(const String &s)
  271.   {
  272.     String ret = s;
  273.     ret.Trim(" ", String::TRIMSTART | String::TRIMEND);
  274.     return ret.IsValidIPAddress() ? ret : "";
  275.   }
  276. }
  277.  
  278. /**
  279.  Dialog to choose a role and enter nodes to sweep
  280. **/
  281.  
  282. class NetTextDialogClass: DialogClass
  283. {
  284.  
  285.   MainClass Data;
  286.   StaticTextClass SafeTextEdit;
  287.   TreeEditClass Tree;
  288.   StaticTextClass Help;
  289.   StringEditClass NetTextEdit;
  290.  
  291.   NetTextDialogClass(DialogClass diag, MainClass d) :
  292.     DialogClass(diag, d.StatusBarName + " Options"),
  293.     Data = d,
  294.     SafeTextEdit(this, "", START, 15, 200, 100, 0),
  295.     Tree(this, "Choose The Role You Want To Assume", NEXT, START, 200, 100, 0, d.RoleRoot, 0),
  296.     Help(this, "Enter IP addresses or machine names on separate\n"
  297.                  "lines. Enter ranges on separate lines and delimit\n"
  298.                  "the start and stop address with a dash (\"-\").\n\n"
  299.                  "Example:\n\n"
  300.                  "\tlocalhost\n"
  301.                  "\t192.168.5.5\n"
  302.                  "\t192.168.0.16-192.168.0.64\n"
  303.                  "\t192.168.1.1-192.168.3.255\n"
  304.                  "\tfd00:0:1000:20:0:0:0:100\n",
  305.                  START, NEXT, 200, 100, REQUIRED),
  306.     NetTextEdit(this, "", NEXT, SAME, 200, 100, AUTOVSCROLL | MULTILINE | WANTRETURN, d.NetText, 9999, 0)
  307.   {
  308.  
  309.   }
  310.  
  311.   virtual void Setup()
  312.   {
  313.     DialogClass::Setup();
  314.     SafeTextEdit.SetText("SAFE:\t\t\t\t" + Data.Safe.Name() +
  315.                          "\nUser:\t\t\t\t" + Data.Safe.UserName() +
  316.                           "\n\nTotal Connections:\t\t" + Data.Safe.TotalConnections() +
  317.                           "\nActive Connections:\t\t" + Data.Safe.ActiveConnections() +
  318.                           "\nConnections To Use:\t\t" + Data.NumConnections +
  319.                           "\n\nRemediation Allowed:\t\t" + (Data.Safe.RemediationAllowed() ? "Yes" : "No") +
  320.                           "\nSnapshot Allowed:\t\t" + (Data.Safe.SnapshotAllowed() ? "Yes" : "No") +
  321.                           "\n\nSAFE Version:\t\t\t" + Data.Safe.Version()
  322.                           );
  323.   }
  324.  
  325.   virtual void CheckControls()
  326.   {
  327.     DialogClass::CheckControls();
  328.     EnableClose(Tree.GetValue().Parent());
  329.   }
  330.  
  331.   virtual bool CanClose()
  332.   {
  333.     Output();
  334.     bool ret = false;
  335.     if (DialogClass::CanClose()) {
  336.       Data.Role = RoleClass::TypeCast(Tree.GetValue());
  337.       ret = Data.ParseText(Data.NetText);
  338.       if (!ret)
  339.         ErrorMessage("Please Enter a value in the IP List Text Area.");
  340.     }
  341.     return ret;
  342.   }
  343. }
  344.  
RAW Paste Data