diff --git a/AUTHORS b/AUTHORS index b5f1cd0..0b64a86 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,3 @@ Francisco Garcia MD. JAHIDUL HAMID +intika diff --git a/ChangeLog b/ChangeLog index 5f96469..69432b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ CHANGES +4.0.3 Tue Nov 20 08:22:20 UTC 2018 + + * Enhance -H flag by intika (Hide commands arguments from ps and cmdline) + * Remove -s flag (experimental feature not working as expected by intika ) + 4.0.2 Mon 01 Jul 2019 02:57:36 PM UTC * Fix typo @@ -11,17 +16,17 @@ CHANGES 4.0.0 Mon Nov 12 16:54:56 UTC 2018 - * Add -H option for extra security without root (Thanks to intika ). It protects against dumping, code injection, `cat /proc/pid/cmdline`, ptrace, etc.. (only works with Bourne shell (sh) scripts with no parameter) + * Add -H option for extra security without root (Thanks to intika ). It protects against dumping, code injection, `cat /proc/pid/cmdline`, ptrace, etc.. (only works with Bourne shell (sh) scripts with no parameter) * Add -s option to force single process for hardening features (requires -H) . (only works with Bourne shell (sh) scripts with no parameter) - * dash support + * dash support 3.9.8 Sat Oct 20 17:49:28 UTC 2018 - * Add setuid option -S (Thanks to Boon Pang ) + * Add setuid option -S (Thanks to Boon Pang ) 3.9.7 Sat Oct 20 15:25:13 UTC 2018 - * Fix issue #58 + * Fix issue #58 3.9.6 Sat Jun 3 10:05:03 UTC 2017 diff --git a/README.md b/README.md index f25c121..3e2a978 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,6 @@ shc [options] shc -f script.sh -o binary shc -U -f script.sh -o binary # Untraceable binary (prevent strace, ptrace etc..) shc -H -f script.sh -o binary # Untraceable binary, does not require root (only bourne shell (sh) scripts with no parameter) -shc -H -s -f script.sh -o binary # Untraceable binary running in a singe process, does not require root (only bourne shell (sh) scripts with no parameter) ``` ## The hardening flag -H diff --git a/configure b/configure index b01a7ec..6b60fa7 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for shc 4.0.2. +# Generated by GNU Autoconf 2.69 for shc 4.0.3. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='shc' PACKAGE_TARNAME='shc' -PACKAGE_VERSION='4.0.2' -PACKAGE_STRING='shc 4.0.2' +PACKAGE_VERSION='4.0.3' +PACKAGE_STRING='shc 4.0.3' PACKAGE_BUGREPORT='http://github.com/neurobin/shc/issues' PACKAGE_URL='' @@ -1268,7 +1268,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures shc 4.0.2 to adapt to many kinds of systems. +\`configure' configures shc 4.0.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1334,7 +1334,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of shc 4.0.2:";; + short | recursive ) echo "Configuration of shc 4.0.3:";; esac cat <<\_ACEOF @@ -1425,7 +1425,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -shc configure 4.0.2 +shc configure 4.0.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1851,7 +1851,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by shc $as_me 4.0.2, which was +It was created by shc $as_me 4.0.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2721,7 +2721,7 @@ fi # Define the identity of the package. PACKAGE='shc' - VERSION='4.0.2' + VERSION='4.0.3' cat >>confdefs.h <<_ACEOF @@ -5299,7 +5299,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by shc $as_me 4.0.2, which was +This file was extended by shc $as_me 4.0.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5356,7 +5356,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -shc config.status 4.0.2 +shc config.status 4.0.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index ece0570..5caa65d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([shc], [4.0.2], [http://github.com/neurobin/shc/issues]) +AC_INIT([shc], [4.0.3], [http://github.com/neurobin/shc/issues]) AC_CONFIG_AUX_DIR(config) #prefix="/usr" AC_CONFIG_SRCDIR([src/shc.c]) diff --git a/shc.1 b/shc.1 index df2a123..1e6cf8e 100644 --- a/shc.1 +++ b/shc.1 @@ -6,7 +6,7 @@ shc \- Generic shell script compiler .PP \f[B]shc\f[] [ \-e \f[I]date\f[] ] [ \-m \f[I]addr\f[] ] [ \-i \f[I]iopt\f[] ] [ \-x \f[I]cmnd\f[] ] [ \-l \f[I]lopt\f[] ] [ \-o -\f[I]outfile\f[] ] [ \-ABCDhUHsvSr ] \-f \f[I]script\f[] +\f[I]outfile\f[] ] [ \-ABCDhUHvSr ] \-f \f[I]script\f[] .SH DESCRIPTION .PP \f[B]shc\f[] creates a stripped binary executable version of the script @@ -86,15 +86,7 @@ Extra security flag without root access requirement that protects against dumping, code injection, \f[C]cat\ /proc/pid/cmdline\f[], ptrace, etc.. This feature is \f[B]experimental\f[] and may not work on all systems. -This option currently only works with Bourne shell (sh) scripts without -any positional parameters. -.PP -\-s : Hardening with single process. -Requires \-H option, runs the binary in a single process, shell is -called in the main process otherwise its called in a child process. -This feature is \f[B]experimental\f[] (may hang) and may not work on all -systems. -This option currently only works with Bourne shell (sh) scripts without +it require bourne shell (sh) scripts any positional parameters. .PP \-C : Display license and exit @@ -147,6 +139,8 @@ limited by the operating system configuration parameter .PP Francisco Rosales .PP +intika +.PP Md Jahidul Hamid .SH REPORT BUGS TO .PP diff --git a/src/shc.c b/src/shc.c index fad01e5..7b73d85 100644 --- a/src/shc.c +++ b/src/shc.c @@ -17,7 +17,7 @@ */ static const char my_name[] = "shc"; -static const char version[] = "Version 4.0.2"; +static const char version[] = "Version 4.0.3"; static const char subject[] = "Generic Shell Script Compiler"; static const char cpright[] = "GNU GPL Version 3"; static const struct { const char * f, * s, * e; } @@ -68,7 +68,7 @@ static const char * abstract[] = { 0}; static const char usage[] = -"Usage: shc [-e date] [-m addr] [-i iopt] [-x cmnd] [-l lopt] [-o outfile] [-rvDSUHCABhs] -f script"; +"Usage: shc [-e date] [-m addr] [-i iopt] [-x cmnd] [-l lopt] [-o outfile] [-rvDSUHCABh] -f script"; static const char * help[] = { "", @@ -85,14 +85,7 @@ static const char * help[] = { " -D Switch ON debug exec calls [OFF]", " -U Make binary untraceable [no]", " -H Hardening : extra security protection [no]", -" untraceable, undumpable, etc. and root is not required", -" * currently only works with bourne shell (sh)", -" * does not work with positional parameters", -" -s Hardening : use a single process (no child) [no]", -" option available only with -H otherwise its ignored", -" experimental feature may hang...", -" * currently only works with bourne shell (sh)", -" * does not work with positional parameters", +" Require bourne shell (sh) and parameters are not supported", " -C Display license and exit", " -A Display abstract and exit", " -B Compile for busybox", @@ -148,15 +141,92 @@ static int TRACEABLE_flag = 1; static const char HARDENING_line[] = "#define HARDENING %d /* Define as 1 to disable ptrace/dump the executable */\n"; static int HARDENING_flag = 0; -static const char HARDENINGSP_line[] = -"#define HARDENINGSP %d /* Define as 1 to disable bash child process */\n"; -static int HARDENINGSP_flag = 0; static const char BUSYBOXON_line[] = "#define BUSYBOXON %d /* Define as 1 to enable work with busybox */\n"; static int BUSYBOXON_flag = 0; static const char * RTC[] = { "", +"#if HARDENING", +"static const char * shc_x[] = {", +"\"/*\",", +"\" * Copyright 2019 - Intika \",", +"\" * Replace ******** with secret read from fd 21\",", +"\" * Also change arguments location of sub commands (sh script commands)\",", +"\" * gcc -Wall -fpic -shared -o shc_secret.so shc_secret.c -ldl\",", +"\" */\",", +"\"\",", +"\"#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */\",", +"\"#define PLACEHOLDER \\\"********\\\"\",", +"\"#include \",", +"\"#include \",", +"\"#include \",", +"\"#include \",", +"\"#include \",", +"\"#include \",", +"\"\",", +"\"static char secret[128000]; //max size\",", +"\"typedef int (*pfi)(int, char **, char **);\",", +"\"static pfi real_main;\",", +"\"\",", +"\"// copy argv to new location\",", +"\"char **copyargs(int argc, char** argv){\",", +"\" char **newargv = malloc((argc+1)*sizeof(*argv));\",", +"\" char *from,*to;\",", +"\" int i,len;\",", +"\"\",", +"\" for(i = 0; i 0) {\",", +"\" int i;\",", +"\"\",", +"\" if (secret[n - 1] == '\\\\n') secret[--n] = '\\\\0';\",", +"\" for (i = 1; i < argc; i++)\",", +"\" if (strcmp(argv[i], PLACEHOLDER) == 0)\",", +"\" argv[i] = secret;\",", +"\" }\",", +"\"\",", +"\" real_main = main;\",", +"\"\",", +"\" return real___libc_start_main(mymain, argc, argv, init, fini, rtld_fini, stack_end);\",", +"\"}\",", +"\"\",", +"0};", +"#endif /* HARDENING */", +"", "/* rtc.c */", "", "#include ", @@ -291,64 +361,51 @@ static const char * RTC[] = { "} ", "/* End Seccomp Sandboxing Init */", "", +"void shc_x_file() {", +" FILE *fp;", +" int line = 0;", +"", +" if ((fp = fopen(\"/tmp/shc_x.c\", \"w\")) == NULL ) {exit(1); exit(1);}", +" for (line = 0; shc_x[line]; line++) fprintf(fp, \"%s\\n\", shc_x[line]);", +" fflush(fp);fclose(fp);", +"}", +"", +"int make() {", +" char * cc, * cflags, * ldflags;", +" char cmd[4096];", +"", +" cc = getenv(\"CC\");", +" if (!cc) cc = \"cc\";", +"", +" sprintf(cmd, \"%s %s -o %s %s\", cc, \"-Wall -fpic -shared\", \"/tmp/shc_x.so\", \"/tmp/shc_x.c -ldl\");", +" if (system(cmd)) {remove(\"/tmp/shc_x.c\"); return -1;}", +" remove(\"/tmp/shc_x.c\"); return 0;", +"}", +"", "void arc4_hardrun(void * str, int len) {", " //Decode locally", " char tmp2[len];", +" char tmp3[len+1024];", " memcpy(tmp2, str, len);", "", " unsigned char tmp, * ptr = (unsigned char *)tmp2;", -"", " int lentmp = len;", +" int pid, status;", +" pid = fork();", "", -"#if HARDENINGSP", -" //Start tracing to protect from dump & trace", -" if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {", -" printf(\"Operation not permitted\\n\");", -" kill(getpid(), SIGKILL);", -" exit(1);", -" }", -"", -" //Decode Bash", -" while (len > 0) {", -" indx++;", -" tmp = stte[indx];", -" jndx += tmp;", -" stte[indx] = stte[jndx];", -" stte[jndx] = tmp;", -" tmp += stte[indx];", -" *ptr ^= stte[tmp];", -" ptr++;", -" len--;", -" }", -"", -" //Exec bash script", -" system(tmp2);", -"", -" //Empty script variable", -" memcpy(tmp2, str, lentmp);", +" shc_x_file();", +" if (make()) {exit(1);}", "", -" //Sinal to detach ptrace", -" ptrace(PTRACE_DETACH, 0, 0, 0);", -" exit(0);", +" setenv(\"LD_PRELOAD\",\"/tmp/shc_x.so\",1);", "", -" /* Seccomp Sandboxing - Start */", -" seccomp_hardening();", -"", -" exit(0);", -"#endif /* HARDENINGSP Exit here anyway*/", -"", -" int pid, status;", -" pid = fork();", -"", " if(pid==0) {", "", " //Start tracing to protect from dump & trace", " if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {", -" printf(\"Operation not permitted\\n\");", " kill(getpid(), SIGKILL);", " _exit(1);", " }", -"", +"", " //Decode Bash", " while (len > 0) {", " indx++;", @@ -362,25 +419,29 @@ static const char * RTC[] = { " len--;", " }", "", -" //Exec bash script", +" //Do the magic", +" sprintf(tmp3, \"%s %s\", \"'********' 21<<<\", tmp2);", +"", +" //Exec bash script //fork execl with 'sh -c'", " system(tmp2);", "", " //Empty script variable", " memcpy(tmp2, str, lentmp);", "", +" //Clean temp", +" remove(\"/tmp/shc_x.so\");", +"", " //Sinal to detach ptrace", " ptrace(PTRACE_DETACH, 0, 0, 0);", " exit(0);", " }", -" else {", -" wait(&status);", -" }", +" else {wait(&status);}", "", " /* Seccomp Sandboxing - Start */", " seccomp_hardening();", "", " exit(0);", -"} ", +"}", "#endif /* HARDENING */", "", "/*", @@ -689,7 +750,7 @@ static const char * RTC[] = { static int parse_an_arg(int argc, char * argv[]) { extern char * optarg; - const char * opts = "e:m:f:i:x:l:o:rvDSUHCABhs"; + const char * opts = "e:m:f:i:x:l:o:rvDSUHCABh"; struct tm tmp[1]; time_t expdate; int cnt, l; @@ -756,9 +817,6 @@ static int parse_an_arg(int argc, char * argv[]) case 'H': HARDENING_flag = 1; break; - case 's': - HARDENINGSP_flag = 1; - break; case 'C': fprintf(stderr, "%s %s, %s\n", my_name, version, subject); fprintf(stderr, "%s %s %s %s %s\n", my_name, cpright, provider.f, provider.s, provider.e); @@ -826,11 +884,6 @@ static void parse_args(int argc, char * argv[]) err++; } while (ret); - if (HARDENING_flag == 0 && HARDENINGSP_flag == 1) { - fprintf(stderr, "\n%s '-s' feature is only available with '-H'\n",my_name); - err++; - } - if (err) { fprintf(stderr, "\n%s %s\n\n", my_name, usage); exit(1); @@ -1222,7 +1275,6 @@ int write_C(char * file, char * argv[]) fprintf(o, DEBUGEXEC_line, DEBUGEXEC_flag); fprintf(o, TRACEABLE_line, TRACEABLE_flag); fprintf(o, HARDENING_line, HARDENING_flag); - fprintf(o, HARDENINGSP_line, HARDENINGSP_flag); fprintf(o, BUSYBOXON_line, BUSYBOXON_flag); for (indx = 0; RTC[indx]; indx++) fprintf(o, "%s\n", RTC[indx]);