如何创建病毒签名?

发布于 2024-11-09 11:34:34 字数 90 浏览 0 评论 0 原文

如何创建我自己的 .exe 或 .lib 文件病毒签名?我开始将某些字节读取到文件中,然后将它们存储在另一个文件中,然后手动将其添加到病毒扫描程序中。这行得通吗?谢谢

How can I create my own virus signature of a .exe or .lib file? I started my reading certain bytes to the file and then just storing them in another file and manually adding this to a virus scanner. Will this work? thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海蓝天 2024-11-16 11:34:34

基本上,您需要找到使其独一无二的字节序列,反病毒公司花费大量时间来分析行为、训练并找到独特的东西。防病毒应用程序读取二进制文件以查找字节模式

请阅读 防病毒基础知识:来自卡巴斯基的病毒、签名、杀毒

要从基础开始,您需要创建/维护一个十六进制表,其中签名是唯一列,后跟名称、类型。并读取计算机中的文件并尝试与十六进制数据库表进行匹配。

现在如何保持它的唯一性,因为很难自己分析每个 .exe 来获取签名。如此处所述,请阅读 创建防病毒签名介绍

查找什么是 yara 引擎和引擎此处的规则 virustotal.github.io/yara/ 以及 VirusTotal 如何使用它用于创建 AV 签名,然后创建规则 yararules.com 。很少有像 yaraeditor 可以帮助您,但通过 google 您可以找到更多信息。

然后您可以使用开源防病毒软件,例如 ClamAV github.com/ Cisco-Talos/clamav-devel 并将其用于特定目的。

Basically you need to find a sequence of bytes that's makes it unique, the AV companies spend a lot of time to analyse the behaviour, traints and find something unique. And the Antivirus application reads the binary file to look for the byte pattern

Kindly read the Antivirus fundamentals: Viruses, signatures, disinfection from Kasperskey

To start with basic you need to create/maintain a hex table where signature is unique column followed by the Name, Type. And read files in your computer and try to get a match with the Hex database table.

Now how to keep it unique, as it's hard to analyse each .exe on your own to get the signature. As stated here, kindly read the intro-to-creating-anti-virus-signatures

Look for what is yara Engine & Rules here virustotal.github.io/yara/ and how VirusTotal uses it to create AV signatures then on to rules yararules.com .There are few tools like yaraeditor to help you out but with google you can find more.

Then you can put your hands on OpenSource Antivirus like ClamAV github.com/Cisco-Talos/clamav-devel and use it for purpose.

A君 2024-11-16 11:34:34

创建文件签名的方法有很多种,最简单的方法之一是采用哈希函数(例如 SHA1),并对整个文件运行它。

There are many different ways to create a signature of a file, one of the simplest, and easiest, is to take a hashing function, like SHA1, and run it against the whole file.

一江春梦 2024-11-16 11:34:34

首先必须了解基于散列的分析(与基于签名的分析)以及静态分析(哪些可执行文件应通过)的差异。productAbortListSignatures 生成防病毒签名。
许可证:允许所有使用(“Creative Commons”/“Apache 2”)
[帖子版本为 ?cxx/ClassSys.*xx %s/vector SwuduSusuwu/SubStack@ee7c23a ] 对于最新的源(+​​静态库),请使用诸如 iSH(适用于 iOS)或 Termux(适用于 Android 操作系统)运行此命令:
git 克隆 https://github.com/SwuduSusuwu/SubStack.git && cd ./Substack/ && ./构建
cxx/Macros.hxx
更少 cxx/ClassPortableExecutable.hxx

typedef std::string FilePath;
typedef FilePath FileBytecode;
typedef FilePath FileHash;
typedef class PortableExecutable : Object {
public:
    PortableExecutable(FilePath path_ = "") : path(path_) {}
    PortableExecutable(FilePath path_, FileBytecode bytecode_) : path(path_), bytecode(bytecode_) {}
    const std::string getName() const {return "Susuwu::class PortableExecutable";}
    FilePath path; /* Suchas "C:\Program.exe" or "/usr/bin/library.so" */
    FileBytecode bytecode; /* compiled programs; bytecode */
    std::string hex; /* `hexdump(path)`, hexadecimal, for C string functions */
} PortableExecutable;
typedef class PortableExecutableBytecode : public PortableExecutable {
public:
    PortableExecutableBytecode(FilePath path_) : input(path_) {path = path_; if(input.good()) {bytecode = std::string(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>());}}
    std::ifstream input;
} PortableExecutableBytecode;

更少 cxx/ClassSha2.cxx

/* Uses https://www.rfc-editor.org/rfc/rfc6234#section-8.2.2 */
FileHash sha2(const FileBytecode &bytecode) {
    FileHash result;
    SHA256Context context;
    result.resize(SHA256HashSize);
    SHA256Reset(&context);
    SHA256Input(&context, reinterpret_cast<const unsigned char *>(bytecode.c_str()), bytecode.size());
    SHA256Result(&context, const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(result.c_str())));
    return result;
}

less cxx/ClassResultList.hxx< /a>

typedef FileHash ResultListHash;
typedef FileBytecode ResultListBytecode;
typedef FilePath ResultListSignature;
typedef ptrdiff_t BytecodeOffset;
typedef struct ResultList /* : Object */ {
    const std::string getName() const {return "Susuwu::struct ResultList";}
    std::unordered_set<ResultListHash> hashes; /* Checksums of executables (or pages); to avoid duplicates, plus to do constant ("O(1)") test for which executables (or pages) exists */
    std::vector<ResultListSignature> signatures; /* Smallest substrings (or regexes, or Universal Resource Locators) which can identify `bytecodes`; has uses close to `hashes`, but can match if executables (or pages) have small differences */
    std::vector<ResultListBytecode> bytecodes;
} ResultList;

template<class List>
const size_t listMaxSize(const List &list) {
    auto it = std::max_element(list.cbegin(), list.cend(), [](const auto &s, const auto &x) { return s.size() < x.size(); });
    return it->size();
}

template<class List>
void listDumpTo(const List &list, std::ostream &os, const bool index, const bool whitespace, const bool pascalValues) {
    size_t index_ = 0;
    os << '{';
    for(const auto &value : list) {
        if(0 != index_) {
            os << ',';
        }
        if(whitespace) {
            os << std::endl << '\t';
        }
        if(index) {
            os << index_;
        }
        if(pascalValues) {
                os << value.size() << value;
        } else {
            os << (index ? "=>0x" : "0x");
            for(char ch : value) {
                os << std::hex << static_cast<int>(ch);
            }
            os << std::dec;
        }
        ++index_;
    }
    if(whitespace) {
        os << "\n};" << std::endl;
    } else {
        os << "};";
    }
}
template<class List>
void resultListDumpTo(const List &list, std::ostream &os, const bool index, const bool whitespace, const bool pascalValues) {
    os << "list.hashes" << (whitespace ? " = " : "=");
    listDumpTo(list.hashes, os, index, whitespace, pascalValues);
    os << "list.signatures" << (whitespace ? " = " : "=");
    listDumpTo(list.signatures, os, index, whitespace, pascalValues);
    os << "list.bytecodes" << (whitespace ? " = " : "=");
    listDumpTo(list.bytecodes, os, index, whitespace, pascalValues);
}

template<class List, class List2>
void listToHashes(const List &list /* ResultList::bytecodes or ResultList::hex*/, List2 &hashes /* ResultList::hashess */) {
    for(const auto &value : list) {
        hashes.insert(sha2(value));
    }
}
static void resultListProduceHashes(ResultList &resultList) {
    listToHashes(resultList.bytecodes, resultList.hashes);
}

/* @pre @code std::is_sorted(list.cbegin(), list.cend()) && std::is_sorted(list2.cbegin(), list2.cend()) @endcode */
template<class List>
const List listIntersections(const List &list, const List &list2) {
    List intersections;
    std::set_intersection(list.cbegin(), list.cend(), list2.cbegin(), list2.cend(), std::back_inserter(intersections));
    return intersections;
}
template<class List>
const bool listsIntersect(const List &list, const List &list2) {
    return listIntersections(list, list2).size();
}

