Skip to content

Commit

Permalink
+classSysKernelSetHook(): for ?virusAnalysisHook
Browse files Browse the repository at this point in the history
?`cxx/ClassSys.hxx`:
	+`classSysKernelSetHook()`: , usage is `classSysSetHook(func, callback);` effect is `%s/function(...)/classSysKernelCallback(...)/` /* `virusAnalysisHook()` will use this */
	+`classSysKernelCallback<Func, Callback>` /* returns `(callback(...) ? function(...) : decltype(function(...))())` */

?`cxx/VirusAnalysis.cxx`:
	-`lambdaScan`, +`virusAnalysisImpl`: C++11 does not allow to use lambda in new lambdas.
	+`lambdaScanExecv`, `+lambdaScanCreateProcessA`: operating system specific lambdas.
	?`virusAnalysisHook`: use `classSysKernelSetHook(*, lambdaScan*)` to scan files which you execute.

Is progress to issues #1, #8 (both about `VirusAnalysis.cxx`).
Is followup to: commit a8c9f9b ("?virusAnalysisHook `s/[] (/auto lambdaScan = [] (/`)").

?`posts/VirusAnalysis.md`: include all this.
  • Loading branch information
SwuduSusuwu committed Nov 24, 2024
1 parent a8c9f9b commit f69c1ee
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 32 deletions.
24 changes: 22 additions & 2 deletions cxx/ClassSys.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#ifndef INCLUDES_cxx_ClassSys_hxx
#define INCLUDES_cxx_ClassSys_hxx
#include "ClassPortableExecutable.hxx" /* FilePath */
#include "Macros.hxx" /* IF_SUSUWU_CPLUSPLUS, SUSUWU_ERROR SUSUWU_NOEXCEPT SUSUWU_POSIX */
#include "Macros.hxx" /* IF_SUSUWU_CPLUSPLUS SUSUWU_ERROR SUSUWU_NOEXCEPT SUSUWU_POSIX SUSUWU_WARNING */
#include <cassert> /* assert */
#include <chrono> /* std::chrono */
#include IF_SUSUWU_CPLUSPLUS(<cstdio>, <stdio.h>) /* FILE fopen */
Expand Down Expand Up @@ -48,9 +48,29 @@ static const int execvex(const std::string &toSh) {return execves({"/bin/sh", "-
/* #if SUSUWU_POSIX, `return (0 == geteuid());` #elif SUSUWU_WIN32 `return IsUserAnAdmin();` #endif `return false;` */
const bool classSysHasRoot();
/* #if SUSUWU_POSIX, `root ? (seteuid(0) : (seteuid(getuid() || getenv("SUDO_UID")), setuid(geteuid)); return classSysHasRoot();` #endif
* Usage: classSysSetRoot(true); functionsWhichRequireRoot; classSysSetRoot(false); */
* Usage: classSysSetRoot(true); classSysKernelSetHook(...); classSysSetRoot(false); */
const bool classSysSetRoot(bool root); /* root ? (seteuid(0) : (seteuid(getuid() || atoi(getenv("SUDO_UID"))), setuid(geteuid)); return classSysHasRoot(); */

/* Effect: `(callback(args...) ? func(args...) : decltype(func(args...))())` */
template<typename func, typename callback, typename... Args>
auto classSysKernelCallback(Args... args) -> decltype(func(args...)) {
const auto ret = callback(args...);
return static_cast<bool>(ret) ? func(args...) : ret;
}
/* Usage: `classSysKernelSetHook(download, classSysKernelCallback<download, virusAnalysisDownloadCallback>);`
* Effect: `:%s/func(/classSysKernelCallback<func, callback>(/`
* @pre @code classSysHasRoot() @endof */
template<typename Func, typename Lambda>
const bool classSysKernelSetHook(Func func, Lambda callback) {
if(classSysHasRoot()) {
SUSUWU_WARNING("classSysKernelSetHook: TODO");
// return true; /* TODO: hook `func` */
} else {
SUSUWU_ERROR("classSysKernelSetHook: if(!classSysHasRoot()) {/* kernel hook impossible to use */}");
}
return false;
}

/* Filesystems */
/* Usage: for Linux (or Windows,) if you don't trust `argv[0]`, replace it with `classSysGetOwnPath()`.
* Error values: `return FilePath();` */
Expand Down
45 changes: 31 additions & 14 deletions cxx/VirusAnalysis.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#include "ClassPortableExecutable.hxx" /* PortableExecutable */
#include "ClassResultList.hxx" /* size_t listMaxSize listHasValue listProduceSignature listFindSignatureOfValue ResultList resultListDumpTo resultListProduceHashes */
#include "ClassSha2.hxx" /* classSha2 */
#include "ClassSys.hxx" /* classSysHasRoot classSysHexStr classSysSetRoot execvex */
#include "Macros.hxx" /* ERROR NOTICE SUSUWU_ERRSTR SUSUWU_NOTICE SUSUWU_NOTICE_EXECUTEVERBOSE SUSUWU_SH_VERBOSE */
#include "ClassSys.hxx" /* classSysGetOwnPath classSysHasRoot classSysHexStr classSysSetRoot classSysKernelSetHook execvex */
#include "Macros.hxx" /* ERROR NOTICE SUSUWU_ERROR SUSUWU_ERRSTR SUSUWU_NOTICE SUSUWU_NOTICE_EXECUTEVERBOSE SUSUWU_SH_VERBOSE */
#include "VirusAnalysis.hxx" /* passList abortList *AnalyisCaches */
#include <algorithm> /* std::sort */
#include <cassert> /* assert */
Expand All @@ -20,6 +20,11 @@
#include <stdexcept> /* std::runtime_error */
#include <string> /* std::string std::to_string */
#include <tuple> /* std::tuple std::get */
#ifdef SUSUWU_POSIX
#include <unistd.h> /* execv */
#elif defined(SUSUWU_WIN32)
#include <processthreadsapi.h> /* CreateProcessA BOOL DWORD LPCSTR LPPROCESS_INFORMATION LPSECURITY_ATTRIBUTES LPSTARTUPINFOA LPSTR LPVOID */
#endif /* elif DEFINED(SUSUWU_WIN32) */
#include <vector> /* std::vector */
/* (Work-in-progress) virus analysis: uses hashes, signatures, static analysis, sandboxes, plus artificial CNS (central nervous systems) */
namespace Susuwu {
Expand Down Expand Up @@ -127,6 +132,16 @@ const bool virusAnalysisHookTests() {
}
return true;
}
const bool virusAnalysisImpl(const PortableExecutable &file) {
switch(virusAnalysis(file)) {
case virusAnalysisPass:
return true; /* launch this */
case virusAnalysisRequiresReview:
return (virusAnalysisPass == virusAnalysisManualReview(file));
default:
return false; /* abort */
}
};
const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook hookStatus) { /* Ignore depth-of-1 recursion: NOLINT(misc-no-recursion) */
const VirusAnalysisHook originalHookStatus = globalVirusAnalysisHook;
if(virusAnalysisHookQuery == hookStatus || originalHookStatus == hookStatus) {
Expand All @@ -136,22 +151,24 @@ const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook hookStatus) { /* Ign
/* TODO: undo OS-specific "hook"s/"callback"s */
globalVirusAnalysisHook = virusAnalysisHookDefault;
}
auto lambdaScan = [](const PortableExecutable &file) {
switch(virusAnalysis(file)) {
case virusAnalysisPass:
return true; /* launch this */
case virusAnalysisRequiresReview:
return (virusAnalysisPass == virusAnalysisManualReview(file));
default:
return false; /* abort */
}
};
if(virusAnalysisHookExec & hookStatus) {
/* callbackHook("exec*", lambdaScan); */ /* TODO: OS-specific "hook"/"callback" for `exec()`/app-launches */
#ifdef SUSUWU_POSIX
auto lambdaScanExecv = [](const char *pathname, char *const argv[]) {
return static_cast<int>(virusAnalysisImpl(PortableExecutable(pathname)));
};
classSysKernelSetHook(execv, lambdaScanExecv);
#elif defined(SUSUWU_WIN32) /* def SUSUWU_POSIX else */
auto lambdaScanCreateProcessA = [](LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) {
return virusAnalysisImpl(PortableExecutable(lpApplicationName));
};
classSysKernelSetHook(CreateProcessA, lambdaScanCreateProcessA);
#else /* defined(SUSUWU_WIN32) else */
SUSUWU_ERROR("virusAnalysisHook(virusAnalysisHookExec) { if(!SUSUWU_POSIX && !SUSUWU_WIN32) { /* TODO: you can contribute or post to https://github.com/SwuduSusuwu/SubStack/issues/new */ } }");
#endif /* defined(SUSUWU_WIN32) else */
globalVirusAnalysisHook = (globalVirusAnalysisHook | virusAnalysisHookExec);
}
if(virusAnalysisHookNewFile & hookStatus) {
/* callbackHook("fwrite", lambdaScan); */ /* TODO: OS-specific "hook"/"callback" for new files/downloads */
// classSysKernelSetHook(fwrite, lambdaScanFwrite); /* TODO: OS-specific "hook"/"callback" for new files/downloads */
globalVirusAnalysisHook = (globalVirusAnalysisHook | virusAnalysisHookNewFile);
}
return virusAnalysisGetHook();
Expand Down
66 changes: 50 additions & 16 deletions posts/VirusAnalysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,29 @@ static const int execvex(const std::string &toSh) {return execves({"/bin/sh", "-
/* #if SUSUWU_POSIX, `return (0 == geteuid());` #elif SUSUWU_WIN32 `return IsUserAnAdmin();` #endif `return false;` */
const bool classSysHasRoot();
/* #if SUSUWU_POSIX, `root ? (seteuid(0) : (seteuid(getuid() || getenv("SUDO_UID")), setuid(geteuid)); return classSysHasRoot();` #endif
* Usage: classSysSetRoot(true); functionsWhichRequireRoot; classSysSetRoot(false); */
* Usage: classSysSetRoot(true); classSysKernelSetHook(...); classSysSetRoot(false); */
const bool classSysSetRoot(bool root); /* root ? (seteuid(0) : (seteuid(getuid() || atoi(getenv("SUDO_UID"))), setuid(geteuid)); return classSysHasRoot(); */
/* Effect: `(callback(args...) ? func(args...) : decltype(func(args...))())` */
template<typename func, typename callback, typename... Args>
auto classSysKernelCallback(Args... args) -> decltype(func(args...)) {
const auto ret = callback(args...);
return static_cast<bool>(ret) ? func(args...) : ret;
}
/* Usage: `classSysKernelSetHook(download, classSysKernelCallback<download, virusAnalysisDownloadCallback>);`
* Effect: `:%s/func(/classSysKernelCallback<func, callback>(/`
* @pre @code classSysHasRoot() @endof */
template<typename Func, typename Lambda>
const bool classSysKernelSetHook(Func func, Lambda callback) {
if(classSysHasRoot()) {
SUSUWU_WARNING("classSysKernelSetHook: TODO");
// return true; /* TODO: hook `func` */
} else {
SUSUWU_ERROR("classSysKernelSetHook: if(!classSysHasRoot()) {/* kernel hook impossible to use */}");
}
return false;
}
/* Filesystems */
/* Usage: for Linux (or Windows,) if you don't trust `argv[0]`, replace it with `classSysGetOwnPath()`.
* Error values: `return FilePath();` */
Expand Down Expand Up @@ -454,9 +474,9 @@ inline Os &classSysColoredParamOs(Os &os, const List &argvS, const bool parenthe
}
return os;
}
template<class List>
inline const typename List::value_type classSysColoredParamStr(const List &argvS, const bool parenthesis/* {...} */ = true) {
typename List::value_type str = (parenthesis ? "{" : "");
template<template<class> class List, class Str>
inline const Str classSysColoredParamStr(const List<Str> &argvS, const bool parenthesis/* {...} */ = true) {
Str str = (parenthesis ? "{" : "");
for(const auto &it: argvS) {
if(&it != &*argvS.cbegin()) {
str += ", ";
Expand Down Expand Up @@ -1331,6 +1351,7 @@ const bool virusAnalysisTests() {
return true;
}
/* `clang-tidy` suppress: NOLINTBEGIN(readability-implicit-bool-conversion) */
const bool virusAnalysisHookTests() {
const VirusAnalysisHook originalHookStatus = virusAnalysisGetHook();
VirusAnalysisHook hookStatus = virusAnalysisHook(virusAnalysisHookClear | virusAnalysisHookExec);
Expand Down Expand Up @@ -1360,6 +1381,16 @@ const bool virusAnalysisHookTests() {
}
return true;
}
const bool virusAnalysisImpl(const PortableExecutable &file) {
switch(virusAnalysis(file)) {
case virusAnalysisPass:
return true; /* launch this */
case virusAnalysisRequiresReview:
return (virusAnalysisPass == virusAnalysisManualReview(file));
default:
return false; /* abort */
}
};
const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook hookStatus) { /* Ignore depth-of-1 recursion: NOLINT(misc-no-recursion) */
const VirusAnalysisHook originalHookStatus = globalVirusAnalysisHook;
if(virusAnalysisHookQuery == hookStatus || originalHookStatus == hookStatus) {
Expand All @@ -1369,26 +1400,29 @@ const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook hookStatus) { /* Ign
/* TODO: undo OS-specific "hook"s/"callback"s */
globalVirusAnalysisHook = virusAnalysisHookDefault;
}
auto lambdaScan = [](const PortableExecutable &file) {
switch(virusAnalysis(file)) {
case virusAnalysisPass:
return true; /* launch this */
case virusAnalysisRequiresReview:
return (virusAnalysisPass == virusAnalysisManualReview(file));
default:
return false; /* abort */
}
};
if(virusAnalysisHookExec & hookStatus) {
/* callbackHook("exec*", lambdaScan); */ /* TODO: OS-specific "hook"/"callback" for `exec()`/app-launches */
#ifdef SUSUWU_POSIX
auto lambdaScanExecv = [](const char *pathname, char *const argv[]) {
return static_cast<int>(virusAnalysisImpl(PortableExecutable(pathname)));
};
classSysKernelSetHook(execv, lambdaScanExecv);
#elif defined(SUSUWU_WIN32) /* def SUSUWU_POSIX else */
auto lambdaScanCreateProcessA = [](LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) {
return virusAnalysisImpl(PortableExecutable(lpApplicationName));
};
classSysKernelSetHook(CreateProcessA, lambdaScanCreateProcessA);
#else /* defined(SUSUWU_WIN32) else */
SUSUWU_ERROR("virusAnalysisHook(virusAnalysisHookExec) { if(!SUSUWU_POSIX && !SUSUWU_WIN32) { /* TODO: you can contribute or post to https://github.com/SwuduSusuwu/SubStack/issues/new */ } }");
#endif /* defined(SUSUWU_WIN32) else */
globalVirusAnalysisHook = (globalVirusAnalysisHook | virusAnalysisHookExec);
}
if(virusAnalysisHookNewFile & hookStatus) {
/* callbackHook("fwrite", lambdaScan); */ /* TODO: OS-specific "hook"/"callback" for new files/downloads */
// classSysKernelSetHook(fwrite, lambdaScanFwrite); /* TODO: OS-specific "hook"/"callback" for new files/downloads */
globalVirusAnalysisHook = (globalVirusAnalysisHook | virusAnalysisHookNewFile);
}
return virusAnalysisGetHook();
}
/* `clang-tidy` on: NOLINTEND(readability-implicit-bool-conversion) */
const VirusAnalysisResult virusAnalysis(const PortableExecutable &file) {
const auto fileHash = classSha2(file.bytecode);
Expand Down

0 comments on commit f69c1ee

Please sign in to comment.