A Pluggable Authentication Module (PAM) which allows the establishment of alternate passwords that can be used to perform actions to clear sensitive data, notify IT/Security staff, close off sensitive network connections, etc if a user is coerced into giving a threat actor a password.

Overview

Intro

The PAM Duress is a module designed to allow users to generate 'duress' passwords that when used in place of their normal password will execute abritrary scripts.

This functionality could be used to allow someone pressed to give a password under coersion to provide a password that grants access but in the background runs scripts to clean up sensitive data, close connections to other networks to limit lateral movement, and/or to send off a notifcation or alert (potentially one with detailed information like location, visible wifi hotspots, a picture from the camera, a link to a stream from the microphone, etc). You could even spawn a process to remove the pam_duress module so the threat actor won't be able to see if the duress module was available.

This is transparent to the person coersing the password from the user as the duress password will grant authentication and drop to the user's shell.

Duress scripts can be generated on an individual user basis or generated globally. Users can also re-use global duress passwords to sign their own duress scripts (rare instance where this could actually be useful from a security perspective).

Contributions to this project are more than welcome; refer to our guidance on making contributions here.

Requirements

# Ubuntu/Debian dependencies
sudo apt-get install build-essential libpam0g-dev libssl-dev

Build

make
sudo make install
make clean
# make uninstall

Configuration

Configuration of the duress module is split into two different configuration directories. After installation, you'll need to manually create both of them.

mkdir -p ~/.duress # Local duress scripts/binaries.
mkdir -p /etc/duress.d  # Global Duress scripts/binaries.

After creating the directories you can create scripts, compile binaries, etc and put them in these directories. To assign a password to execute a particular script you use the duress_sign to create a combination password hash and integrity hash for the script.

$> duress_sign ~/.duress/delete_workspace.sh
Password: 
Confirm: 
Reading /home/user/.duress/delete_workspace.sh, 33...
Done
6B8B621EFB8050B83AAC734D56BF9165DC55D709CBAD530C6241E8A352587B3F
$> chmod -R 500 ~/.duress
$> ls -al ~/.duress/
drwxr-xr-x 2 user user 4096 Aug 20 15:15 .
drwxr-xr-x 8 user user 4096 Aug 20 15:11 ..
-r-x------ 1 user user   33 Aug 20 15:11 delete_workspace.sh
-r-x------ 1 user user   32 Aug 20 21:49 delete_workspace.sh.sha256

NOTE: Scripts will only execute with permission masks of 500, 540, 550, 700 or 750

NOTE: User generated duress scripts are only run when they attempt to log in AND use a duress password that one of their scripts is signed with. If user Jill signs their scripts with the same password as a global script, when they use it the global scripts will run, followed by Jill's duress scripts, but Bob, Jane, or Dan's scripts will not be run even if they also re-used the same duress scripts.

PAM Configuration

Modify /etc/pam.d/common-auth from the following defaults:

auth    [success=1 default=ignore]      pam_unix.so

auth    requisite                       pam_deny.so

To the below:

# Example /etc/pam.d/common-auth
auth    [success=2 default=ignore]      pam_unix.so
auth    [success=1 default=ignore]      pam_duress.o

auth    requisite                       pam_deny.so

Order of Operations Normal Password

  • User enters their standard username and password.
  • pam_unix.o confirms them and returns PAM_SUCESS and skips 2 past pam_deny.o.

Order of Operations Duress Password

  • The pam_unix.o module first checks standard username and password, but since the duress password is not the users actuall password it fails resulting in a default behavior of 'ignore' per the configuration.
  • PAM then applies the username/password to pam_duress.o which:
    • Enumerates files in /etc/duress.d/
    • Checks for files that have matching .sha256 extensions
    • Hashes the provided password salted with the sha256 hash of the file and compares it with the one stored in the .sha256 extension file
    • If the hashes match, the script is executed via:
      • export PAMUSER=[USERNAME]; /bin/sh [FILE]
      • NOTE: PAMUSER is set so global duress scripts can specify the account flagging durress.
    • Process is repeated for all files in ~/.duress/ for the user attempting to log in.
    • Finally if ANY script is run, PAM_SUCCESS is return. Otherwise PAM_IGNORE is returned.
  • If PAM_SUCESS is returned PAM will skip 1 and move past pam_deny.o to continue the pam module processes, eventually dropping to an authenticated shell. Otherwise the default 'ignore' behavior is honored moving to pam_deny.o, resulting in a failed authentication.

