示例#1
0
def fTestNetworkConnect(oProcess, sProcessType, sNetworkType, sIPAddress, uPort, sSandBoxToolsPath):
  sTestType = "network %s connect" % sNetworkType;
  if fbHaveResults(sProcessType, sTestType):
    oConsole.fPrint("Testing %s already completed" % sTestType);
    return;
  oConsole.fPrint("Testing ", sNetworkType, " network connection for process ", INFO, str(oProcess.uId), NORMAL, " running ", INFO, oProcess.sBinaryName);
  oTestProcess = subprocess.Popen(
    "\"%s\\CheckNetworkAccess\\bin\\Debug\\CheckNetworkAccess.exe\" -p %d %s %d" % (sSandBoxToolsPath, oProcess.uId, sIPAddress, uPort),
    stdout = subprocess.PIPE,
    stderr = subprocess.PIPE,
  );
  (sStdOut, sStdErr) = oTestProcess.communicate();
  assert not sStdErr, "Failed:\r\n%s" % sStdErr;
  if sStdOut in [
    "** Opened Connection **\r\n",
    "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond %s:%d\r\n" % (sIPAddress, uPort),
    "No connection could be made because the target machine actively refused it %s:%d\r\n" % (sIPAddress, uPort),
  ]:
    # Connection was made
    fWriteResults(sProcessType, sTestType, False, "This process is able to open a connection on the %s to %s:%d." % (sNetworkType, sIPAddress, uPort));
  elif sStdOut in [
    "Unknown error (0x271d)\r\n",
    "(0xC0000022) - {Access Denied}\r\nA process has requested access to an object, but has not been granted those access rights.\r\n",
    "An attempt was made to access a socket in a way forbidden by its access permissions %s:%d\r\n" % (sIPAddress, uPort),
  ]:
    fWriteResults(sProcessType, sTestType, True);
  else:
    raise AssertionError("Unknown test output: %s" % sStdOut);
示例#2
0
def fTestNetworkListen(oProcess, sProcessType, sNetworkType, sIPAddress, uPort, sSandBoxToolsPath):
  sTestType = "network %s listen" % sNetworkType;
  if fbHaveResults(sProcessType, sTestType):
    oConsole.fPrint("Testing %s already completed" % sTestType);
    return;
  oConsole.fPrint("Testing ", sNetworkType, " network listen for process ", INFO, str(oProcess.uId), NORMAL, " running ", INFO, oProcess.sBinaryName);
  oTestProcess = subprocess.Popen(
    "\"%s\\CheckNetworkAccess\\bin\\Debug\\CheckNetworkAccess.exe\" -p %d -l %s %d" % (sSandBoxToolsPath, oProcess.uId, sIPAddress, uPort),
    stdout = subprocess.PIPE,
    stderr = subprocess.PIPE,
  );
  # The process is currently suspended, so it can't actually accept a connection.
  # This means the test will hang if it can listen on a port, even if we try to
  # connect to the port. Instead, we will use a timer to terminate the test
  # after five seconds and see if it outputs an error or not.
  abConnectionAccepted = []; # Weird hack to be able to export info from another thread.
  def fConnect():
    oConsole.fStatus("fConnect: Attempting to connect to ", INFO, sIPAddress, NORMAL, ":", INFO, str(uPort), NORMAL, "...");
    try:
      socket.create_connection((sIPAddress, uPort), 5);
    except socket.error as oException:
      abConnectionAccepted.append(False);
    else:
      abConnectionAccepted.append(True);
    oTestProcess.terminate();
  oConnectThread = threading.Thread(target=fConnect);
  oConnectThread.start();
  (sStdOut, sStdErr) = oTestProcess.communicate();
  assert not sStdErr, "Failed:\r\n%s" % sStdErr;
  oConnectThread.join();
  bConnectionAccepted = abConnectionAccepted[0];
  if bConnectionAccepted:
    fWriteResults(sProcessType, sTestType, False, "+ This process is able to listen for connections on the %s at %s:%d.\r\n%s" % (sNetworkType, sIPAddress, uPort, sStdOut));
  elif sStdOut in [
    "Make a connection to %s:%d\r\n" % (sIPAddress, uPort), # It thinks it can accept connections, but it never will.
    "Unknown error (0x271d)\r\n",
    "An attempt was made to access a socket in a way forbidden by its access permissions\r\n",
    "An attempt was made to access a socket in a way that was forbidden by its access permissions\r\n",
    "(0xC0000022) - {Access Denied}\r\nA process has requested access to an object, but has not been granted those access rights.\r\n",
  ]:
    fWriteResults(sProcessType, sTestType, True);
  else:
    raise AssertionError("Unknown test output: %s" % sStdOut);
