├── CMakeLists.txt ├── LICENSE ├── README.md └── src ├── pendulum.c └── pendulum.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(pendulum LANGUAGES C) 3 | set(CMAKE_C_STANDARD 11) 4 | 5 | find_package(OpenSSL REQUIRED) 6 | include_directories(${OPENSSL_INCLUDE_DIR}) 7 | 8 | string(APPEND CMAKE_C_FLAGS " -Wno-deprecated-declarations") # OpenSSL RC4 is deprecated 9 | add_executable(${PROJECT_NAME} "src/pendulum.c") 10 | 11 | target_link_libraries(${PROJECT_NAME} ${OPENSSL_LIBRARIES}) 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Kyle Avery 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pendulum 2 | 3 | Sleep obfuscation for Linux. 4 | 5 | ## References 6 | 7 | * [POSIX sigevent manual](https://man7.org/linux/man-pages/man7/sigevent.7.html) 8 | * Inspired by [Ekko](https://github.com/Cracked5pider/Ekko), a Windows timer-based sleep obfuscation POC 9 | -------------------------------------------------------------------------------- /src/pendulum.c: -------------------------------------------------------------------------------- 1 | #include "pendulum.h" 2 | 3 | int prep_context(pen_state* s, int sleep_time) { 4 | RC4_set_key(&s->rc4.enc_key, 16, s->rc4.key); 5 | RC4_set_key(&s->rc4.dec_key, 16, s->rc4.key); 6 | 7 | if (getcontext(&s->ctx.prot_rw) == -1 || 8 | getcontext(&s->ctx.encrypt) == -1 || 9 | getcontext(&s->ctx.delay) == -1 || 10 | getcontext(&s->ctx.decrypt) == -1 || 11 | getcontext(&s->ctx.prot_rx) == -1 || 12 | getcontext(&s->ctx.signal) == -1 || 13 | getcontext(&s->ctx.block) == -1) { 14 | perror("getcontext"); 15 | return 1; 16 | } 17 | 18 | s->ctx.prot_rw.uc_link = &s->ctx.encrypt; 19 | makecontext(&s->ctx.prot_rw, (void (*)(void))mprotect, 3, s->target.data, s->target.size, PROT_READ | PROT_WRITE); 20 | 21 | s->ctx.encrypt.uc_link = &s->ctx.delay; 22 | makecontext(&s->ctx.encrypt, (void (*)(void))RC4, 4, &s->rc4.enc_key, s->target.size, s->target.data, s->target.data); 23 | 24 | s->ctx.delay.uc_link = &s->ctx.decrypt; 25 | makecontext(&s->ctx.delay, (void (*)(void))sleep, 1, sleep_time); 26 | 27 | s->ctx.decrypt.uc_link = &s->ctx.prot_rx; 28 | makecontext(&s->ctx.decrypt, (void (*)(void))RC4, 4, &s->rc4.dec_key, s->target.size, s->target.data, s->target.data); 29 | 30 | s->ctx.prot_rx.uc_link = &s->ctx.signal; 31 | makecontext(&s->ctx.prot_rx, (void (*)(void))mprotect, 3, s->target.data, s->target.size, PROT_READ | PROT_EXEC); 32 | 33 | s->ctx.signal.uc_link = &s->ctx.block; 34 | makecontext(&s->ctx.signal, (void (*)(void))sem_post, 1, &s->block_main); 35 | 36 | s->ctx.block.uc_link = &s->ctx.prot_rw; 37 | makecontext(&s->ctx.block, (void (*)(void))sem_wait, 1, &s->block_timer); 38 | 39 | return 0; 40 | } 41 | 42 | int pendulum(pen_state* s, int delay) { 43 | if (prep_context(s, delay) != 0) { 44 | return 1; 45 | } 46 | 47 | sem_post(&s->block_timer); 48 | sem_wait(&s->block_main); 49 | 50 | return 0; 51 | } 52 | 53 | static inline ucontext_t init_ctx() { 54 | return (ucontext_t){ 55 | .uc_stack.ss_sp = calloc(SIGSTKSZ, 1), 56 | .uc_stack.ss_size = SIGSTKSZ, 57 | .uc_stack.ss_flags = 0 58 | }; 59 | } 60 | 61 | static inline int init_state(pen_state** s) { 62 | *s = calloc(1, sizeof(pen_state)); 63 | if (*s == NULL) { 64 | perror("calloc"); 65 | return 1; 66 | } 67 | 68 | (*s)->ctx.prot_rw = init_ctx(); 69 | (*s)->ctx.encrypt = init_ctx(); 70 | (*s)->ctx.delay = init_ctx(); 71 | (*s)->ctx.decrypt = init_ctx(); 72 | (*s)->ctx.prot_rx = init_ctx(); 73 | (*s)->ctx.signal = init_ctx(); 74 | (*s)->ctx.block = init_ctx(); 75 | (*s)->target.data = &__executable_start; 76 | (*s)->target.size = (size_t) &__etext - (size_t) &__executable_start; 77 | (*s)->rc4.key = KEY; 78 | 79 | if (sem_init(&(*s)->block_main, 0, 0) == -1 || 80 | sem_init(&(*s)->block_timer, 0, 0) == -1) { 81 | perror("sem_init"); 82 | return 1; 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | static inline int init_timer(pen_state* s, timer_state** t) { 89 | if (s == NULL || t == NULL) { 90 | return 1; 91 | } 92 | 93 | *t = calloc(1, sizeof(timer_state)); 94 | if (*t == NULL) { 95 | perror("calloc"); 96 | return 1; 97 | } 98 | 99 | (*t)->delay = DELAY; 100 | 101 | (*t)->sigev.sigev_notify = SIGEV_THREAD; 102 | (*t)->sigev.sigev_notify_function = (void*)setcontext; 103 | (*t)->sigev.sigev_value.sival_ptr = (void*)&s->ctx.prot_rw; 104 | 105 | if (timer_create(CLOCK_REALTIME, &(*t)->sigev, &(*t)->timer) == -1) { 106 | perror("timer_create"); 107 | return 1; 108 | } 109 | 110 | (*t)->spec.it_interval.tv_sec = 0; 111 | (*t)->spec.it_interval.tv_nsec = 0; 112 | (*t)->spec.it_value.tv_sec = 0; 113 | (*t)->spec.it_value.tv_nsec = 1; 114 | 115 | return 0; 116 | } 117 | 118 | static int start_timer(pen_state* s, timer_state* t) { 119 | if (s == NULL || t == NULL) { 120 | return 1; 121 | } 122 | 123 | if (prep_context(s, t->delay) != 0) { 124 | return 1; 125 | } 126 | 127 | if (timer_settime(t->timer, 0, &t->spec, NULL) == -1) { 128 | perror("timer_settime"); 129 | return 1; 130 | } 131 | sem_wait(&s->block_main); 132 | 133 | return 0; 134 | } 135 | 136 | int main() { 137 | pen_state* s = NULL; 138 | timer_state* t = NULL; 139 | int counter = 0; 140 | 141 | if (init_state(&s) != 0) { 142 | return 1; 143 | } 144 | 145 | if (init_timer(s, &t) != 0) { 146 | return 1; 147 | } 148 | 149 | if (start_timer(s, t) != 0) { 150 | return 1; 151 | } 152 | 153 | while(1) { 154 | printf("Good morning %d\n", ++counter); 155 | if (pendulum(s, t->delay) != 0) { 156 | break; 157 | } 158 | } 159 | 160 | return 0; 161 | } 162 | -------------------------------------------------------------------------------- /src/pendulum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define DELAY 5 14 | #define KEY (unsigned char*)"abcd1234abcd1234" 15 | 16 | extern char __executable_start; 17 | extern char __etext; 18 | 19 | typedef struct itimerspec timerspec_t; 20 | typedef struct sigevent sigevent_t; 21 | 22 | typedef struct { 23 | int delay; 24 | timer_t timer; 25 | timerspec_t spec; 26 | sigevent_t sigev; 27 | } timer_state; 28 | 29 | typedef struct { 30 | sem_t block_main; 31 | sem_t block_timer; 32 | struct { 33 | ucontext_t prot_rw; 34 | ucontext_t encrypt; 35 | ucontext_t delay; 36 | ucontext_t decrypt; 37 | ucontext_t prot_rx; 38 | ucontext_t signal; 39 | ucontext_t block; 40 | } ctx; 41 | struct { 42 | void* data; 43 | size_t size; 44 | } target; 45 | struct { 46 | unsigned char* key; 47 | RC4_KEY enc_key; 48 | RC4_KEY dec_key; 49 | } rc4; 50 | } pen_state; 51 | --------------------------------------------------------------------------------