template<class List>
auto listFindValue(const List &list, const typename List::value_type &value) {
    return std::find(list.cbegin(), list.cend(), value);
}
template<class List>
const bool listHasValue(const List &list, const typename List::value_type &value) {
    return list.cend() != listFindValue(list, value);
}

template<class List>
const typename List::value_type::const_iterator listDefaultIterator = typename List::value_type::const_iterator(); /* Equates to "Not found" */
template<class List>
/* @pre @code itBegin < itEnd @endcode */
typeof listDefaultIterator<List> listFindSubstr(const List &list, typename List::value_type::const_iterator itBegin, typename List::value_type::const_iterator itEnd) {
#pragma unroll
    for(const auto &value : list) {
        auto result = std::search(value.cbegin(), value.cend(), itBegin, itEnd, [](char chValue, char chIt) { return chValue == chIt; });
        if(value.cend() != result) {
            return result;
        }
    }
    return listDefaultIterator<List>;
}
template<class List>
/* @pre @code itBegin < itEnd @endcode */
const bool listHasSubstr(const List &list, typename List::value_type::const_iterator itBegin, typename List::value_type::const_iterator itEnd) {
    return listDefaultIterator<List> != listFindSubstr(list, itBegin, itEnd);
}
template<class List>
const std::tuple<typename List::value_type::const_iterator, typename List::value_type::const_iterator> listProduceSignature(const List &list, const typename List::value_type &value) {
    size_t smallest = value.size();
    auto itBegin = value.cbegin(), itEnd = value.cend();
    for(auto first = itBegin; value.cend() != first; ++first) {
        for(auto last = value.cend(); first != last; --last) {
            if((last - first) < smallest) {
                if(listHasSubstr(list, first, last)) {
                    break;
                }
                smallest = last - first;
                itBegin = first, itEnd = last;
            }
        }
    }
    return {itBegin, itEnd};
}
typedef struct ResultListSignatureMatch {
    BytecodeOffset fileOffset;
    ResultListSignature signature;
} ResultListSignatureMatch;
#include "Macros.hxx" /* SUSUWU_DEBUG */
template<class List>
ResultListSignatureMatch listFindSignatureOfValue(const List &list, const typename List::value_type &value) {
    for(const auto &signature : list) {
        auto it = std::search(value.cbegin(), value.cend(), signature.cbegin(), signature.cend(), [](char ch1, char ch2) { return ch1 == ch2; });
        if(signature.cend() != it) {
            return {it - value.cbegin(), signature};
        }
    }
    return {-1, ""};
}
template<class List>
const bool listHasSignatureOfValue(const List &list, const typename List::value_type &value) {
    return -1 != listFindSignatureOfValue(list, value).fileOffset;
}

template<class S>
const std::vector<S> explodeToList(const S &s, const S &token) {
    std::vector<S> list;
    for(auto x = s.cbegin(); s.cend() != x; ) {
        auto it = std::search(x, s.cend(), token.cbegin(), token.cend(), [](char ch1, char ch2) { return ch1 == ch2; });
        list.push_back(S(x, it));
        if(s.cend() == x) {
            return list;
        }
        x = it;
    }
    return list;
}

cxx/ClassCns.hxx

cxx/ClassCns.cxx

less cxx/ClassSys.hxx

extern int classSysArgc;
extern const char **classSysArgs;
bool classSysInit(int argc, const char *args[]);

/* @pre @code (-1 != access(argv[0], X_OK) @endcode */
const pid_t execvesFork(const std::vector<std::string> &argvS = {}, const std::vector<std::string> &envpS = {});
static const pid_t execvexFork(const std::string &toSh) {return execvesFork({"/bin/sh", "-c", toSh});}

const int execves(const std::vector<std::string> &argvS = {}, const std::vector<std::string> &envpS = {});
static const int execvex(const std::string &toSh) {return execves({"/bin/sh", "-c", toSh});}

const bool hasRoot();
const bool setRoot(bool root);

template<typename Func, typename... Args>
auto templateCatchAll(Func func, const std::string &funcName, Args... args) {
    try {
        return func(args...);
    } catch (const std::exception &ex) {
        SUSUWU_CERR(ERROR, funcName + " {throw std::exception(\"" + ex.what() + "\");}");
        return decltype(func(args...))();
    }
}

cxx/ClassSys.cxx

less cxx/VirusAnalysis.hxx

typedef enum VirusAnalysisHook : char {
    virusAnalysisHookDefault = 0,      /* "real-time" virus scans not initialized */
    virusAnalysisHookQuery   = 0,      /* return present hooks (as enum) */
    virusAnalysisHookClear   = 1 << 0, /* unhook (remove present hooks), then parse rest of bits */
    virusAnalysisHookExec    = 1 << 1, /* hook {execl(), execlp(), execle(), execv(), execvp(), execvpe()} */
    virusAnalysisHookNewFile = 1 << 2, /* hook (for modeNew in {"w+", "a", "a+"}) fwrite((void *)ptr, (size_t)size, (size_t)nmemb, {fopen((const char *)pathname, modeNew), fdopen((int)fd, modeNew), freopen((const char *)pathname, modeNew, (FILE *)stream)}) */
}
} VirusAnalysisHook;
static const VirusAnalysisHook operator|(VirusAnalysisHook x,  VirusAnalysisHook s) {return static_cast<VirusAnalysisHook>(static_cast<unsigned>(x) | static_cast<unsigned>(s));}
static const VirusAnalysisHook operator&(VirusAnalysisHook x,  VirusAnalysisHook s) {return static_cast<VirusAnalysisHook>(static_cast<unsigned>(x) & static_cast<unsigned>(s));}
static VirusAnalysisHook globalVirusAnalysisHook = virusAnalysisHookDefault;

typedef enum VirusAnalysisResult : char {
    virusAnalysisAbort = static_cast<char>(false), /* do not launch */
    virusAnalysisPass = static_cast<char>(true), /* launch this (file passes) */
    virusAnalysisRequiresReview, /* submit to hosts to do analysis */
    virusAnalysisContinue /* continue to next tests */
} VirusAnalysisResult;

extern ResultList passList, abortList;
extern Cns analysisCns, virusFixCns;

/* @pre @code analysisCns.hasImplementation() && virusFixCns.hasImplementation() @endcode */
const bool virusAnalysisTests();
static const bool virusAnalysisTestsNoexcept() NOEXCEPT {return templateCatchAll(virusAnalysisTests, "virusAnalysisTests()");}
const bool virusAnalysisHookTests;
static const bool virusAnalysisHookTestsNoexcept() NOEXCEPT {return templateCatchAll(virusAnalysisHookTests, "virusAnalysisHookTests()");}

const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook);
static const VirusAnalysisHook virusAnalysisGetHook() {return virusAnalysisHook(virusAnalysisHookQuery);}

const VirusAnalysisResult hashAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);

/* To produce virus signatures:
 * use passlists (of files reviewed which pass),
 * plus abortlists (of files which failed), such lists as Virustotal has.
 * `produceAbortListSignatures()` is to produce the `abortList.signatures` list, with the smallest substrings unique to infected files; is slow, requires huge database of executables; just hosts should produce this.
 * For clients: Comodo has lists of virus signatures to check against at https://www.comodo.com/home/internet-security/updates/vdp/database.php
 * @pre @code passList.bytecodes.size() && abortList.bytecodes.size() && !listsIntersect(passList.bytecodes, abortList.bytecodes) @endcode
 * @post @code abortList.signatures.size() @endcode */
void produceAbortListSignatures(const ResultList &passList, ResultList &abortList);
 /* @pre @code abortList.signatures.size() @endcode */
const VirusAnalysisResult signatureAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);

