예제 #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 fdsTestProcessMitigations(oProcess, sProcessType, sHardeningToolsPath):
    sTestType = "process mitigations %s" % oProcess.sBinaryName
    if fbHaveResults(sProcessType, sTestType):
        oConsole.fPrint("Testing %s already completed" % sTestType)
        return
    oConsole.fPrint("Testing ", INFO, sTestType, NORMAL, " for process ", INFO, str(oProcess.uId), NORMAL, \
        " running ", INFO, oProcess.sBinaryName)

    # Child Process Policy
    oTestProcess = subprocess.Popen(
      "POWERSHELL \"Import-Module '%s\\NtObjectManager\\NtObjectManager.psd1'; Use-NtObject($p = Get-NtProcess -ProcessId %d) { Write-Output $p.IsChildProcessRestricted };\"" % \
          (sHardeningToolsPath, oProcess.uId),
      stdout = subprocess.PIPE,
      stderr = subprocess.PIPE,
    )
    (sStdOut, sStdErr) = oTestProcess.communicate()
    assert not sStdErr, \
        "Failed:\r\n%s" % sStdErr
    bChildProcessPolicy = None
    for sLine in sStdOut.split("\r\n"):
        sLine = sLine.rstrip("\r").strip()
        if sLine == "": continue
        bChildProcessPolicy = {
            "True": True,
            "False": False
        }.get(sLine)
        assert bChildProcessPolicy is not None, \
            "Unexpected IsChildProcessRestricted value %s" % repr(sLine)
    assert bChildProcessPolicy is not None, \
        "missing IsChildProcessRestricted value:\r\n%s" % sStdOut

    # Process mitigations
    oTestProcess = subprocess.Popen(
      "POWERSHELL \"Import-Module '%s\\ProcessMitigations\\ProcessMitigations.psd1'; Get-ProcessMitigation -Id %d;\"" % \
          (sHardeningToolsPath, oProcess.uId),
      stdout = subprocess.PIPE,
      stderr = subprocess.PIPE,
    )
    (sStdOut, sStdErr) = oTestProcess.communicate()
    assert not sStdErr, \
        "Failed:\r\n%s" % sStdErr
    dsTestResults = {
        "Child Process Policy":
        bChildProcessPolicy and "true"
        or "FALSE; CHILD PROCESSES CAN BE CREATED AT WILL",
    }
    sSubject = None
    for sLine in sStdOut.split("\r\n"):
        sLine = sLine.rstrip("\r").strip()
        if sLine == "": continue
        if sLine[-1] == ":":
            sSubject = sLine[:-1]
        else:
            oNameValueMatch = re.match(r"(.*?)\s*: (.+)$", sLine)
            assert oNameValueMatch, \
                "Unexpected name value pair: %s\r\n%s" % (repr(sLine), sStdOut)
            sName, sValue = oNameValueMatch.groups()
            if sSubject == "DEP":
                if sName == "Enable":
                    dsTestResults[
                        "DEP enabled"] = sValue == "on" and "true" or "FALSE!"
                elif sName == "Disable ATL":
                    # Take into account on x64 (https://twitter.com/epakskape/status/851783906688876544):
                    if sValue == "off" and oProcess.sISA != "x64":
                        dsTestResults[
                            "Disable ATL Thunk Emulation"] = "FALSE; ATL THUNKS CAN BE EXECUTED IN NON-EXECUTABLE MEMORY!"
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "ASLR":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/hh769086(v=vs.85).aspx
                if sName == "BottomUp":
                    dsTestResults[
                        "ASLR enabled for stack & heap"] = sValue == "on" and "true" or "FALSE; STACK AND HEAP ADDRESSES ARE NOT RANDOMIZED!"
                elif sName == "HighEntropy":
                    if oProcess.sISA == "x86":
                        dsTestResults[
                            "ASLR high entropy"] = "not available on x86"
                    else:
                        dsTestResults[
                            "ASLR high entropy"] = sValue == "on" and "true" or "FALSE; RANDOMIZATION IS LOWER THAN IT COULD BE!"
                elif sName == "ForceRelocate":
                    dsTestResults[
                        "ASLR forced"] = sValue == "on" and "true; even binaries that do not opt-in are randomized" or "FALSE; BINARIES CAN OPT-OUT AND BE LOADED AT PREDICTABLE ADDRESSES!"
                elif sName == "DisallowStripped":
                    dsTestResults[
                        "ASLR disallow stripped relocation"] = sValue == "on" and "true; binaries without relocation information will fail to load" or "FALSE; BINARIES WITHOUT RELOCATION INFORMATION CAN BE LOADED AT PREDICTABLE ADDRESSES!"
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "StrictHandle":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/hh871471(v=vs.85).aspx
                if sName == "RaiseExceptionOnInvalid":
                    if "Invalid handle exceptions" not in dsTestResults:
                        # This may be overwritten later when we parse "HandleExceptionsPermanently"
                        dsTestResults[
                            "Invalid handle exceptions"] = sValue == "on" and "TRUE; BUT CAN BE DISABLED!" or "FALSE; INVALID HANDLES WILL NOT TERMINATE THE APPLICATION!"
                elif sName == "HandleExceptionsPermanently":
                    if sValue == "on":
                        dsTestResults[
                            "Invalid handle exceptions"] = "true (permanently enabled)"
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "System Call":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/hh871472(v=vs.85).aspx
                if sName == "DisallowWin32kSysCalls":
                    dsTestResults[
                        "Disallow win32k system calls"] = sValue == "on" and "true" or "FALSE; WIN32K SYSTEM CALLS CAN BE MADE!"
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "ExtensionPoint":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/jj200586(v=vs.85).aspx
                if sName == "DisableExtensionPoints":
                    # TODO: What does this do?
                    dsTestResults[
                        "Disable Legacy Extension Point DLLs"] = sValue == "on" and "true" or "FALSE; LEGACY EXTENSION POINT DLLS CAN BE LOADED!"
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "DynamicCode":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/mt706243(v=vs.85).aspx
                if sName == "ProhibitDynamicCode":
                    dsTestResults[
                        "ACG enabled"] = sValue == "on" and "true" or "FALSE; CODE CAN BE CREATED DYNAMICALLY!"
                elif sName == "AllowThreadOpt":
                    dsTestResults[
                        "ACG: disallow thread opt-out"] = sValue == "off" and "true" or "FALSE; THREADS ARE ALLOWED TO DISABLE ACG!"
                elif sName == "AllowRemoteDowngrade":
                    dsTestResults[
                        "ACG: disallow remote downgrade"] = sValue == "off" and "true" or "FALSE; ANOTHER PROCESS COULD INSERT ARBITRARY CODE!"
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "CFG":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/mt654121(v=vs.85).aspx
                if sName == "EnableCFG":
                    dsTestResults[
                        "CFG enabled"] = sValue == "on" and "true" or "FALSE; CODE DOES NOT CHECK IF INDIRECT CALL TARGETS ARE VALID!"
                elif sName == "EnableExportSuppression":
                    dsTestResults[
                        "CFG: exports are not valid CFG targets"] = sValue == "off" and "true" or "FALSE; EXPORTED FUNCTIONS ARE VALID INDIRECT CALL TARGETS!"
                elif sName == "StrictMode":
                    dsTestResults[
                        "CFG forced"] = sValue == "on" and "true; binaries without CFG cannot be loaded" or "FALSE; BINARIES WITHOUT CFG CAN BE LOADED!"
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "BinarySignature":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/mt706242(v=vs.85).aspx
                # Note: a default value has been set above.
                if "Signature checks" not in dsTestResults:
                    dsTestResults[
                        "Signature checks"] = "FALSE; ANY BINARY CAN BE LOADED INTO THE PROCESS"
                if sName == "MicrosoftSignedOnly":
                    if sValue == "on":
                        dsTestResults[
                            "Signature checks"] = "true (Microsoft only)"
                elif sName == "StoreSignedOnly":
                    if sValue == "on":
                        dsTestResults[
                            "Signature checks"] = "true (Microsoft Store only)"
                elif sName == "MitigationOptIn":
                    if sValue == "on":
                        dsTestResults[
                            "Signature checks"] = "true (Microsoft, Microsoft Store or WHQL only)"
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "FontDisable":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/mt706244(v=vs.85).aspx
                if sName == "DisableNonSystemFonts":
                    dsTestResults[
                        "Disallow non-system fonts"] = sValue == "on" and "true" or "FALSE; THE PROCESS CAN ATTEMPT TO LOAD ANY FONT FILE!"
                elif sName == "AuditNonSystemFontLoading":
                    # This flag just means stuff gets logged, not that it is mitigated.
                    pass
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
            elif sSubject == "ImageLoad":
                # https://msdn.microsoft.com/en-us/library/windows/desktop/mt706245(v=vs.85).aspx
                if sName == "NoRemoteImages":
                    dsTestResults[
                        "Disallow loading remote images"] = sValue == "on" and "true" or "FALSE; THE PROCESS CAN LOAD BINARIES FROM NETWORK SHARES!"
                elif sName == "NoLowMandatoryLabelImages":
                    dsTestResults[
                        "Disallow low-integrity images"] = sValue == "on" and "true" or "FALSE; THE PROCESS CAN LOAD BINARIES FROM LOW INTEGRITY FOLDERS"
                elif sName == "PreferSystem32Images":
                    # This kinda protects against side-loading attacks, but I don't think it's relevant to the browser.
                    pass
                else:
                    raise AssertionError("Unknown %s name: value pair: %s" %
                                         (sSubject, repr(sLine)))
    return dsTestResults