def fTestProcessAccess(oProcess, sProcessType, sSandBoxToolsPath):
    sTestType = "process access"
    if fbHaveResults(sProcessType, sTestType):
        oConsole.fPrint("Testing %s already completed" % sTestType)
        return
    oConsole.fPrint("Testing process access for process ", INFO,
                    str(oProcess.uId), NORMAL, " running ", INFO,
                    oProcess.sBinaryName)
    oTestProcess = subprocess.Popen(
        "\"%s\\CheckProcessAccess\\bin\\Debug\\CheckProcessAccess.exe\" -p %d"
        % (sSandBoxToolsPath, oProcess.uId),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    (sStdOut, sStdErr) = oTestProcess.communicate()
    assert not sStdErr, "Failed:\r\n%s" % sStdErr
    if sStdOut == "":
        fWriteResults(sProcessType, sTestType, True)
    else:
        fWriteResults(
            sProcessType, sTestType, False,
            "This process is able to access the following processes:\r\n%s" %
            sStdOut)
def fdsTestBinaryHardening(oProcess, sProcessType, oModule, sHardeningToolsPath):
  if oModule.sBinaryPath in gdsBinaryHardeningTestResultsCache_by_sPath:
    return gdsBinaryHardeningTestResultsCache_by_sPath[oModule.sBinaryPath];
  sTestType = "binary hardening %s" % oModule.sBinaryName;
  oConsole.fPrint("Testing binary hardening for ", INFO, oModule.sBinaryName, NORMAL, " for process ", INFO, str(oProcess.uId), NORMAL, " running ", INFO, oProcess.sBinaryName);
  if oModule.sBinaryPath is None:
    fWriteResults(sProcessType, sTestType, False, "The file path could not be determined.");
    return
  if not os.path.isfile(oModule.sBinaryPath):
    oConsole.fPrint(ERROR, "ERROR: the file ", oModule.sBinaryPath, " was not found!");
    fWriteResults(sProcessType, sTestType, False, "The file %s was not found!?" % oModule.sBinaryPath);
    return;
  oTestProcess = subprocess.Popen(
    "POWERSHELL \"Import-Module '%s\\PESecurity\\Get-PESecurity.psm1'; Get-PESecurity -File '%s';\"" % (sHardeningToolsPath, oModule.sBinaryPath),
    stdout = subprocess.PIPE,
    stderr = subprocess.PIPE,
  );
  (sStdOut, sStdErr) = oTestProcess.communicate();
  assert not sStdErr, "Failed:\r\n%s" % sStdErr;
  dsPESecurityOutput = {};
  for sLine in sStdOut.split("\n"):
    oMatch = re.match(r"(\w+)\s*: (.+)", sLine.rstrip("\r"));
    if oMatch:
      sName, sValue = oMatch.groups();
      dsPESecurityOutput[sName] = sValue;
  dsTestResults = {};
  dsTestResults["ASLR enabled"] = dsPESecurityOutput["ASLR"] == "True" and "true" or "FALSE!";
  if dsPESecurityOutput["ARCH"] != "I386":
    dsTestResults["ASLR high entropy"] = dsPESecurityOutput["HighentropyVA"] == "True" and "true" or "FALSE!";
  dsTestResults["DEP enabled"] = {"True": "true", "False": "FALSE!", "N/A": "n/a"}[dsPESecurityOutput["DEP"]]
  dsTestResults["Authenticode enabled"] = {"True": "true", "False": "FALSE!", "N/A": "n/a"}[dsPESecurityOutput["Authenticode"]];
  dsTestResults["SafeSEH enabled"] = {"True": "true", "False": "FALSE!", "N/A": "n/a"}[dsPESecurityOutput["SafeSEH"]];
  dsTestResults["CFG enabled"] = {"True": "true", "False": "FALSE!", "N/A": "n/a"}[dsPESecurityOutput["CFG"]];
  oConsole.fStatus("Testing MemGC for ", INFO, oModule.sBinaryName, NORMAL, " for process ", INFO, str(oProcess.uId), NORMAL, " running ", INFO, oProcess.sBinaryName);
  # MemGC
  bMemGCEnabled = oModule.oProcess.fuGetValue("%s!MemoryProtection::HeapFree" % oModule.sCdbId, "Attempt to detect MemGC") is not None;
  dsTestResults["MemGC enabled"] = bMemGCEnabled and "true" or "FALSE!";
  oConsole.fStatus("Testing VTGuard for ", INFO, oModule.sBinaryName, NORMAL, " for process ", INFO, str(oProcess.uId), NORMAL, " running ", INFO, oProcess.sBinaryName);
  # VTGuard
  uVTGuardValue = (
    oModule.oProcess.fuGetValue("%s!_vtguard" % oModule.sCdbId, "Attempt to detect VTGuard")
    or oModule.oProcess.fuGetValue("%s!__vtguard" % oModule.sCdbId, "Attempt to detect VTGuard")
  );
  if uVTGuardValue is None:
    dsTestResults["VTGuard enabled"] = "FALSE!";
  else:
    asSearchResults = oModule.oProcess.fasExecuteCdbCommand(
      sCommand = "s -%s 0x%X 0x%X 0x%X" % (oModule.sISA == "x86" and "d" or "q", oModule.uStartAddress, oModule.uEndAddress, uVTGuardValue),
      sComment = "Look for references to %s!_vtguard" % oModule.sCdbId,
    );
    asProtectedClasses = set();
    for sLine in asSearchResults:
      oMatch = re.match(r"^([0-9`a-f]+)\s+([0-9`a-f]+)\s+.*", sLine, re.I);
      assert oMatch, \
          "Unexpected search output: %s\r\n%s" % (repr(sLine), "\r\n".join(asSearchResults));
      sVTGuardAddress, sVTGuardValueCheck = oMatch.groups();
      assert long(sVTGuardValueCheck.replace("`", ""), 16) == uVTGuardValue, \
          "Unexpected search output (value !=0x%X): %s\r\n%s" % (uVTGuardValue, repr(sLine), "\r\n".join(asSearchResults));
      uVTGuardAddress = long(sVTGuardAddress.replace("`", ""), 16);
      asSymbolResults = oModule.oProcess.fasExecuteCdbCommand(
        sCommand = "ln 0x%X" % uVTGuardAddress,
        sComment = "Try to detect VTGuard",
      );
      oSymbolMatch = re.match(r"^\(([0-9`a-f]+)\)\s+(\w+!.+?)(?:\+0x[0-9a-f]+)?\s+\|.*", asSymbolResults[0], re.I);
      assert oSymbolMatch, \
          "Unexpected symbol output:\r\n%s" % "\r\n".join(asSymbolResults);
      sSymbolAddress, sSymbol = oSymbolMatch.groups();
      if sSymbol.endswith("::`vftable'"):
        asProtectedClasses.add(sSymbol);
      if len(asSymbolResults) >= 2 and asSymbolResults[1] == "Exact matches:":
        uClassCount = 0;
        # exact match; multiple classes are possible
        for uIndex in xrange(2, len(asSymbolResults)):
          oSymbolMatch = re.match(r"^\s+(\w+!.+?) = .+", asSymbolResults[uIndex], re.I);
          assert oSymbolMatch, \
              "Unrecognized symbol output line %d: %s\r\n%s" % (uIndex + 1, repr(asSymbolResults[uIndex]), "\r\n".join(asSymbolResults));
          sSymbol = oSymbolMatch.group(1);
          if sSymbol.endswith("::`vftable'"):
            asProtectedClasses.add(sSymbol);
    asClassesResult = set(oModule.oProcess.fasExecuteCdbCommand(
      sCommand = "x %s!*::`vftable';" % oModule.sCdbId,
      sComment = "Enumerate classes",
    ));
    for sLine in asClassesResult:
      assert re.match(r"^[0-9`a-f]+\s+%s!.*" % oModule.sCdbId, sLine, re.I), \
          "Unrecognized classes output: %s\r\n%s" % (repr(sLine), "\r\n".join(asClassesResult));
    uTotalClassesCount = len(asClassesResult);
    dsTestResults["VTGuard enabled"] = "true (in %d/%d classes; %.1f%% coverage)" % \
        (len(asProtectedClasses), uTotalClassesCount, len(asProtectedClasses) * 100.0 / uTotalClassesCount);
  gdsBinaryHardeningTestResultsCache_by_sPath[oModule.sBinaryPath] = dsTestResults;
  return dsTestResults;