/* @throw bad_alloc */
const std::vector<std::string> importedFunctionsList(const PortableExecutable &file);
extern std::vector<std::string> syscallPotentialDangers;
const VirusAnalysisResult staticAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);
const VirusAnalysisResult sandboxAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);
extern std::vector<std::string> stracePotentialDangers;
const VirusAnalysisResult straceOutputsAnalysis(const FilePath &straceOutput); /* TODO: regex */

/* @pre @code cns.hasImplementation() && pass.bytecodes.size() && abort.bytecodes.size() @endcode
 * @post @code cns.isInitialized() @endcode */
void produceAnalysisCns(const ResultList &pass, const ResultList &abort,
    const ResultList &unreviewed = ResultList(),
    Cns &cns = analysisCns
);
/* @pre @code cns.isInitialized() @endcode */
const float cnsAnalysisScore(const PortableExecutable &file, const ResultListHash &fileHash, const Cns &cns = analysisCns);
/* @pre @code cns.isInitialized() @endcode */
const VirusAnalysisResult cnsAnalysis_(const PortableExecutable &file, const ResultListHash &fileHash, const Cns &cns = analysisCns);
const VirusAnalysisResult cnsAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);

extern std::map<ResultListHash, VirusAnalysisResult> hashAnalysisCaches, signatureAnalysisCaches, staticAnalysisCaches, cnsAnalysisCaches, sandboxAnalysisCaches; 

typedef const VirusAnalysisResult (*VirusAnalysisFun)(const PortableExecutable &file, const ResultListHash &fileHash);
extern std::vector<typeof(VirusAnalysisFun)> virusAnalyses;

const VirusAnalysisResult virusAnalysis(const PortableExecutable &file);
static const VirusAnalysisResult submitSampleToHosts(const PortableExecutable &file) {return virusAnalysisRequiresReview;} /* TODO */

/* @pre @code cns.hasImplementation() @endcode
 * @post @code cns.isInitialized() @encode */
void produceVirusFixCns(
    const ResultList &passOrNull, /* Expects `resultList->bytecodes[x] = NULL` if does not pass */
    const ResultList &abortOrNull, /* Expects `resultList->bytecodes[x] = NULL` if does pass */
    Cns &cns = virusFixCns
);

/* @pre @code cns.isInitialized() @endcode */
const std::string cnsVirusFix(const PortableExecutable &file, const Cns &cns = virusFixCns);

less cxx/VirusAnalysis.cxx

VirusAnalysisHook globalVirusAnalysisHook = virusAnalysisHookDefault;
ResultList passList, abortList;
Cns analysisCns, virusFixCns;
std::vector<std::string> syscallPotentialDangers = {
    "memopen", "fwrite", "socket", "GetProcAddress", "IsVmPresent"
};
std::vector<std::string> stracePotentialDangers = {"write(*)"};
std::map<ResultListHash, VirusAnalysisResult> hashAnalysisCaches, signatureAnalysisCaches, staticAnalysisCaches, cnsAnalysisCaches, sandboxAnalysisCaches;

std::vector<typeof(VirusAnalysisFun)> virusAnalyses = {hashAnalysis, signatureAnalysis, staticAnalysis, cnsAnalysis, sandboxAnalysis};

const bool virusAnalysisTests() {
    ResultList abortOrNull {
        .bytecodes {
            "infection",
            "infectedSW",
            "corruptedSW",
            ""
        }
    };
    ResultList passOrNull {
        .bytecodes {
            "",
            "SW",
            "SW",
            "newSW"
        }
    };
    resultListProduceHashes(passOrNull);
    resultListProduceHashes(abortOrNull);
    produceAbortListSignatures(passOrNull, abortOrNull);
    SUSUWU_NOTICE_DEBUGEXECUTE(resultListDumpTo(passOrNull, std::cout, true, true, false));
    SUSUWU_NOTICE_DEBUGEXECUTE((resultListDumpTo(/*.list = */abortOrNull, std::cout, false, false, false), std::cout << std::endl));
    assert(4 == passOrNull.bytecodes.size());
    assert(passOrNull.bytecodes.size() - 1 /* 2 instances of "SW", discount dup */ == passOrNull.hashes.size());
    assert(0 == passOrNull.signatures.size());
    assert(4 == abortOrNull.bytecodes.size());
    assert(abortOrNull.bytecodes.size() == abortOrNull.hashes.size());
    assert(abortOrNull.bytecodes.size() - 1 /* discount empty substr */ == abortOrNull.signatures.size());
    produceAnalysisCns(passOrNull, abortOrNull, ResultList(), analysisCns);
    produceVirusFixCns(passOrNull, abortOrNull, virusFixCns);
    if(0 < classSysArgc) {
        PortableExecutableBytecode executable(classSysArgs[0]);
        if(virusAnalysisAbort == virusAnalysis(executable)) {
            throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "{virusAnalysisAbort == virusAnalysis(args[0]);} /* With such false positives, shouldn't hook kernel modules */"));
        }
    }
    const bool originalRootStatus = hasRoot();
    setRoot(true);
    virusAnalysisHookTests();
    setRoot(originalRootStatus);
    return true;
}