Simple Flow Diagram

Testing

It is easy to do a quick test to ensure the duress module is working properly.

$> mkdir -p ~/.duress
$> echo 'echo "Hello World"' > ~/.duress/hello.sh
$> duress_sign ~/.duress/hello.sh
Password: # Enter a duress password that is NOT your actual password.
Confirm: 
$> chmod 500 ~/.duress/hello.sh
$> chmod 400 ~/.duress/hello.sh.sha256
$> sudo pam_test $USER
Credentials accepted.
Password: # Enter the password you signed the hello.sh script with.
Hello World # This output is from the duress script...
Account is valid. # ...and we still got a valid authentication.
Authenticated
$> sudo pam_test $USER
Credentials accepted.
Password: # Now enter your actual password.
Account is valid. # Note, Hello World doesn't print.
Authenticated

Exmample Implementations

Issues
  • Privilege escalation vulnerability.

    Privilege escalation vulnerability.

    The initial implementation does not run user scripts as the target user; nor checks to see if the script being run is owned by the user; only if it's readable and executable by the "owner". Then all scripts are run as root, even the local ones. This could allow and attacker to use a non-privileged account to execute root level commands if the PAM Duress module is employed.

    Repro steps: image

    opened by nuvious 5
  • [FR] macOS support?

    [FR] macOS support?

    null

    opened by NightMachinary 4
  • Typo

    Typo "durress" in README.me and Pushover.md

    Typo "durress" in README.me and Pushover.md, line 90 of README.md and line 24 of Pushover.md

    opened by idi-moe 1
  • Execute commands directly using execv

    Execute commands directly using execv

    There is no reason to start an intermediate shell.

    opened by juergenhoetzel 1
  • Add macOS support

    Add macOS support

    Fixes #5

    As noted there, there is a bug where you can get a SIGSEGV when using this with sudo and hitting Ctrl-C. I don't know if this is macOS specific.

    Needs documentation but basically add this to some /etc/pam.d file.

    # sudo: auth account password session
    auth       sufficient     pam_smartcard.so
    auth       required       pam_opendirectory.so
    # add this line here
    auth       optional       pam_duress.so
    account    required       pam_permit.so
    password   required       pam_deny.so
    session    required       pam_permit.so
    

    The installer will copy the PAM module to /usr/local/lib/pam because /usr/lib/pam is not writable even with sudo with SIP enabled. I think that's what's happening anyway.

    Includes a couple of incidental changes which I think are appropriate anyway:

    • Changes the binary installation path to /usr/local/bin
    • Various makefile improvements
    • Renames pam_duress.o to pam_duress.so
    • A format warning zapped
    opened by cormacrelf 1
  • Fix memory if the hash is incorrect.

    Fix memory if the hash is incorrect.

    null

    opened by juergenhoetzel 1
  • Avoid casting malloc to char* explicitly

    Avoid casting malloc to char* explicitly

    General comment on this codebase as a whole as requested.

    In many instances this code uses the construct

    char * foo = (char *) malloc(x); 
    

    In this case the cast is not required as void* is implicitly promotable, and casting explicitly can create some subtle bugs if done wrongly. Instead the code should probably remove the cast such as:

    char * foo = malloc(x); 
    
    opened by Vality 1
  • Potential code injection vulnerability submitted via hacker news user 'wowaname'

    Potential code injection vulnerability submitted via hacker news user 'wowaname'

    Below is the full text of the email sent with the patch. Part of the implementation is already in the PR #12. Remainder of the fix is to use setuid/setgid/setenv as apposed to using system() which potentially provides a code-injection avenue.

    (Untested) attempt to fix patch https://github.com/nuvious/pam-duress/pull/2 and remove avenues for improper shell quoting and unexpected code injection.

    Implement our own analogue to system() which sets environ for PAMUSER and drops privs without parsing any of the user-modifiable values, guarding against unsafe input. As a side effect, this provides granular error handling for failed setenv, setuid, or setgid as opposed to overloading one system() call for it.

    ---
     CHANGELOG.md  |  4 +++-
     src/duress.c  | 43 +++++++++--------------------------
     src/util.c    | 62 +++++++++++++++++++++++++++++++++++++++++++++------
     src/version.h |  4 ++--
     4 files changed, 71 insertions(+), 42 deletions(-)
    
    diff --git a/CHANGELOG.md b/CHANGELOG.md index 88bed64..b68edc9 100644
    --- a/CHANGELOG.md
    +++ b/CHANGELOG.md
    @@ -2,4 +2,6 @@
      - 1.0.0
        - Initial commit of prototype tested on Debian 10.
      - 1.0.1
    -   - Fixed some potential memory leaks, linted, and adjusted documentation.
    \ No newline at end of file
    +   - Fixed some potential memory leaks, linted, and adjusted documentation.
    + - 1.1.0
    +   - Fixed privilege escalation vulnerability that could allow an unprivileged user to run commands as root.
    \ No newline at end of file
    diff --git a/src/duress.c b/src/duress.c index 3252922..ca0b4b5 100644
    --- a/src/duress.c
    +++ b/src/duress.c
    @@ -192,22 +192,6 @@ int is_valid_duress_file(const char *filepath, const char *pam_pass)  #endif //DEBUG
           unsigned char *duress_hash = sha_256_sum(pam_pass, strlen(pam_pass), file_bytes, st.st_size);
     
    -#ifdef DEBUG
    -      syslog(LOG_INFO, "Loaded Hash: ");
    -      for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    -      {
    -            syslog(LOG_INFO, "%02X", hash[i]);
    -      }
    -      syslog(LOG_INFO, "\n");
    -      // Output the hash
    -      syslog(LOG_INFO, "Computed Hash: ");
    -      for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    -      {
    -            syslog(LOG_INFO, "%02X", duress_hash[i]);
    -      }
    -      syslog(LOG_INFO, "\n");
    -#endif //DEBUG
    -
           int result = 1;
           if (memcmp(hash, duress_hash, SHA256_DIGEST_LENGTH))
           {
    @@ -224,7 +208,7 @@ int is_valid_duress_file(const char *filepath, const char *pam_pass)
           return result;
     }
     
    -int process_dir(const char *directory, const char *pam_user, const char *pam_pass)
    +int process_dir(const char *directory, const char *pam_user, const char 
    +*pam_pass, const char* run_as_user)
     {
           int ret = 0;
           struct dirent *de;
    @@ -249,20 +233,15 @@ int process_dir(const char *directory, const char *pam_user, const char *pam_pas
                 if (is_valid_duress_file(fpath, pam_pass))
                 {
                       syslog(LOG_INFO, "File is valid.\n");
    -                  char *cmd = (char *) malloc(strlen(pam_user) + strlen(SHELL_CMD) + strlen(fpath) + 21);
    -                  if (sprintf(cmd, "export PAMUSER=%s; %s %s", pam_user, SHELL_CMD, fpath) < 0)
    -                  {
    -                        syslog(LOG_ERR, "Failed to format command. %s %s\n", SHELL_CMD, fpath);
    -                  }
    -                  else
    -                  {
     #ifdef DEBUG
    -                        syslog(LOG_INFO, "Running command %s\n", cmd);
    -#endif //DEBUG
    -                        system(cmd);
    -                        ret = 1;
    -                  }
    +                  char *cmd = (char *) malloc(
    +                        strlen(pam_user) * 2 +
    +                        strlen(SHELL_CMD) +
    +                        strlen(fpath) + 29);
    +                  syslog(LOG_INFO, "Running command %s\n", cmd);
                       free(cmd);
    +#endif //DEBUG
    +                  ret = run_shell_as(pam_user, run_as_user, fpath);
                 }
                 free(fpath);
           }
    @@ -273,8 +252,8 @@ int process_dir(const char *directory, const char *pam_user, const char *pam_pas
     
     int execute_duress_scripts(const char *pam_user, const char *pam_pass)  {
    -      int global_duress_run = process_dir(GLOBAL_CONFIG_DIR, pam_user, pam_pass);
    -      int local_duress_run = process_dir(get_local_config_dir(pam_user), pam_user, pam_pass);
    +      int global_duress_run = process_dir(GLOBAL_CONFIG_DIR, pam_user, pam_pass, "root");
    +      int local_duress_run = 
    + process_dir(get_local_config_dir(pam_user), pam_user, pam_pass, 
    + pam_user);
     
           if (global_duress_run || local_duress_run)
                 return PAM_SUCCESS;
    @@ -309,4 +288,4 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)  int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)  {
           return (PAM_SUCCESS);
    -}
    \ No newline at end of file
    +}
    diff --git a/src/util.c b/src/util.c
    index cdc1738..22907cc 100644
    --- a/src/util.c
    +++ b/src/util.c
    @@ -91,16 +91,64 @@ char *get_local_config_dir(const char *user_name)
         memcpy(config_dir + strlen(home_dir), LOCAL_CONFIG_DIR_SUFFIX, strlen(LOCAL_CONFIG_DIR_SUFFIX));
         config_dir[final_path_len - 1] = 0;
     
    -    // Output the hash
    -    for (size_t i = 0; i <= strlen(config_dir); i++)
    -    {
    -        syslog(LOG_INFO, "%02X", config_dir[i]);
    -    }
    -    syslog(LOG_INFO, "\n");
    -
         return config_dir;
     }
     
    +pid_t run_shell_as(const char *pam_user, const char *run_as_user, const 
    +char *script) {
    +    pid_t pid = fork();
    +    switch (pid) {
    +        case 0: {
    +            char* const argv[] = { SHELL, "-c", script, NULL };
    +            struct passwd *run_as_pw = getpwnam(run_as_user);
    +
    +            if (setenv("PAMUSER", pam_user, 1)) { #ifdef DEBUG
    +                syslog(LOG_ERR, "Could not set environment for PAMUSER 
    +to %s, %d.\n", pam_user, errno); #endif //DEBUG
    +                goto child_failed;
    +            }
    +
    +            if (!run_as_pw) {
    +#ifdef DEBUG
    +                syslog(LOG_ERR, "Could not getpwnam %s, %d.\n", 
    +run_as_user, errno); #endif //DEBUG
    +                goto child_failed;
    +            }
    +
    +            if (setuid(run_as_pw->pw_uid)) { #ifdef DEBUG
    +                syslog(LOG_ERR, "Could not setuid, %d.\n", errno); 
    +#endif //DEBUG
    +                goto child_failed;
    +            }
    +            if (setgid(run_as_pw->pw_gid)) { #ifdef DEBUG
    +                syslog(LOG_ERR, "Could not setgid, %d.\n", errno); 
    +#endif //DEBUG
    +                goto child_failed;
    +            }
    +
    +            execv(SHELL_CMD, argv);
    +
    +child_failed:
    +#ifdef DEBUG
    +            syslog(LOG_ERR, "Could not run script %s, %d.\n", script, 
    +errno); #endif //DEBUG
    +            _exit(1);
    +            break;
    +        }
    +        case -1:
    +#ifdef DEBUG
    +            syslog(LOG_ERR, "Could not fork for script %s, %d\n", 
    +script, errno); #endif //DEBUG
    +            break;
    +        default:
    +            break;
    +    }
    +    return pid;
    +}
    +
     unsigned char *sha_256_sum(const char *payload, size_t payload_size, const char *salt, size_t salt_size)  {
         unsigned char salt_hash[SHA256_DIGEST_LENGTH]; diff --git a/src/version.h b/src/version.h index 689e2fc..6a6e0df 100644
    --- a/src/version.h
    +++ b/src/version.h
    @@ -2,7 +2,7 @@
     #define SOURCE_VERSION_H
     
     #define VERS_MAJOR 1
    -#define VERS_MINOR 0
    -#define VERS_REVISION 1
    +#define VERS_MINOR 1
    +#define VERS_REVISION 0
     
     #endif
    \ No newline at end of file
    --
    2.31.1
    
    opened by nuvious 1
  • The contribution guidelines are ambiguous on the correct license for contributions.

    The contribution guidelines are ambiguous on the correct license for contributions.

    Contributing.md states:

    Any contributions you make will be under the MIT Software License In short, when you submit code changes, your submissions are understood to be under the same LGPL v3 that covers the project.

    This mentions two different licenses. One of them should be changed to match the other.

    opened by Vality 1
  • Issue 10  & 11 Fixes

    Issue 10 & 11 Fixes

    Fixed issues 10 and 11 while making a demo video of the pushover example. During the making I found a bug in the implementation introduced by the fix for issue #3 resulting in scripts not running when the root account login is disabled.

    Video demo also linked showing off the pushover implementation.

    opened by nuvious 0
  • not work on Linux Mint 20.2

    not work on Linux Mint 20.2

    When trying to enter a "password under duress", we return to the password entry window. If you enter a regular password, authentication is normal.

    In the same time:

    sudo pam_test $ USER
    Credentials accepted.
    Password:
    Account is valid.
    Authenticated
    

    Configuration /etc/pam.d/common-auth

    auth    [success=2 default=ignore]      pam_unix.so nullok
    auth    [success=1 default=ignore]      pam_duress.so nullok
    auth    requisite                       pam_deny.so
    auth    required                        pam_permit.so
    auth    optional        pam_ecryptfs.so unwrap
    auth    optional                        pam_cap.so
    

    `

    opened by bug0000 0
  • /etc/duress.d scripts should run after ~/.duress scripts

    /etc/duress.d scripts should run after ~/.duress scripts

    /etc/duress.d scripts should be run after ~/.duress script to allow for a script to be implemented that removes pam-duress itself as a cleanup action. In the current implementation one would have to write a delayed-action script to remove pam-duress system-wide which if misconfigured may allow an attacker to see the modules presence after the attacker has dropped to a user shell.

    opened by nuvious 0
  • Feature request: Protect the duress script itself

    Feature request: Protect the duress script itself

    Hi there,

    I think there are chances that a duress password could be the utmost simple one, which means it could be a dictionary word or easily being brute force and guessed it out. An adversary could also use PII or related information from the victim, to potentially guess what is the password(either the correct one or the duress code).

    SHA256 is great, and it does the job on checksum, but not when it comes to the case that we should also protect the duress script itself.

    I suggest introducing an option to add cryptographically signed duress script, ideally would be PGP signed, on top of the sha256 hashed script. So that the user can always know if the file has been tampered with, and failover to the sha256 hashed script if the validation failed.

    Regards, Ivan

    opened by lifehome 4
  • Make ~/.duress directory a toggleable feature.

    Make ~/.duress directory a toggleable feature.

    Some admins may not trust their users to create duress scripts and want full control to only have the ones in /etc/duress.d run when duress password is used. Modify the module such that it reads in a configuration file /etc/duress.conf to see if the administrator wants to enable ~/.duress for users and create a group that controls which users have their ~/.duress files parsed during login.

    opened by nuvious 0
  • Store duress password in unix crypt format

    Store duress password in unix crypt format

    https://github.com/nuvious/pam-duress/blob/30d7065e173d6062384387af10e74e8c1c138d48/src/duress.c#L193

    Using the modular crypt(3) format from glibc instead of specifying a hash, will make this a bit more future-proof, storing passwords the same way as standard password authentication.

    opened by rechner 5
  • Lack of unit tests.

    Lack of unit tests.

    At the moment there are not unit tests to ensure compatibility with linux, freebsd, etc. Also negative testing should be added to ensure that the module doesn't permit authentication attacks such as impersonation or privilege escalation. Finally there should be tests to ensure that scripts are only run if owned by the user or group the user; both positive tests and negative. Here's a list of the desired positive and negative test to implement.

    • Positive test for scripts in ~/.duress/*
      • Test with 500, 510, 550, 700, 710 & 750 # NOTE: Add support for 510 and 710 permissions.
    • Positive test for scripts in /etc/duress.d/*
    • Negative tests for improper permissions on duress scripts.
    • Docker files for all tests to run them under different distributions; ideally Debian, Ubuntu, BSD, CentOS/Redhat, etc.
    opened by nuvious 0
  • Failed to allocate buffer for getpwnam_r

    Failed to allocate buffer for getpwnam_r

    This is thrown from

        size_t buffer_len = sysconf(_SC_GETPW_R_SIZE_MAX) * sizeof(char);
        char *buffer = (char *) malloc(buffer_len);
        if (buffer == NULL)
        {
            syslog(LOG_INFO, "Failed to allocate buffer for getpwnam_r.\n");
            exit(2);
        }
        getpwnam_r(user_name, pwd, buffer, buffer_len, &pwd);
    

    in src/util.c, since for some reason, sysconf(_SC_GETPW_R_SIZE_MAX) yields -1 on that system (alpine linux 3.13). Any more infos needed?

    opened by kedorlaomer 5
This is a proof-of-concept of a modern C web-framework that compiles to WASM and is used for building user interfaces.

DanCing Web ?? ?? (DCW) Getting Started Dancing Web is now distributed with the Tarantella Package Manager — a tool I've made to simplify setup of pro

Danilo Chiarlone 3 Sep 11, 2021
Pion Network Library (Boost licensed open source)

Pion Network Library C++ framework for building lightweight HTTP interfaces Project Home: https://github.com/splunk/pion Retrieving the code git clone

Splunk GitHub 290 Dec 2, 2021
fix vmprotect import function used unicorn-engine.

Vm2Import fix vmprotect import function used unicorn-engine. it can repair functions such as call [module.function] or jmp [module.function] or reg(mo

共产主义接班人 55 Nov 10, 2021
The application framework for developer module of EdgeGallery platform

crane-framework crane-framework将可复用的计算和软件功能抽象成插件,APP开发者面向使用插件进行MEC APP开发。这样屏蔽了和MEC平台交互的细节,实现MCE APP和MEC平台的松耦合。而且插件框架基础能力可裁剪,按需提供最小的APP系统。 特性介绍 为了方便开发者

EdgeGallery 21 Aug 30, 2021
anthemtotheego 241 Dec 1, 2021
Cobalt Strike is a commercial, full-featured, remote access tool that bills itself as "adversary simulation software designed to execute targeted attacks and emulate the post-exploitation actions of advanced threat actors".

COBALT STRIKE 4.4 Cobalt Strike is a commercial, full-featured, remote access tool that bills itself as "adversary simulation software designed to exe

Trewis [work] Scotch 6 Nov 26, 2021
ESP32 + GitHub Actions + Husarnet. A boilerplate project for ESP32 allowing in-field firmware update using GitHub Actions workflow.

esp32-internet-ota ESP32 + GitHub Actions + Husarnet. A boilerplate project for ESP32 allowing in-field firmware update using GitHub Actions workflow.

Husarnet 18 Nov 27, 2021
King Hamlet is a simple tool, which allows you to perform a Process Ghosting Attack

KingHamlet Process Ghosting Tool - 64 bits Only! King Hamlet is a simple tool, which allows you to perform a Process Ghosting Attack

null 25 Nov 22, 2021
✔️The smallest header-only GUI library(4 KLOC) for all platforms

Welcome to GUI-lite The smallest header-only GUI library (4 KLOC) for all platforms. 中文 Lightweight ✂️ Small: 4,000+ lines of C++ code, zero dependenc

null 5.8k Nov 28, 2021
Stock exchange simulator made in Swing using Java with logic backend in C++ giving it faster load time and better data control

StockSimulator Stock exchange simulator made in Swing using Java with logic backend in C++ giving it faster load time and better data control Features

Dušan Todorović 1 Nov 4, 2021
A collection of multiple types of lists used during pentesting, collected in one place. List types include usernames, passwords, combos, wordlist and may more..

Access list is a collection of multiple types of lists used during pentesting, collected in one place, created by Undercode This list include a collec

UNDERCODE UTILITIES 6 Nov 7, 2021
HIBA is a system built on top of regular OpenSSH certificate-based authentication that allows to manage flexible authorization of principals on pools of target hosts without the need to push customized authorized_users files periodically.

HIBA is a system built on top of regular OpenSSH certificate-based authentication that allows to manage flexible authorization of principals on pools of target hosts without the need to push customized authorized_users files periodically.

Google 312 Nov 19, 2021
The pico can be used to program other devices. Raspberry pi made such an effort. However there is no board yet, that is open-source and can be used with OpenOCD as a general-purpose programmer

pico-probe-programmer The pico can be used to program other devices. Raspberry pi made such an effort. However there is no board yet, that is open-sou

martijn 17 Nov 29, 2021
By controlling the frequency at which the output Pins of MSP430 are turned off and on, we can make music.

By controlling the frequency at which the output Pins of MSP430 are turned off and on, we can make music.

Premkumar Vincent 1 Nov 9, 2021
A different way of calling the notify function on the ps4 for homebrew development.

PS4-Notify A different way of calling the notify function on the ps4 for homebrew development. Calling the new Notify void Notify(char* IconURI, char*

Greg 11 May 7, 2021
BerylDB is a data structure data manager that can be used to store data as key-value entries.

BerylDB is a data structure data manager that can be used to store data as key-value entries. The server allows channel subscription and is optimized to be used as a cache repository. Supported structures include lists, sets, and keys.

BerylDB 190 Nov 27, 2021
If the button pressed esp will reset and App mode will on. App mode will on then led will on, network is connected led will off.

DHT22-to-Google-sheet-Reset-Using-ESP8266-LED-Switch If button pressed esp will reset and App mode will on. App mode will on then led will on, network

Md. Harun-Or-Rashid 4 Oct 5, 2021
The purpose of these streams is to be educational and entertaining for viewers to learn about systems architecture, reverse engineering, software security, etc., and NOT to encourage nor endorse malicious game hacking.

Memestream This repository holds the code that I develop during my live game "modding" ?? sessions. When I stream, I like to speedrun making a success

Stephen Tong 20 Nov 14, 2021
C++ Live Toolkit are tools subset used to perform on-the-fly compilation and running of cpp code

C++ Live Toolkit CLT (C++ Live Toolkit) is subset of tools that are very light in size, and maintained to help programmers in compiling and executing

MondeO 1 Nov 16, 2021
Demonstrates basic advantages of integrating the Data Distribution Service (DDS) and Time-Sensitive Networking (TSN) Ethernet.

ROS2-DDS-TSN integration demo This repository demonstrates basic advantages of integrating the Data Distribution Service (DDS) and Time-Sensitive Netw

NXP 23 Dec 6, 2021
This is for interfacing rasberry-pi's (2 cards) with an arduino for sending raw data to form the close loop system to avoid motor heating by acting on a given temperature.

This is for interfacing rasberry-pi's (2 cards) with an arduino for sending raw data to form the close loop system to avoid motor heating by acting on a given temperature. Interface is explained through a master slave approach and client server approach. another camera is used with OPEN-CV platform to interface and collect data aswell.

Younes HAMZA 2 Oct 25, 2021
Samir Teymurov 1 Oct 6, 2021
This repository is a summary of the basic knowledge of recruiting job seekers and beginners in the direction of C/C++ technology, including language, program library, data structure, algorithm, system, network, link loading library, interview experience, recruitment, recommendation, etc.

?? C/C++ 技术面试基础知识总结,包括语言、程序库、数据结构、算法、系统、网络、链接装载库等知识及面试经验、招聘、内推等信息。This repository is a summary of the basic knowledge of recruiting job seekers and beginners in the direction of C/C++ technology, including language, program library, data structure, algorithm, system, network, link loading library, interview experience, recruitment, recommendation, etc.

huihut 21.5k Dec 6, 2021
An ESP32 system that can perform a Directory, Upload, Download, Delete, Rename and Stream Files in SPIFFS

ESP-File-Server An ESP32 system that can perform a Directory, Upload, Download, Delete, Rename and Stream Files in SPIFFS Using an ESP32 to handle fil

G6EJD 13 Oct 30, 2021
📝 Kernel module that can be used as a replacement for logger or logwrapper

Kernel logger Kernel logger is a kernel module that can be used as a replacement for logger or logwrapper. Its log is similar to systemd's journal and

Tian Yuanhao 31 Oct 25, 2021
An Open Source Implementation of the Actor Model in C++

CAF: C++ Actor Framework CAF is an open source implementation of the actor model for C++ featuring lightweight & fast actor implementations, pattern m

CAF: C++ Actor Framework 2.6k Dec 4, 2021
An implementation of Actor, Publish-Subscribe, and CSP models in one rather small C++ framework. With performance, quality, and stability proved by years in the production.

What is SObjectizer? What distinguishes SObjectizer? SObjectizer is not like TBB, taskflow or HPX Show me the code! HelloWorld example Ping-Pong examp

Stiffstream 226 Nov 29, 2021