const bool virusAnalysisHookTests() {
    const VirusAnalysisHook originalHookStatus = virusAnalysisGetHook();
    VirusAnalysisHook hookStatus = virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookExec);
    if(virusAnalysisHookExec != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookExec)` == " + std::to_string(hookStatus));
        return false;
    }
    hookStatus = virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookNewFile);
    if(virusAnalysisHookNewFile != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookNewFile)` == " + std::to_string(hookStatus));
        return false;
    }
    hookStatus = virusAnalysisHook(virusAnalysisHookClear);
    if(virusAnalysisHookDefault != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisHookClear)` == " + std::to_string(hookStatus));
        return false;
    }
    hookStatus = virusAnalysisHook(virusAnalysisHookExec | virusAnalysisHookNewFile);
    if((virusAnalysisHookExec | virusAnalysisHookNewFile) != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisExec | virusAnalysisHookNewFile)` == " + std::to_string(hookStatus));
        return false;
    }
    hookStatus = virusAnalysisHook(virusAnalysisHookClear | originalHookStatus);
    if(originalHookStatus != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisHookClear | originalHookStatus)` == " + std::to_string(hookStatus));
        return false;
    }
    return true;
}
const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook virusAnalysisHookStatus) {
    const VirusAnalysisHook originalHookStatus = globalVirusAnalysisHook;
    if(virusAnalysisHookQuery == virusAnalysisHookStatus || originalHookStatus == virusAnalysisHookStatus) {
        return originalHookStatus;
    }
    if(virusAnalysisHookClear & virusAnalysisHookStatus) {
        /* TODO: undo OS-specific "hook"s/"callback"s */
        globalVirusAnalysisHook = virusAnalysisHookDefault;
    }
    if(virusAnalysisHookExec & virusAnalysisHookStatus) {
        /* callbackHook("exec*", */ [](const PortableExecutable &file) { /* TODO: OS-specific "hook"/"callback" for `exec()`/app-launches */
            switch(virusAnalysis(file)) {
            case virusAnalysisPass:
                return true; /* launch this */
            case virusAnalysisRequiresReview:
                submitSampleToHosts(file); /* manual review */
                    return false;
            default:
                return false; /* abort */
            }
        } /* ) */ ;
        globalVirusAnalysisHook = (globalVirusAnalysisHook | virusAnalysisHookExec);
    }
    if(virusAnalysisHookNewFile & virusAnalysisHookStatus) {
        /* callbackHook("fwrite", */ /* TODO: OS-specific "hook"/"callback" for new files/downloads */
        globalVirusAnalysisHook = (globalVirusAnalysisHook | virusAnalysisHookNewFile);
    }
    return virusAnalysisGetHook();
}

const VirusAnalysisResult virusAnalysis(const PortableExecutable &file) {
    const auto fileHash = sha2(file.bytecode);
    for(const auto &analysis : virusAnalyses) {
        switch(analysis(file, fileHash)) {
            case virusAnalysisPass:
                return virusAnalysisPass;
            case virusAnalysisRequiresReview:
                /*submitSampleToHosts(file);*/ /* TODO:? */
                return virusAnalysisRequiresReview;
            case virusAnalysisAbort:
                return virusAnalysisAbort;
            virusAnalysisContinue:
                continue;
        }
    }
    return virusAnalysisPass;
}

const VirusAnalysisResult hashAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    try {
        const auto result = hashAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        if(listHasValue(passList.hashes, fileHash)) {
            return hashAnalysisCaches[fileHash] = virusAnalysisPass;
        } else if(listHasValue(abortList.hashes, fileHash)) {
            return hashAnalysisCaches[fileHash] = virusAnalysisAbort;
        } else {
            return hashAnalysisCaches[fileHash] =  virusAnalysisContinue; /* continue to next tests */
        }
    }
}

const VirusAnalysisResult signatureAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    try {
        const auto result = signatureAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        if(listHasSignatureOfValue(abortList.signatures, file.bytecode)) {
            return signatureAnalysisCaches[fileHash] = virusAnalysisAbort;
        }
        return signatureAnalysisCaches[fileHash] = virusAnalysisContinue;
    }
}

void produceAbortListSignatures(const ResultList &passList, ResultList &abortList) {
    abortList.signatures.reserve(abortList.bytecodes.size());
    for(const auto &file : abortList.bytecodes) {
        auto tuple = listProduceSignature(passList.bytecodes, file);
        if(std::get<0>(tuple) < std::get<1>(tuple)) {
            abortList.signatures.push_back(ResultListSignature(std::get<0>(tuple), std::get<1>(tuple)));
        }
    } /* The most simple signature is a substring, but some analyses use regexes. */
}

const std::vector<std::string> importedFunctionsList(const PortableExecutable &file) {
    return {}; /* fixes crash, until importedFunctionsList is implemented/finished */
/* TODO: https://www.codeproject.com/Questions/338807/How-to-get-list-of-all-imported-functions-invoked shows how to analyse dynamic loads of functions (if do this, `syscallPotentialDangers[]` does not include `GetProcAddress()`.)
 */
}

const VirusAnalysisResult staticAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    try {
        const auto result = staticAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        auto syscallsUsed = importedFunctionsList(file);
        std::sort(syscallPotentialDangers.begin(), syscallPotentialDangers.end());
        std::sort(syscallsUsed.begin(), syscallsUsed.end());
        if(listsIntersect(syscallPotentialDangers, syscallsUsed)) {
            return staticAnalysisCaches[fileHash] = virusAnalysisRequiresReview;
        }
        return staticAnalysisCaches[fileHash] = virusAnalysisContinue;
    }
}

const VirusAnalysisResult sandboxAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    try {
        const auto result = sandboxAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        execvex("cp -r '/usr/home/sandbox/' '/usr/home/sandbox.bak'"); /* or produce FS snapshot */
        execvex("cp '" + file.path + "' '/usr/home/sandbox/'");
        execvex("chroot '/usr/home/sandbox/' \"strace basename '" + file.path + "'\" >> strace.outputs");
        execvex("mv/ '/usr/home/sandbox/strace.outputs' '/tmp/strace.outputs'");
        execvex("rm -r '/usr/home/sandbox/' && mv '/usr/home/sandbox.bak' '/usr/home/sandbox/'"); /* or restore FS snapshot */
        return sandboxAnalysisCaches[fileHash] = straceOutputsAnalysis("/tmp/strace.outputs");
    }
}
const VirusAnalysisResult straceOutputsAnalysis(const FilePath &straceOutput) {
        auto straceDump = std::ifstream(straceOutput);
        std::vector<std::string> straceOutputs /*= explodeToList(straceDump, "\n")*/;
        for(std::string straceOutput; std::getline(straceDump, straceOutput); ) {
            straceOutputs.push_back(straceOutput);
        }
        std::sort(stracePotentialDangers.begin(), stracePotentialDangers.end());
        std::sort(straceOutputs.begin(), straceOutputs.end());
        if(listsIntersect(stracePotentialDangers, straceOutputs)) { /* Todo: regex */
            return virusAnalysisRequiresReview;
        }
    return virusAnalysisContinue;
}

void produceAnalysisCns(const ResultList &pass, const ResultList &abort,const ResultList &unreviewed,Cns &cns) {
    std::vector<std::tuple<FileBytecode, float>> inputsToOutputs;
    const size_t maxPassSize = listMaxSize(pass.bytecodes);
    const size_t maxAbortSize = listMaxSize(abort.bytecodes);
    cns.setInputMode(cnsModeString);
    cns.setOutputMode(cnsModeFloat);
    cns.setInputNeurons(maxPassSize > maxAbortSize ? maxPassSize : maxAbortSize);
    cns.setOutputNeurons(1);
    cns.setLayersOfNeurons(6666);
    cns.setNeuronsPerLayer(26666);
    inputsToOutputs.reserve(pass.bytecodes.size());
    for(const auto &bytecodes : pass.bytecodes) {
        inputsToOutputs.push_back({bytecodes, 1.0});
    }
    cns.setupSynapses(inputsToOutputs);
    inputsToOutputs.clear();
    if(!unreviewed.bytecodes.empty()) {
        inputsToOutputs.reserve(unreviewed.bytecodes.size());
        for(const auto &bytecodes : unreviewed.bytecodes) {
            inputsToOutputs.push_back({bytecodes, 1 / 2});
        }
        cns.setupSynapses(inputsToOutputs);
        inputsToOutputs.clear();
    }
    inputsToOutputs.reserve(abort.bytecodes.size());
    for(const auto &bytecodes : abort.bytecodes) {
        inputsToOutputs.push_back({bytecodes, 0.0});
    }
    cns.setupSynapses(inputsToOutputs);
    inputsToOutputs.clear();
}
const float cnsAnalysisScore(const PortableExecutable &file, const Cns &cns) {
    return cns.processToFloat(file.bytecode);
}
const VirusAnalysisResult cnsAnalysis_(const PortableExecutable &file, const ResultListHash &fileHash, const Cns &cns) {
    try {
        const auto result = cnsAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        return cnsAnalysisCaches[fileHash] = static_cast<bool>(round(cnsAnalysisScore(file, cns))) ? virusAnalysisContinue : virusAnalysisRequiresReview;
    }
}
const VirusAnalysisResult cnsAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    return cnsAnalysis_(file, fileHash);
}

void produceVirusFixCns(const ResultList &passOrNull, const ResultList &abortOrNull, Cns &cns) {
    std::vector<std::tuple<FileBytecode, FileBytecode>> inputsToOutputs;
    cns.setInputMode(cnsModeString);
    cns.setOutputMode(cnsModeString);
    cns.setInputNeurons(listMaxSize(passOrNull.bytecodes));
    cns.setOutputNeurons(listMaxSize(abortOrNull.bytecodes));
    cns.setLayersOfNeurons(6666);
    cns.setNeuronsPerLayer(26666);
    assert(passOrNull.bytecodes.size() == abortOrNull.bytecodes.size());
    inputsToOutputs.reserve(passOrNull.bytecodes.size());
    for(int x = 0; passOrNull.bytecodes.size() > x; ++x) {
        inputsToOutputs.push_back({abortOrNull.bytecodes[x], passOrNull.bytecodes[x]});
    }
    cns.setupSynapses(inputsToOutputs);
}

const FileBytecode cnsVirusFix(const PortableExecutable &file, const Cns &cns /* = virusFixCns */) {
    return cns.processToString(file.bytecode);
}

less cxx/main.cxx

namespace Susuwu {
void noExcept() NOEXCEPT;
NORETURN void noReturn();
void noExcept() NOEXCEPT {std::cout << std::flush;}
void noReturn() {exit(0);}
int testHarnesses() EXPECTS(true) ENSURES(true) {
    std::cout << "cxx/Macros.hxx: " << std::flush;
    ASSUME(true);
    noExcept();
    std::cout << "pass" << std::endl;
    std::cout << "execves(): " << std::flush;
    (EXIT_SUCCESS == execves({"/bin/echo", "pass"})) || std::cout << "error" << std::endl;
    std::cout << "execvex(): " << std::flush;
    (EXIT_SUCCESS == execvex("/bin/echo pass")) || std::cout << "error" << std::endl;
    std::cout << "virusAnalysisTestsNoexcept(): " << std::flush;
    if(virusAnalysisTestsNoexcept()) {
        std::cout << "pass" << std::endl;
    } else {
        std::cout << "error" << std::endl;
    }
    std::cout << "assistantCnsTestsNoexcept(): " << std::flush;
    if(assistantCnsTestsNoexcept()) {
        std::cout << "pass" << std::endl;
    } else {
        std::cout << "error" << std::endl;
    }
    noReturn();
}
}; /* namespace Susuwu */
int main(int argc, const char **args) {
    const bool classSysInitSuccess = Susuwu::classSysInit(argc, args);
    assert(classSysInitSuccess);
    return Susuwu::testHarnesses();
}

用于比较; productVirusFixCns 接近助手
cxx/AssistantCns.hxx
cxx/AssistantCns.cxx
/* 由于 30000 个字符限制而被剪断 */

First must understand differences of hash-based (versus signature based analysis,) plus the static analyses (which executables should pass.) produceAbortListSignatures produces signatures for antivirus.
Licenses: allows all uses ("Creative Commons"/"Apache 2")
[ Version of post is ?cxx/ClassSys.*xx %s/vector<const /vector< SwuduSusuwu/SubStack@ee7c23a ] For the most new sources (+ static libs), use apps such as iSH (for iOS) or Termux (for Android OS) to run this:
git clone https://github.com/SwuduSusuwu/SubStack.git && cd ./Substack/ && ./build
cxx/Macros.hxx
less cxx/ClassPortableExecutable.hxx

typedef std::string FilePath;
typedef FilePath FileBytecode;
typedef FilePath FileHash;
typedef class PortableExecutable : Object {
public:
    PortableExecutable(FilePath path_ = "") : path(path_) {}
    PortableExecutable(FilePath path_, FileBytecode bytecode_) : path(path_), bytecode(bytecode_) {}
    const std::string getName() const {return "Susuwu::class PortableExecutable";}
    FilePath path; /* Suchas "C:\Program.exe" or "/usr/bin/library.so" */
    FileBytecode bytecode; /* compiled programs; bytecode */
    std::string hex; /* `hexdump(path)`, hexadecimal, for C string functions */
} PortableExecutable;
typedef class PortableExecutableBytecode : public PortableExecutable {
public:
    PortableExecutableBytecode(FilePath path_) : input(path_) {path = path_; if(input.good()) {bytecode = std::string(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>());}}
    std::ifstream input;
} PortableExecutableBytecode;

less cxx/ClassSha2.cxx

/* Uses https://www.rfc-editor.org/rfc/rfc6234#section-8.2.2 */
FileHash sha2(const FileBytecode &bytecode) {
    FileHash result;
    SHA256Context context;
    result.resize(SHA256HashSize);
    SHA256Reset(&context);
    SHA256Input(&context, reinterpret_cast<const unsigned char *>(bytecode.c_str()), bytecode.size());
    SHA256Result(&context, const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(result.c_str())));
    return result;
}

less cxx/ClassResultList.hxx

typedef FileHash ResultListHash;
typedef FileBytecode ResultListBytecode;
typedef FilePath ResultListSignature;
typedef ptrdiff_t BytecodeOffset;
typedef struct ResultList /* : Object */ {
    const std::string getName() const {return "Susuwu::struct ResultList";}
    std::unordered_set<ResultListHash> hashes; /* Checksums of executables (or pages); to avoid duplicates, plus to do constant ("O(1)") test for which executables (or pages) exists */
    std::vector<ResultListSignature> signatures; /* Smallest substrings (or regexes, or Universal Resource Locators) which can identify `bytecodes`; has uses close to `hashes`, but can match if executables (or pages) have small differences */
    std::vector<ResultListBytecode> bytecodes;
} ResultList;

template<class List>
const size_t listMaxSize(const List &list) {
    auto it = std::max_element(list.cbegin(), list.cend(), [](const auto &s, const auto &x) { return s.size() < x.size(); });
    return it->size();
}

template<class List>
void listDumpTo(const List &list, std::ostream &os, const bool index, const bool whitespace, const bool pascalValues) {
    size_t index_ = 0;
    os << '{';
    for(const auto &value : list) {
        if(0 != index_) {
            os << ',';
        }
        if(whitespace) {
            os << std::endl << '\t';
        }
        if(index) {
            os << index_;
        }
        if(pascalValues) {
                os << value.size() << value;
        } else {
            os << (index ? "=>0x" : "0x");
            for(char ch : value) {
                os << std::hex << static_cast<int>(ch);
            }
            os << std::dec;
        }
        ++index_;
    }
    if(whitespace) {
        os << "\n};" << std::endl;
    } else {
        os << "};";
    }
}
template<class List>
void resultListDumpTo(const List &list, std::ostream &os, const bool index, const bool whitespace, const bool pascalValues) {
    os << "list.hashes" << (whitespace ? " = " : "=");
    listDumpTo(list.hashes, os, index, whitespace, pascalValues);
    os << "list.signatures" << (whitespace ? " = " : "=");
    listDumpTo(list.signatures, os, index, whitespace, pascalValues);
    os << "list.bytecodes" << (whitespace ? " = " : "=");
    listDumpTo(list.bytecodes, os, index, whitespace, pascalValues);
}

template<class List, class List2>
void listToHashes(const List &list /* ResultList::bytecodes or ResultList::hex*/, List2 &hashes /* ResultList::hashess */) {
    for(const auto &value : list) {
        hashes.insert(sha2(value));
    }
}
static void resultListProduceHashes(ResultList &resultList) {
    listToHashes(resultList.bytecodes, resultList.hashes);
}

/* @pre @code std::is_sorted(list.cbegin(), list.cend()) && std::is_sorted(list2.cbegin(), list2.cend()) @endcode */
template<class List>
const List listIntersections(const List &list, const List &list2) {
    List intersections;
    std::set_intersection(list.cbegin(), list.cend(), list2.cbegin(), list2.cend(), std::back_inserter(intersections));
    return intersections;
}
template<class List>
const bool listsIntersect(const List &list, const List &list2) {
    return listIntersections(list, list2).size();
}

template<class List>
auto listFindValue(const List &list, const typename List::value_type &value) {
    return std::find(list.cbegin(), list.cend(), value);
}
template<class List>
const bool listHasValue(const List &list, const typename List::value_type &value) {
    return list.cend() != listFindValue(list, value);
}

template<class List>
const typename List::value_type::const_iterator listDefaultIterator = typename List::value_type::const_iterator(); /* Equates to "Not found" */
template<class List>
/* @pre @code itBegin < itEnd @endcode */
typeof listDefaultIterator<List> listFindSubstr(const List &list, typename List::value_type::const_iterator itBegin, typename List::value_type::const_iterator itEnd) {
#pragma unroll
    for(const auto &value : list) {
        auto result = std::search(value.cbegin(), value.cend(), itBegin, itEnd, [](char chValue, char chIt) { return chValue == chIt; });
        if(value.cend() != result) {
            return result;
        }
    }
    return listDefaultIterator<List>;
}
template<class List>
/* @pre @code itBegin < itEnd @endcode */
const bool listHasSubstr(const List &list, typename List::value_type::const_iterator itBegin, typename List::value_type::const_iterator itEnd) {
    return listDefaultIterator<List> != listFindSubstr(list, itBegin, itEnd);
}
template<class List>
const std::tuple<typename List::value_type::const_iterator, typename List::value_type::const_iterator> listProduceSignature(const List &list, const typename List::value_type &value) {
    size_t smallest = value.size();
    auto itBegin = value.cbegin(), itEnd = value.cend();
    for(auto first = itBegin; value.cend() != first; ++first) {
        for(auto last = value.cend(); first != last; --last) {
            if((last - first) < smallest) {
                if(listHasSubstr(list, first, last)) {
                    break;
                }
                smallest = last - first;
                itBegin = first, itEnd = last;
            }
        }
    }
    return {itBegin, itEnd};
}
typedef struct ResultListSignatureMatch {
    BytecodeOffset fileOffset;
    ResultListSignature signature;
} ResultListSignatureMatch;
#include "Macros.hxx" /* SUSUWU_DEBUG */
template<class List>
ResultListSignatureMatch listFindSignatureOfValue(const List &list, const typename List::value_type &value) {
    for(const auto &signature : list) {
        auto it = std::search(value.cbegin(), value.cend(), signature.cbegin(), signature.cend(), [](char ch1, char ch2) { return ch1 == ch2; });
        if(signature.cend() != it) {
            return {it - value.cbegin(), signature};
        }
    }
    return {-1, ""};
}
template<class List>
const bool listHasSignatureOfValue(const List &list, const typename List::value_type &value) {
    return -1 != listFindSignatureOfValue(list, value).fileOffset;
}

template<class S>
const std::vector<S> explodeToList(const S &s, const S &token) {
    std::vector<S> list;
    for(auto x = s.cbegin(); s.cend() != x; ) {
        auto it = std::search(x, s.cend(), token.cbegin(), token.cend(), [](char ch1, char ch2) { return ch1 == ch2; });
        list.push_back(S(x, it));
        if(s.cend() == x) {
            return list;
        }
        x = it;
    }
    return list;
}

cxx/ClassCns.hxx

cxx/ClassCns.cxx

less cxx/ClassSys.hxx

extern int classSysArgc;
extern const char **classSysArgs;
bool classSysInit(int argc, const char *args[]);

/* @pre @code (-1 != access(argv[0], X_OK) @endcode */
const pid_t execvesFork(const std::vector<std::string> &argvS = {}, const std::vector<std::string> &envpS = {});
static const pid_t execvexFork(const std::string &toSh) {return execvesFork({"/bin/sh", "-c", toSh});}

const int execves(const std::vector<std::string> &argvS = {}, const std::vector<std::string> &envpS = {});
static const int execvex(const std::string &toSh) {return execves({"/bin/sh", "-c", toSh});}

const bool hasRoot();
const bool setRoot(bool root);

template<typename Func, typename... Args>
auto templateCatchAll(Func func, const std::string &funcName, Args... args) {
    try {
        return func(args...);
    } catch (const std::exception &ex) {
        SUSUWU_CERR(ERROR, funcName + " {throw std::exception(\"" + ex.what() + "\");}");
        return decltype(func(args...))();
    }
}

cxx/ClassSys.cxx

less cxx/VirusAnalysis.hxx

typedef enum VirusAnalysisHook : char {
    virusAnalysisHookDefault = 0,      /* "real-time" virus scans not initialized */
    virusAnalysisHookQuery   = 0,      /* return present hooks (as enum) */
    virusAnalysisHookClear   = 1 << 0, /* unhook (remove present hooks), then parse rest of bits */
    virusAnalysisHookExec    = 1 << 1, /* hook {execl(), execlp(), execle(), execv(), execvp(), execvpe()} */
    virusAnalysisHookNewFile = 1 << 2, /* hook (for modeNew in {"w+", "a", "a+"}) fwrite((void *)ptr, (size_t)size, (size_t)nmemb, {fopen((const char *)pathname, modeNew), fdopen((int)fd, modeNew), freopen((const char *)pathname, modeNew, (FILE *)stream)}) */
}
} VirusAnalysisHook;
static const VirusAnalysisHook operator|(VirusAnalysisHook x,  VirusAnalysisHook s) {return static_cast<VirusAnalysisHook>(static_cast<unsigned>(x) | static_cast<unsigned>(s));}
static const VirusAnalysisHook operator&(VirusAnalysisHook x,  VirusAnalysisHook s) {return static_cast<VirusAnalysisHook>(static_cast<unsigned>(x) & static_cast<unsigned>(s));}
static VirusAnalysisHook globalVirusAnalysisHook = virusAnalysisHookDefault;

typedef enum VirusAnalysisResult : char {
    virusAnalysisAbort = static_cast<char>(false), /* do not launch */
    virusAnalysisPass = static_cast<char>(true), /* launch this (file passes) */
    virusAnalysisRequiresReview, /* submit to hosts to do analysis */
    virusAnalysisContinue /* continue to next tests */
} VirusAnalysisResult;

extern ResultList passList, abortList;
extern Cns analysisCns, virusFixCns;

/* @pre @code analysisCns.hasImplementation() && virusFixCns.hasImplementation() @endcode */
const bool virusAnalysisTests();
static const bool virusAnalysisTestsNoexcept() NOEXCEPT {return templateCatchAll(virusAnalysisTests, "virusAnalysisTests()");}
const bool virusAnalysisHookTests;
static const bool virusAnalysisHookTestsNoexcept() NOEXCEPT {return templateCatchAll(virusAnalysisHookTests, "virusAnalysisHookTests()");}

const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook);
static const VirusAnalysisHook virusAnalysisGetHook() {return virusAnalysisHook(virusAnalysisHookQuery);}

const VirusAnalysisResult hashAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);

/* To produce virus signatures:
 * use passlists (of files reviewed which pass),
 * plus abortlists (of files which failed), such lists as Virustotal has.
 * `produceAbortListSignatures()` is to produce the `abortList.signatures` list, with the smallest substrings unique to infected files; is slow, requires huge database of executables; just hosts should produce this.
 * For clients: Comodo has lists of virus signatures to check against at https://www.comodo.com/home/internet-security/updates/vdp/database.php
 * @pre @code passList.bytecodes.size() && abortList.bytecodes.size() && !listsIntersect(passList.bytecodes, abortList.bytecodes) @endcode
 * @post @code abortList.signatures.size() @endcode */
void produceAbortListSignatures(const ResultList &passList, ResultList &abortList);
 /* @pre @code abortList.signatures.size() @endcode */
const VirusAnalysisResult signatureAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);

/* @throw bad_alloc */
const std::vector<std::string> importedFunctionsList(const PortableExecutable &file);
extern std::vector<std::string> syscallPotentialDangers;
const VirusAnalysisResult staticAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);
const VirusAnalysisResult sandboxAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);
extern std::vector<std::string> stracePotentialDangers;
const VirusAnalysisResult straceOutputsAnalysis(const FilePath &straceOutput); /* TODO: regex */

/* @pre @code cns.hasImplementation() && pass.bytecodes.size() && abort.bytecodes.size() @endcode
 * @post @code cns.isInitialized() @endcode */
void produceAnalysisCns(const ResultList &pass, const ResultList &abort,
    const ResultList &unreviewed = ResultList(),
    Cns &cns = analysisCns
);
/* @pre @code cns.isInitialized() @endcode */
const float cnsAnalysisScore(const PortableExecutable &file, const ResultListHash &fileHash, const Cns &cns = analysisCns);
/* @pre @code cns.isInitialized() @endcode */
const VirusAnalysisResult cnsAnalysis_(const PortableExecutable &file, const ResultListHash &fileHash, const Cns &cns = analysisCns);
const VirusAnalysisResult cnsAnalysis(const PortableExecutable &file, const ResultListHash &fileHash);

extern std::map<ResultListHash, VirusAnalysisResult> hashAnalysisCaches, signatureAnalysisCaches, staticAnalysisCaches, cnsAnalysisCaches, sandboxAnalysisCaches; 

typedef const VirusAnalysisResult (*VirusAnalysisFun)(const PortableExecutable &file, const ResultListHash &fileHash);
extern std::vector<typeof(VirusAnalysisFun)> virusAnalyses;

const VirusAnalysisResult virusAnalysis(const PortableExecutable &file);
static const VirusAnalysisResult submitSampleToHosts(const PortableExecutable &file) {return virusAnalysisRequiresReview;} /* TODO */

/* @pre @code cns.hasImplementation() @endcode
 * @post @code cns.isInitialized() @encode */
void produceVirusFixCns(
    const ResultList &passOrNull, /* Expects `resultList->bytecodes[x] = NULL` if does not pass */
    const ResultList &abortOrNull, /* Expects `resultList->bytecodes[x] = NULL` if does pass */
    Cns &cns = virusFixCns
);

/* @pre @code cns.isInitialized() @endcode */
const std::string cnsVirusFix(const PortableExecutable &file, const Cns &cns = virusFixCns);

less cxx/VirusAnalysis.cxx

VirusAnalysisHook globalVirusAnalysisHook = virusAnalysisHookDefault;
ResultList passList, abortList;
Cns analysisCns, virusFixCns;
std::vector<std::string> syscallPotentialDangers = {
    "memopen", "fwrite", "socket", "GetProcAddress", "IsVmPresent"
};
std::vector<std::string> stracePotentialDangers = {"write(*)"};
std::map<ResultListHash, VirusAnalysisResult> hashAnalysisCaches, signatureAnalysisCaches, staticAnalysisCaches, cnsAnalysisCaches, sandboxAnalysisCaches;

std::vector<typeof(VirusAnalysisFun)> virusAnalyses = {hashAnalysis, signatureAnalysis, staticAnalysis, cnsAnalysis, sandboxAnalysis};

const bool virusAnalysisTests() {
    ResultList abortOrNull {
        .bytecodes {
            "infection",
            "infectedSW",
            "corruptedSW",
            ""
        }
    };
    ResultList passOrNull {
        .bytecodes {
            "",
            "SW",
            "SW",
            "newSW"
        }
    };
    resultListProduceHashes(passOrNull);
    resultListProduceHashes(abortOrNull);
    produceAbortListSignatures(passOrNull, abortOrNull);
    SUSUWU_NOTICE_DEBUGEXECUTE(resultListDumpTo(passOrNull, std::cout, true, true, false));
    SUSUWU_NOTICE_DEBUGEXECUTE((resultListDumpTo(/*.list = */abortOrNull, std::cout, false, false, false), std::cout << std::endl));
    assert(4 == passOrNull.bytecodes.size());
    assert(passOrNull.bytecodes.size() - 1 /* 2 instances of "SW", discount dup */ == passOrNull.hashes.size());
    assert(0 == passOrNull.signatures.size());
    assert(4 == abortOrNull.bytecodes.size());
    assert(abortOrNull.bytecodes.size() == abortOrNull.hashes.size());
    assert(abortOrNull.bytecodes.size() - 1 /* discount empty substr */ == abortOrNull.signatures.size());
    produceAnalysisCns(passOrNull, abortOrNull, ResultList(), analysisCns);
    produceVirusFixCns(passOrNull, abortOrNull, virusFixCns);
    if(0 < classSysArgc) {
        PortableExecutableBytecode executable(classSysArgs[0]);
        if(virusAnalysisAbort == virusAnalysis(executable)) {
            throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "{virusAnalysisAbort == virusAnalysis(args[0]);} /* With such false positives, shouldn't hook kernel modules */"));
        }
    }
    const bool originalRootStatus = hasRoot();
    setRoot(true);
    virusAnalysisHookTests();
    setRoot(originalRootStatus);
    return true;
}

const bool virusAnalysisHookTests() {
    const VirusAnalysisHook originalHookStatus = virusAnalysisGetHook();
    VirusAnalysisHook hookStatus = virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookExec);
    if(virusAnalysisHookExec != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookExec)` == " + std::to_string(hookStatus));
        return false;
    }
    hookStatus = virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookNewFile);
    if(virusAnalysisHookNewFile != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookNewFile)` == " + std::to_string(hookStatus));
        return false;
    }
    hookStatus = virusAnalysisHook(virusAnalysisHookClear);
    if(virusAnalysisHookDefault != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisHookClear)` == " + std::to_string(hookStatus));
        return false;
    }
    hookStatus = virusAnalysisHook(virusAnalysisHookExec | virusAnalysisHookNewFile);
    if((virusAnalysisHookExec | virusAnalysisHookNewFile) != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisExec | virusAnalysisHookNewFile)` == " + std::to_string(hookStatus));
        return false;
    }
    hookStatus = virusAnalysisHook(virusAnalysisHookClear | originalHookStatus);
    if(originalHookStatus != hookStatus) {
        throw std::runtime_error("`virusAnalysisHook(virusAnalysisHookClear | originalHookStatus)` == " + std::to_string(hookStatus));
        return false;
    }
    return true;
}
const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook virusAnalysisHookStatus) {
    const VirusAnalysisHook originalHookStatus = globalVirusAnalysisHook;
    if(virusAnalysisHookQuery == virusAnalysisHookStatus || originalHookStatus == virusAnalysisHookStatus) {
        return originalHookStatus;
    }
    if(virusAnalysisHookClear & virusAnalysisHookStatus) {
        /* TODO: undo OS-specific "hook"s/"callback"s */
        globalVirusAnalysisHook = virusAnalysisHookDefault;
    }
    if(virusAnalysisHookExec & virusAnalysisHookStatus) {
        /* callbackHook("exec*", */ [](const PortableExecutable &file) { /* TODO: OS-specific "hook"/"callback" for `exec()`/app-launches */
            switch(virusAnalysis(file)) {
            case virusAnalysisPass:
                return true; /* launch this */
            case virusAnalysisRequiresReview:
                submitSampleToHosts(file); /* manual review */
                    return false;
            default:
                return false; /* abort */
            }
        } /* ) */ ;
        globalVirusAnalysisHook = (globalVirusAnalysisHook | virusAnalysisHookExec);
    }
    if(virusAnalysisHookNewFile & virusAnalysisHookStatus) {
        /* callbackHook("fwrite", */ /* TODO: OS-specific "hook"/"callback" for new files/downloads */
        globalVirusAnalysisHook = (globalVirusAnalysisHook | virusAnalysisHookNewFile);
    }
    return virusAnalysisGetHook();
}

const VirusAnalysisResult virusAnalysis(const PortableExecutable &file) {
    const auto fileHash = sha2(file.bytecode);
    for(const auto &analysis : virusAnalyses) {
        switch(analysis(file, fileHash)) {
            case virusAnalysisPass:
                return virusAnalysisPass;
            case virusAnalysisRequiresReview:
                /*submitSampleToHosts(file);*/ /* TODO:? */
                return virusAnalysisRequiresReview;
            case virusAnalysisAbort:
                return virusAnalysisAbort;
            virusAnalysisContinue:
                continue;
        }
    }
    return virusAnalysisPass;
}

const VirusAnalysisResult hashAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    try {
        const auto result = hashAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        if(listHasValue(passList.hashes, fileHash)) {
            return hashAnalysisCaches[fileHash] = virusAnalysisPass;
        } else if(listHasValue(abortList.hashes, fileHash)) {
            return hashAnalysisCaches[fileHash] = virusAnalysisAbort;
        } else {
            return hashAnalysisCaches[fileHash] =  virusAnalysisContinue; /* continue to next tests */
        }
    }
}

const VirusAnalysisResult signatureAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    try {
        const auto result = signatureAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        if(listHasSignatureOfValue(abortList.signatures, file.bytecode)) {
            return signatureAnalysisCaches[fileHash] = virusAnalysisAbort;
        }
        return signatureAnalysisCaches[fileHash] = virusAnalysisContinue;
    }
}

void produceAbortListSignatures(const ResultList &passList, ResultList &abortList) {
    abortList.signatures.reserve(abortList.bytecodes.size());
    for(const auto &file : abortList.bytecodes) {
        auto tuple = listProduceSignature(passList.bytecodes, file);
        if(std::get<0>(tuple) < std::get<1>(tuple)) {
            abortList.signatures.push_back(ResultListSignature(std::get<0>(tuple), std::get<1>(tuple)));
        }
    } /* The most simple signature is a substring, but some analyses use regexes. */
}

const std::vector<std::string> importedFunctionsList(const PortableExecutable &file) {
    return {}; /* fixes crash, until importedFunctionsList is implemented/finished */
/* TODO: https://www.codeproject.com/Questions/338807/How-to-get-list-of-all-imported-functions-invoked shows how to analyse dynamic loads of functions (if do this, `syscallPotentialDangers[]` does not include `GetProcAddress()`.)
 */
}

const VirusAnalysisResult staticAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    try {
        const auto result = staticAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        auto syscallsUsed = importedFunctionsList(file);
        std::sort(syscallPotentialDangers.begin(), syscallPotentialDangers.end());
        std::sort(syscallsUsed.begin(), syscallsUsed.end());
        if(listsIntersect(syscallPotentialDangers, syscallsUsed)) {
            return staticAnalysisCaches[fileHash] = virusAnalysisRequiresReview;
        }
        return staticAnalysisCaches[fileHash] = virusAnalysisContinue;
    }
}

const VirusAnalysisResult sandboxAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    try {
        const auto result = sandboxAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        execvex("cp -r '/usr/home/sandbox/' '/usr/home/sandbox.bak'"); /* or produce FS snapshot */
        execvex("cp '" + file.path + "' '/usr/home/sandbox/'");
        execvex("chroot '/usr/home/sandbox/' \"strace basename '" + file.path + "'\" >> strace.outputs");
        execvex("mv/ '/usr/home/sandbox/strace.outputs' '/tmp/strace.outputs'");
        execvex("rm -r '/usr/home/sandbox/' && mv '/usr/home/sandbox.bak' '/usr/home/sandbox/'"); /* or restore FS snapshot */
        return sandboxAnalysisCaches[fileHash] = straceOutputsAnalysis("/tmp/strace.outputs");
    }
}
const VirusAnalysisResult straceOutputsAnalysis(const FilePath &straceOutput) {
        auto straceDump = std::ifstream(straceOutput);
        std::vector<std::string> straceOutputs /*= explodeToList(straceDump, "\n")*/;
        for(std::string straceOutput; std::getline(straceDump, straceOutput); ) {
            straceOutputs.push_back(straceOutput);
        }
        std::sort(stracePotentialDangers.begin(), stracePotentialDangers.end());
        std::sort(straceOutputs.begin(), straceOutputs.end());
        if(listsIntersect(stracePotentialDangers, straceOutputs)) { /* Todo: regex */
            return virusAnalysisRequiresReview;
        }
    return virusAnalysisContinue;
}

void produceAnalysisCns(const ResultList &pass, const ResultList &abort,const ResultList &unreviewed,Cns &cns) {
    std::vector<std::tuple<FileBytecode, float>> inputsToOutputs;
    const size_t maxPassSize = listMaxSize(pass.bytecodes);
    const size_t maxAbortSize = listMaxSize(abort.bytecodes);
    cns.setInputMode(cnsModeString);
    cns.setOutputMode(cnsModeFloat);
    cns.setInputNeurons(maxPassSize > maxAbortSize ? maxPassSize : maxAbortSize);
    cns.setOutputNeurons(1);
    cns.setLayersOfNeurons(6666);
    cns.setNeuronsPerLayer(26666);
    inputsToOutputs.reserve(pass.bytecodes.size());
    for(const auto &bytecodes : pass.bytecodes) {
        inputsToOutputs.push_back({bytecodes, 1.0});
    }
    cns.setupSynapses(inputsToOutputs);
    inputsToOutputs.clear();
    if(!unreviewed.bytecodes.empty()) {
        inputsToOutputs.reserve(unreviewed.bytecodes.size());
        for(const auto &bytecodes : unreviewed.bytecodes) {
            inputsToOutputs.push_back({bytecodes, 1 / 2});
        }
        cns.setupSynapses(inputsToOutputs);
        inputsToOutputs.clear();
    }
    inputsToOutputs.reserve(abort.bytecodes.size());
    for(const auto &bytecodes : abort.bytecodes) {
        inputsToOutputs.push_back({bytecodes, 0.0});
    }
    cns.setupSynapses(inputsToOutputs);
    inputsToOutputs.clear();
}
const float cnsAnalysisScore(const PortableExecutable &file, const Cns &cns) {
    return cns.processToFloat(file.bytecode);
}
const VirusAnalysisResult cnsAnalysis_(const PortableExecutable &file, const ResultListHash &fileHash, const Cns &cns) {
    try {
        const auto result = cnsAnalysisCaches.at(fileHash);
        return result;
    } catch (...) {
        return cnsAnalysisCaches[fileHash] = static_cast<bool>(round(cnsAnalysisScore(file, cns))) ? virusAnalysisContinue : virusAnalysisRequiresReview;
    }
}
const VirusAnalysisResult cnsAnalysis(const PortableExecutable &file, const ResultListHash &fileHash) {
    return cnsAnalysis_(file, fileHash);
}

void produceVirusFixCns(const ResultList &passOrNull, const ResultList &abortOrNull, Cns &cns) {
    std::vector<std::tuple<FileBytecode, FileBytecode>> inputsToOutputs;
    cns.setInputMode(cnsModeString);
    cns.setOutputMode(cnsModeString);
    cns.setInputNeurons(listMaxSize(passOrNull.bytecodes));
    cns.setOutputNeurons(listMaxSize(abortOrNull.bytecodes));
    cns.setLayersOfNeurons(6666);
    cns.setNeuronsPerLayer(26666);
    assert(passOrNull.bytecodes.size() == abortOrNull.bytecodes.size());
    inputsToOutputs.reserve(passOrNull.bytecodes.size());
    for(int x = 0; passOrNull.bytecodes.size() > x; ++x) {
        inputsToOutputs.push_back({abortOrNull.bytecodes[x], passOrNull.bytecodes[x]});
    }
    cns.setupSynapses(inputsToOutputs);
}

const FileBytecode cnsVirusFix(const PortableExecutable &file, const Cns &cns /* = virusFixCns */) {
    return cns.processToString(file.bytecode);
}

less cxx/main.cxx

namespace Susuwu {
void noExcept() NOEXCEPT;
NORETURN void noReturn();
void noExcept() NOEXCEPT {std::cout << std::flush;}
void noReturn() {exit(0);}
int testHarnesses() EXPECTS(true) ENSURES(true) {
    std::cout << "cxx/Macros.hxx: " << std::flush;
    ASSUME(true);
    noExcept();
    std::cout << "pass" << std::endl;
    std::cout << "execves(): " << std::flush;
    (EXIT_SUCCESS == execves({"/bin/echo", "pass"})) || std::cout << "error" << std::endl;
    std::cout << "execvex(): " << std::flush;
    (EXIT_SUCCESS == execvex("/bin/echo pass")) || std::cout << "error" << std::endl;
    std::cout << "virusAnalysisTestsNoexcept(): " << std::flush;
    if(virusAnalysisTestsNoexcept()) {
        std::cout << "pass" << std::endl;
    } else {
        std::cout << "error" << std::endl;
    }
    std::cout << "assistantCnsTestsNoexcept(): " << std::flush;
    if(assistantCnsTestsNoexcept()) {
        std::cout << "pass" << std::endl;
    } else {
        std::cout << "error" << std::endl;
    }
    noReturn();
}
}; /* namespace Susuwu */
int main(int argc, const char **args) {
    const bool classSysInitSuccess = Susuwu::classSysInit(argc, args);
    assert(classSysInitSuccess);
    return Susuwu::testHarnesses();
}

For comparison; produceVirusFixCns is close to assistants
cxx/AssistantCns.hxx
cxx/AssistantCns.cxx
/* snipped due to 30000 character limit */

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文