Compilando Shell Scripts com o SHC

De ISPUP!
Revisão de 15h00min de 5 de fevereiro de 2023 por Gondim (discussão | contribs)
Ir para navegação Ir para pesquisar

Introdução

Em algumas situações você pode querer que seu código escrito em shell script seja compilado por diversos motivos como por exemplo: esconder alguma informação sigilosa que está dentro do script, uma credencial de acesso à base de dados, ou porque você não quer que alguém altere o código sem a sua permissão, ou porque você não quer entregar o "ouro" da sua consultoria. Enfim, é uma maneira de esconder o seu código dos olhos alheios. Mas existem algumas coisas que temos que ter em mente quando formos usá-lo:

  • Ele não é a prova de NSA (National Security Agency). Não possui uma criptografia de alto nível mas ajuda bastante na tarefa.
  • Não gera binários independentes. Você continuará dependendo do shell e de todos os programas que ele chama.
  • O SHC (Shell Script Compiler) precisa ter no topo do arquivo o shebang, a informação que aponta o shell que será usado, por exemplo: #!/usr/bin/bash ou #!/usr/bin/sh
  • O SHC gera um código em fonte C do shell script, que na sequência é compilado. Sim você precisa ter um compilador C para isso. No processo de execução, o programa é desencriptado e executado como um bash normal; por isso não é um binário independente.
  • Você pode colocar um prazo de validade do binário e uma mensagem para quem executar o programa após vencer a validade. Ex: "Programa expirado contacte fulano".
  • O binário fica bem maior que o seu arquivo shell script.
  • Não pense que a execução do seu novo binário será muito mais rápido que o seu shell, porque como eu disse, o processo é rodado como shell após ser desencriptado.









Instalação

Como é de hábito aqui, faremos isso no Debian, nesse caso a versão 11 (Bullseye). Você pode instalar o SHC em qualquer distribuição GNU/Linux de sua preferência, só precisará checar se já existe um pacote para ele ou se vai precisar compilar o fonte e logicamente ter um compilador C também instalado para isso.

apt install shc build-essential

Utilizando o SHC

Vou pegar como exemplo um script de backup que tenho aqui e que além de fazer backup dos arquivos e diretórios que tenho no servidor, ele gera um backup da base de dados e as tabelas separadamente.

#!/usr/bin/bash
SERVIDOR="azn"
PROVEDOR="Area Zero Network"
TEMP="/usr/local/backup/azn"
USER="root"
PASS="tua_senha_aqui"

dpkg -l > $TEMP/`date +%d`/lista_pacotes.txt
tar -czpf $TEMP/`date +%d`/$SERVIDOR.tar.gz /etc /root /var/www
tar -tzpf $TEMP/`date +%d`/$SERVIDOR.tar.gz
if [ $? -ne 0 ]; then
        echo "Erro gerando backup AZN tar.gz!" | /usr/local/sbin/telegram-notify --error --text -
   exit
fi

rm $TEMP/`date +%d`/*.bz2
for banco in $(mysql -u$USER -p$PASS --execute="show databases" | grep -v Database) ; do
 for tabela in $(mysql -u$USER -p$PASS --execute="show tables" $banco | grep -v Tables_in_) ; do
   if [ "$banco" == "mysql" -a "$tabela" == "general_log" ]; then
      mysqldump -c -u$USER -p$PASS --lock-tables=0 $banco $tabela | bzip2 -9 > $TEMP/`date +%d`/$SERVIDOR-$banco-$tabela.sql.bz2
   else
      if [ "$banco" == "mysql" -a "$tabela" == "slow_log" ]; then
         mysqldump -c -u$USER -p$PASS --lock-tables=0 $banco $tabela | bzip2 -9 > $TEMP/`date +%d`/$SERVIDOR-$banco-$tabela.sql.bz2
      else
         mysqldump -c -u$USER -p$PASS --single-transaction=TRUE $banco $tabela | bzip2 -9 > $TEMP/`date +%d`/$SERVIDOR-$banco-$tabela.sql.bz2
      fi
   fi
   if [ $? -ne 0 ]; then
        echo "Erro gerando backup AZN MariaDB!" | /usr/local/sbin/telegram-notify --error --text -
      exit
   fi
 done
done

echo "Backup do servidor AZN feito corretamente!" | /usr/local/sbin/telegram-notify --success --text -

Esse script além de fazer o backup, me avisa pelo Telegram se foi tudo bem ou se deu algum erro. Percebam que ali na variável PASS teria a senha da base de dados para o backup e não é bom que fique assim disponível para qualquer um ver. Então vamos compilar nosso shell script assim, supondo que o nome dele seja backup.sh.

# shc -o backup -f backup.sh

Esse comando lerá o backup.sh, gerará nosso binário chamado backup e o fonte em C chamado backup.sh.x.c.

# ls -lah backup_*
-rwxrwxr-x 1 root root  17K fev  5 14:19 backup
-rwx------ 1 root root 1,5K fev  5 13:59 backup.sh
-rw-r--r-- 1 root root  25K fev  5 14:19 backup.sh.x.c

Primeira coisa que reparamos é o tamanho de cada arquivo; nosso backup.sh possui um apenas 1,5k de tamanho enquanto o binário ficou com 17k. Mas não vamos ser mesquinhos quanto a isso, porque na maioria das vezes temos bastante recurso de memória nos servidores que mexemos não é mesmo?

Vamos olhar como ficou nosso fonte em C?

#if 0
        shc Version 4.0.3, Generic Shell Script Compiler
        GNU GPL Version 3 Md Jahidul Hamid <[email protected]>

        shc -o backup_azn -f backup_azn.sh
#endif

static  char data [] =
#define      chk2_z     19
#define      chk2       ((&data[3]))
        "\132\367\223\065\273\354\372\026\336\302\175\261\134\337\354\357"
        "\375\203\257\174\303\036"
#define      msg2_z     19
#define      msg2       ((&data[26]))
        "\155\236\003\175\207\220\316\347\020\101\333\207\160\021\241\204"
        "\017\071\370\357\256\164\171\203\210"
#define      tst1_z     22
#define      tst1       ((&data[47]))
        "\230\215\223\271\263\242\067\162\123\145\022\201\376\321\007\232"
        "\336\205\051\005\242\301\356\243\232\046\200"
#define      rlax_z     1
#define      rlax       ((&data[74]))
        "\166"
#define      opts_z     1
#define      opts       ((&data[75]))
        "\315"
#define      xecc_z     15
#define      xecc       ((&data[76]))
        "\355\244\240\352\251\255\145\034\004\045\341\147\267\353\330\001"
        "\113"
#define      text_z     1447
#define      text       ((&data[445]))
        "\200\361\155\356\220\160\153\024\371\350\061\363\327\324\216\376"
        "\125\100\311\217\007\243\030\145\307\233\147\023\170\140\363\371"
        "\122\140\347\342\321\123\366\313\073\050\277\023\375\115\021\123"
        "\216\332\343\226\176\373\373\106\227\143\131\020\303\115\011\025"
        "\256\360\370\177\103\357\113\177\027\012\222\025\130\244\151\346"
        "\176\114\175\374\110\171\102\337\334\234\357\237\351\371\265\227"
        "\351\255\027\055\234\143\255\264\156\100\312\306\344\063\255\143"
        "\200\052\140\310\243\243\250\200\100\230\037\052\221\324\301\173"
        "\202\331\250\037\075\126\323\253\226\236\162\173\321\037\336\121"
        "\112\077\032\356\342\302\156\042\133\216\114\354\143\016\147\345"
        "\350\020\004\045\146\330\321\375\166\103\171\110\143\127\231\255"
        "\227\264\233\171\167\012\233\322\230\347\276\373\366\045\340\336"
        "\066\345\004\234\276\325\232\064\030\023\174\173\153\026\051\002"
        "\313\304\174\102\317\027\024\147\377\323\142\366\371\103\324\057"
        "\051\330\314\347\255\146\034\306\172\231\101\346\257\152\351\172"
        "\057\145\275\376\175\321\146\174\245\311\163\236\015\107\315\066"
        "\040\231\036\315\000\072\224\172\323\325\140\203\100\111\376\157"
        "\257\274\156\054\216\325\251\063\236\034\321\253\143\236\342\204"
        "\070\001\122\070\073\346\262\017\273\023\223\373\135\221\153\014"
        "\116\332\071\334\257\342\017\115\376\340\371\142\177\334\347\267"
        "\335\071\357\030\037\242\050\332\266\273\326\024\115\102\040\233"
        "\034\132\167\313\074\207\030\073\147\022\236\347\356\205\236\313"
        "\233\371\176\335\105\332\023\173\031\136\021\047\075\346\271\136"
        "\355\074\167\335\232\056\205\052\300\064\000\012\377\036\170\333"
        "\057\321\206\064\306\260\160\276\226\217\301\254\246\003\034\075"
        "\257\100\264\272\042\105\117\252\060\211\073\163\331\064\317\164"
        "\320\321\000\067\012\234\257\331\110\110\324\153\257\206\234\041"
        "\147\271\357\244\113\105\017\227\127\300\255\111\014\120\272\366"
        "\156\313\217\171\257\066\331\320\066\150\073\234\275\012\364\237"
        "\054\001\154\276\113\361\373\317\053\211\251\217\103\015\043\302"
        "\054\207\100\301\337\232\137\013\056\301\145\105\116\226\222\077"
        "\316\346\311\273\066\256\334\022\176\152\031\351\327\270\315\177"
        "\335\333\154\367\367\166\355\106\355\275\336\335\221\052\350\323"
        "\320\337\211\040\255\271\012\073\311\170\010\055\335\351\360\207"
        "\302\240\366\061\057\042\116\177\165\160\102\357\307\137\053\163"
        "\036\045\043\123\231\007\217\000\212\012\310\121\345\104\343\370"
        "\360\153\324\133\045\353\127\072\167\153\011\151\161\076\067\300"
        "\337\371\270\330\232\207\030\213\046\316\006\302\246\274\005\160"
        "\100\037\351\126\142\242\051\117\046\220\175\351\041\156\155\220"
        "\333\334\125\112\135\336\246\374\252\132\355\054\046\132\326\175"
        "\363\134\114\056\113\163\326\163\160\237\364\026\371\301\226\111"
        "\373\126\264\325\310\061\066\274\115\230\137\055\203\255\047\213"
        "\016\140\143\000\222\073\247\120\056\002\263\170\367\313\050\376"
        "\314\215\225\061\254\140\241\057\151\147\047\342\040\314\174\132"
        "\236\136\154\160\032\233\256\101\310\117\367\264\053\216\326\231"
        "\323\172\362\243\136\201\150\136\035\067\055\325\311\171\307\042"
        "\336\305\276\370\071\123\371\063\006\214\225\125\141\036\076\151"
        "\330\247\141\231\030\370\271\216\140\030\163\365\252\157\224\041"
        "\261\125\147\245\060\030\307\240\300\260\263\021\324\174\203\010"
        "\275\313\254\145\266\340\162\052\020\245\060\232\307\002\102\354"
        "\270\110\011\230\332\035\234\135\020\342\122\260\372\251\302\250"
        "\034\114\171\362\307\166\142\137\270\153\371\117\073\251\352\267"
        "\016\157\220\362\226\117\075\275\041\261\210\074\227\274\045\073"
        "\154\250\217\233\322\023\211\163\044\316\326\372\347\334\310\036"
        "\277\062\335\045\163\221\136\162\147\321\170\016\037\043\073\115"
        "\115\352\250\143\314\210\017\337\211\071\222\026\064\022\115\336"
        "\341\214\240\217\320\057\167\232\043\020\155\272\144\316\222\305"
        "\311\112\213\346\377\036\142\270\241\272\163\363\024\264\157\131"
        "\215\371\345\323\264\074\135\126\222\062\352\220\154\101\363\256"
        "\071\161\210\254\372\312\106\076\273\272\062\221\007\306\164\351"
        "\112\343\360\006\011\362\304\071\307\112\274\125\172\024\174\375"
        "\365\150\307\106\042\357\220\337\253\174\225\247\110\374\066\005"
        "\311\376\230\335\232\304\206\340\374\302\112\346\353\063\340\061"
        "\261\075\302\367\344\374\125\256\245\002\142\105\162\212\060\350"
        "\033\351\206\150\162\020\033\064\375\035\035\016\360\001\373\304"
        "\317\157\266\202\333\316\127\203\041\124\162\347\167\064\322\033"
        "\072\343\231\126\224\371\234\171\372\263\051\075\262\363\203\024"
        "\151\304\264\210\021\353\204\124\245\271\072\250\042\226\044\174"
        "\330\246\271\012\246\334\325\261\331\147\334\335\257\010\362\076"
        "\306\364\231\134\167\242\025\050\273\207\125\166\007\132\101\226"
        "\130\331\174\070\236\063\356\140\371\375\265\270\066\244\010\004"
        "\013\321\352\126\200\372\211\275\204\327\361\346\121\273\121\277"
        "\326\116\013\114\200\245\060\225\047\223\051\172\310\113\065\364"
        "\165\064\225\330\032\240\013\252\074\301\222\162\005\252\223\055"
        "\271\361\313\161\147\236\176\145\315\354\140\111\341\331\207\164"
        "\103\353\061\217\155\135\226\260\263\223\150\124\271\151\146\261"
        "\041\362\050\276\377\350\021\045\336\103\134\235\042\200\217\142"
        "\271\273\154\035\056\354\351\014\077\214\141\057\111\220\255\137"
        "\064\171\377\324\146\251\362\020\325\124\260\101\246\117\167\102"
        "\152\274\034\161\330\240\317\360\155\002\232\256\111\031\336\152"
        "\036\235\015\137\006\314\211\130\310\237\045\034\177\375\143\322"
        "\116\164\006\005\203\260\012\361\012\073\054\014\125\263\301\327"
        "\040\002\072\235\274\002\342\355\042\025\131\250\204\231\300\374"
        "\125\015\006\327\105\311\126\142\257\371\156\034\333\051\316\072"
        "\014\116\327\250\164\037\337\370\254\345\323\067\055\225\257\247"
        "\104\045\176\142\215\246\367\323\356\303\131\101\172\034\356\101"
        "\001\115\054\102\300\062\367\053\056\011\254\375\147\244\265\131"
        "\305\054\230\031\144\171\224\223\246\072\002\244\020\212\303\053"
        "\033\377\017\314\210\064\064\152\303\323\230\152\373\060\070\360"
        "\006\063\272\334\232\257\273\004\002\162\041\177\032\143\334\303"
        "\207\021\153\210\257\075\336\344\151\250\255\111\022\167\104\342"
        "\265\150\000\057\271\331\265\210\357\315\141\374\252\120\035\273"
        "\023\170\117\234\324\071\372\345\272\155\334\311\102\173\026\030"
        "\156\355\362\244\025\367\361\100\212\117\220\342\311\111\240\052"
        "\133\117\365\363\324\364\357\121\171\320\352\103\110\017\055\352"
        "\050\034\222\060\374\335\253\120\211\310\175\374\243\376\135\003"
        "\367\015\374\311\250\146\137\001\377\132\211\136\125\163\124\246"
        "\034\373\002\201\347\376\023\211\010\122\073\356\066\333\234\151"
        "\010\075\141\220\377\163\045\253\001\043\005\170\014\232\005\226"
        "\017\113\177\153\123\350\047\151\174\300\340\060\226\163\072\205"
        "\257\124\101\113\132\112\165\150\040\231\016\245\301\165\020\055"
        "\205\214\260\014\245\213\013\075\062\267\244\162\247\154\301\332"
        "\031\200\231\146\364\111\123\237\273\376\145\000\347\117\017\215"
        "\077\105\240\013\024\024\301\233\046\331\016\242\340\211\212\374"
        "\270\310\037\126\321\133\344\136\336\352\023\075\277\107\011\065"
        "\053\061\041\130\367\217\004\074\300\224\177\361\313\375\215\356"
        "\203\354\272\353\174\144\374\261\210\277\365\073\246\064\061\041"
        "\176\311\260\345\340\164\310\322\133\125\161\330\044\214\346\221"
        "\132\260\311\232\240\364\126\026\242\077\155\122\012\202\163\041"
        "\367\266\130\106\306\360\301\335\175\035\301\253\066\163\163\027"
        "\243\112\112\015\141\013\130\354\204\030\172\043\043\126\003\040"
        "\357\032\200\104\074\042\146\243\003\001\271\132\352\030\310\062"
        "\151\107\040\340\311\050\064\276\216\344\335\061\014\270\350\310"
        "\217\374\026\321\035\261\355\167\051\270\263\260\321\357\030\343"
        "\215\377\322\023\236\235\321\055\202\257\137\217\150\107\130\367"
        "\103\156\310\140\040\265\327\112\156\213\373\077\173\023\043\010"
        "\023\365\034\262\223\355\337\026\235\076\245\005\206\375\374\311"
        "\154\305\052\214\172\001\327\351\215\322\051\010\345\115\021\371"
        "\102\055\253\326\033\213\354\270\311\222\276\117\220\272\031\374"
        "\177\103\211\372\105\140\344\323\062\015\333\030\132\355\021\235"
        "\033\275\164\066\110\141\357\022\363\256\142\204\150\173\201\350"
        "\277\013\343\004\153\307\327\236\325\263\267\057\240\311\315\274"
        "\206\101\363\316\242\342\340\226\220\102\033\371\276\234\342\175"
        "\247\305\202\023\215\132\262\142\015\152\222\256\063\140\152\271"
        "\242\135\210\105\100\150\333\321\253\367\313\151\223\255\347\073"
        "\163\151\117\001\303\001\144\321\153\366\177\237\127\352\131\371"
        "\110\341\076\211\112\032\132\365\021\045\137\245\323\107\340\107"
        "\260\060\110\164\062\254\105\236\243\305\075\372\260\226\363\371"
        "\167\062\202\302\114\334\270\136\002\027\003\326\137\344\035\017"
        "\024\145\204\106\022\312\345\265\220\042\257\100\271\243\072\060"
        "\325\274\363\042\230\253\200\233\303\203\161\042\150\216\062\174"
        "\364\266\303\006\201\250\273\021\313\153\122\204\016\214\265\343"
        "\110\250"
#define      pswd_z     256
#define      pswd       ((&data[2264]))
        "\206\174\026\011\356\071\161\175\153\356\161\041\262\167\243\133"
        "\063\264\047\236\007\253\254\223\141\220\334\012\226\276\135\034"
        "\073\164\046\051\255\230\246\031\207\027\073\072\217\336\225\302"
        "\223\274\141\232\150\015\056\311\236\101\076\361\044\220\317\170"
        "\261\011\034\377\147\300\222\275\137\211\064\206\360\045\346\355"
        "\231\152\334\061\323\337\213\050\041\312\031\106\133\351\276\014"
        "\362\332\014\131\233\237\027\372\050\113\201\030\161\147\006\012"
        "\322\342\073\245\302\307\315\343\222\347\051\355\320\347\372\302"
        "\302\006\034\135\245\063\130\315\177\332\346\360\102\354\373\024"
        "\317\067\271\221\377\207\165\221\157\236\176\077\206\170\002\111"
        "\176\036\247\044\122\000\361\321\332\330\302\034\304\275\060\224"
        "\364\352\046\363\162\233\205\341\071\003\041\300\174\043\011\373"
        "\102\260\037\225\260\021\146\213\351\050\247\256\346\330\102\332"
        "\302\150\316\065\004\123\026\076\127\067\376\323\133\007\317\236"
        "\270\356\063\151\000\232\364\351\303\234\227\251\164\332\204\067"
        "\103\122\154\107\246\202\205\375\272\204\321\026\214\240\264\105"
        "\217\350\256\217\202\243\171\105\077\021\356\264\353\163\353\057"
        "\305\130\167\154\333\375\152\225\201\073\253\015\334\140\123\153"
        "\110\001\373\312\245\164\020\345\205\377\231\161\162\205\240\067"
        "\335\027\244\270\024\016\116\226\112\012\324\064\311\061\121\004"
        "\246\170\055\124\020\324\155\230\354\250\322\174\207\147"
#define      shll_z     14
#define      shll       ((&data[2541]))
        "\201\333\141\250\373\350\322\221\324\376\333\204\172\165"
#define      tst2_z     19
#define      tst2       ((&data[2558]))
        "\255\342\127\230\174\067\202\133\305\341\056\052\041\216\246\161"
        "\266\045\220\035\116\151\114\355"
#define      date_z     1
#define      date       ((&data[2579]))
        "\173"
#define      lsto_z     1
#define      lsto       ((&data[2580]))
        "\061"
#define      msg1_z     65
#define      msg1       ((&data[2585]))
        "\130\134\275\306\206\170\220\063\325\271\325\374\376\070\240\216"
        "\263\032\004\000\156\271\123\225\240\070\024\223\202\157\071\257"
        "\103\314\022\152\374\277\174\330\076\251\125\113\033\155\230\356"
        "\032\306\005\320\306\227\244\323\257\032\172\026\305\153\101\147"
        "\346\271\102\230\037\364\251\157\306\045\366\056\144\020\123\004"
        "\304\340\262\247"
#define      inlo_z     3
#define      inlo       ((&data[2665]))
        "\054\131\301"
#define      chk1_z     22
#define      chk1       ((&data[2670]))
        "\300\122\272\277\177\234\273\371\140\206\142\100\226\064\304\245"
        "\163\143\142\034\026\135\015\306\006"/* End of data[] */;
#define      hide_z     4096
#define SETUID 0        /* Define as 1 to call setuid(0) at start of script */
#define DEBUGEXEC       0       /* Define as 1 to debug execvp calls */
#define TRACEABLE       1       /* Define as 1 to enable ptrace the executable */
#define HARDENING       0       /* Define as 1 to disable ptrace/dump the executable */
#define BUSYBOXON       0       /* Define as 1 to enable work with busybox */

#if HARDENING
static const char * shc_x[] = {
"/*",
" * Copyright 2019 - Intika <[email protected]>",
" * 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 <dlfcn.h>",
"#include <stdlib.h>",
"#include <string.h>",
"#include <unistd.h>",
"#include <stdio.h>",
"#include <signal.h>",
"",
"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<argc; i++){",
"        from = argv[i];",
"        len = strlen(from)+1;",
"        to = malloc(len);",
"        memcpy(to,from,len);",
"        // zap old argv space",
"        memset(from,'\\0',len);",
"        newargv[i] = to;",
"        argv[i] = 0;",
"    }",
"    newargv[argc] = 0;",
"    return newargv;",
"}",
"",
"static int mymain(int argc, char** argv, char** env) {",
"    //fprintf(stderr, \"Inject main argc = %d\\n\", argc);",
"    return real_main(argc, copyargs(argc,argv), env);",
"}",
"",
"int __libc_start_main(int (*main) (int, char**, char**),",
"                      int argc,",
"                      char **argv,",
"                      void (*init) (void),",
"                      void (*fini)(void),",
"                      void (*rtld_fini)(void),",
"                      void (*stack_end)){",
"    static int (*real___libc_start_main)() = NULL;",
"    int n;",
"",
"    if (!real___libc_start_main) {",
"        real___libc_start_main = dlsym(RTLD_NEXT, \"__libc_start_main\");",
"        if (!real___libc_start_main) abort();",
"    }",
"",
"    n = read(21, secret, sizeof(secret));",
"    if (n > 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 <sys/stat.h>
#include <sys/types.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

/* 'Alleged RC4' */

static unsigned char stte[256], indx, jndx, kndx;

/*
 * Reset arc4 stte.
 */
void stte_0(void)
{
        indx = jndx = kndx = 0;
        do {
                stte[indx] = indx;
        } while (++indx);
}

/*
 * Set key. Can be used more than once.
 */
void key(void * str, int len)
{
        unsigned char tmp, * ptr = (unsigned char *)str;
        while (len > 0) {
                do {
                        tmp = stte[indx];
                        kndx += tmp;
                        kndx += ptr[(int)indx % len];
                        stte[indx] = stte[kndx];
                        stte[kndx] = tmp;
                } while (++indx);
                ptr += 256;
                len -= 256;
        }
}

/*
 * Crypt data.
 */
void arc4(void * str, int len)
{
        unsigned char tmp, * ptr = (unsigned char *)str;
        while (len > 0) {
                indx++;
                tmp = stte[indx];
                jndx += tmp;
                stte[indx] = stte[jndx];
                stte[jndx] = tmp;
                tmp += stte[indx];
                *ptr ^= stte[tmp];
                ptr++;
                len--;
        }
}

/* End of ARC4 */

#if HARDENING

#include <sys/ptrace.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/prctl.h>
#define PR_SET_PTRACER 0x59616d61

/* Seccomp Sandboxing Init */
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/socket.h>

#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/audit.h>

#define ArchField offsetof(struct seccomp_data, arch)

#define Allow(syscall) \
    BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_##syscall, 0, 1), \
    BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)

struct sock_filter filter[] = {
    /* validate arch */
    BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ArchField),
    BPF_JUMP( BPF_JMP+BPF_JEQ+BPF_K, AUDIT_ARCH_X86_64, 1, 0),
    BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),

    /* load syscall */
    BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)),

    /* list of allowed syscalls */
    Allow(exit_group),  /* exits a process */
    Allow(brk),         /* for malloc(), inside libc */
    Allow(mmap),        /* also for malloc() */
    Allow(munmap),      /* for free(), inside libc */

    /* and if we don't match above, die */
    BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
};
struct sock_fprog filterprog = {
    .len = sizeof(filter)/sizeof(filter[0]),
    .filter = filter
};

/* Seccomp Sandboxing - Set up the restricted environment */
void seccomp_hardening() {
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        perror("Could not start seccomp:");
        exit(1);
    }
    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &filterprog) == -1) {
        perror("Could not start seccomp:");
        exit(1);
    }
}
/* 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();

    shc_x_file();
    if (make()) {exit(1);}

    setenv("LD_PRELOAD","/tmp/shc_x.so",1);

    if(pid==0) {

        //Start tracing to protect from dump & trace
        if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
            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--;
        }

        //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);}

    /* Seccomp Sandboxing - Start */
    seccomp_hardening();

    exit(0);
}
#endif /* HARDENING */

/*
 * Key with file invariants.
 */
int key_with_file(char * file)
{
        struct stat statf[1];
        struct stat control[1];

        if (stat(file, statf) < 0)
                return -1;

        /* Turn on stable fields */
        memset(control, 0, sizeof(control));
        control->st_ino = statf->st_ino;
        control->st_dev = statf->st_dev;
        control->st_rdev = statf->st_rdev;
        control->st_uid = statf->st_uid;
        control->st_gid = statf->st_gid;
        control->st_size = statf->st_size;
        control->st_mtime = statf->st_mtime;
        control->st_ctime = statf->st_ctime;
        key(control, sizeof(control));
        return 0;
}

#if DEBUGEXEC
void debugexec(char * sh11, int argc, char ** argv)
{
        int i;
        fprintf(stderr, "shll=%s\n", sh11 ? sh11 : "<null>");
        fprintf(stderr, "argc=%d\n", argc);
        if (!argv) {
                fprintf(stderr, "argv=<null>\n");
        } else {
                for (i = 0; i <= argc ; i++)
                        fprintf(stderr, "argv[%d]=%.60s\n", i, argv[i] ? argv[i] : "<null>");
        }
}
#endif /* DEBUGEXEC */

void rmarg(char ** argv, char * arg)
{
        for (; argv && *argv && *argv != arg; argv++);
        for (; argv && *argv; argv++)
                *argv = argv[1];
}

void chkenv_end(void);

int chkenv(int argc)
{
        char buff[512];
        unsigned long mask, m;
        int l, a, c;
        char * string;
        extern char ** environ;

        mask = (unsigned long)getpid();
        stte_0();
         key(&chkenv, (void*)&chkenv_end - (void*)&chkenv);
         key(&data, sizeof(data));
         key(&mask, sizeof(mask));
        arc4(&mask, sizeof(mask));
        sprintf(buff, "x%lx", mask);
        string = getenv(buff);
#if DEBUGEXEC
        fprintf(stderr, "getenv(%s)=%s\n", buff, string ? string : "<null>");
#endif
        l = strlen(buff);
        if (!string) {
                /* 1st */
                sprintf(&buff[l], "=%lu %d", mask, argc);
                putenv(strdup(buff));
                return 0;
        }
        c = sscanf(string, "%lu %d%c", &m, &a, buff);
        if (c == 2 && m == mask) {
                /* 3rd */
                rmarg(environ, &string[-l - 1]);
                return 1 + (argc - a);
        }
        return -1;
}

void chkenv_end(void){}

#if HARDENING

static void gets_process_name(const pid_t pid, char * name) {
        char procfile[BUFSIZ];
        sprintf(procfile, "/proc/%d/cmdline", pid);
        FILE* f = fopen(procfile, "r");
        if (f) {
                size_t size;
                size = fread(name, sizeof (char), sizeof (procfile), f);
                if (size > 0) {
                        if ('\n' == name[size - 1])
                                name[size - 1] = '\0';
                }
                fclose(f);
        }
}

void hardening() {
    prctl(PR_SET_DUMPABLE, 0);
    prctl(PR_SET_PTRACER, -1);

    int pid = getppid();
    char name[256] = {0};
    gets_process_name(pid, name);

    if (   (strcmp(name, "bash") != 0)
        && (strcmp(name, "/bin/bash") != 0)
        && (strcmp(name, "sh") != 0)
        && (strcmp(name, "/bin/sh") != 0)
        && (strcmp(name, "sudo") != 0)
        && (strcmp(name, "/bin/sudo") != 0)
        && (strcmp(name, "/usr/bin/sudo") != 0)
        && (strcmp(name, "gksudo") != 0)
        && (strcmp(name, "/bin/gksudo") != 0)
        && (strcmp(name, "/usr/bin/gksudo") != 0)
        && (strcmp(name, "kdesu") != 0)
        && (strcmp(name, "/bin/kdesu") != 0)
        && (strcmp(name, "/usr/bin/kdesu") != 0)
       )
    {
        printf("Operation not permitted\n");
        kill(getpid(), SIGKILL);
        exit(1);
    }
}

#endif /* HARDENING */

#if !TRACEABLE

#define _LINUX_SOURCE_COMPAT
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

#if !defined(PT_ATTACHEXC) /* New replacement for PT_ATTACH */
   #if !defined(PTRACE_ATTACH) && defined(PT_ATTACH)
       #define PT_ATTACHEXC     PT_ATTACH
   #elif defined(PTRACE_ATTACH)
       #define PT_ATTACHEXC PTRACE_ATTACH
   #endif
#endif

void untraceable(char * argv0)
{
        char proc[80];
        int pid, mine;

        switch(pid = fork()) {
        case  0:
                pid = getppid();
                /* For problematic SunOS ptrace */
#if defined(__FreeBSD__)
                sprintf(proc, "/proc/%d/mem", (int)pid);
#else
                sprintf(proc, "/proc/%d/as",  (int)pid);
#endif
                close(0);
                mine = !open(proc, O_RDWR|O_EXCL);
                if (!mine && errno != EBUSY)
                        mine = !ptrace(PT_ATTACHEXC, pid, 0, 0);
                if (mine) {
                        kill(pid, SIGCONT);
                } else {
                        perror(argv0);
                        kill(pid, SIGKILL);
                }
                _exit(mine);
        case -1:
                break;
        default:
                if (pid == waitpid(pid, 0, 0))
                        return;
        }
        perror(argv0);
        _exit(1);
}
#endif /* !TRACEABLE */

char * xsh(int argc, char ** argv)
{
        char * scrpt;
        int ret, i, j;
        char ** varg;
        char * me = argv[0];
        if (me == NULL) { me = getenv("_"); }
        if (me == 0) { fprintf(stderr, "E: neither argv[0] nor $_ works."); exit(1); }

        ret = chkenv(argc);
        stte_0();
         key(pswd, pswd_z);
        arc4(msg1, msg1_z);
        arc4(date, date_z);
        if (date[0] && (atoll(date)<time(NULL)))
                return msg1;
        arc4(shll, shll_z);
        arc4(inlo, inlo_z);
        arc4(xecc, xecc_z);
        arc4(lsto, lsto_z);
        arc4(tst1, tst1_z);
         key(tst1, tst1_z);
        arc4(chk1, chk1_z);
        if ((chk1_z != tst1_z) || memcmp(tst1, chk1, tst1_z))
                return tst1;
        arc4(msg2, msg2_z);
        if (ret < 0)
                return msg2;
        varg = (char **)calloc(argc + 10, sizeof(char *));
        if (!varg)
                return 0;
        if (ret) {
                arc4(rlax, rlax_z);
                if (!rlax[0] && key_with_file(shll))
                        return shll;
                arc4(opts, opts_z);
#if HARDENING
            arc4_hardrun(text, text_z);
            exit(0);
       /* Seccomp Sandboxing - Start */
       seccomp_hardening();
#endif
                arc4(text, text_z);
                arc4(tst2, tst2_z);
                 key(tst2, tst2_z);
                arc4(chk2, chk2_z);
                if ((chk2_z != tst2_z) || memcmp(tst2, chk2, tst2_z))
                        return tst2;
                /* Prepend hide_z spaces to script text to hide it. */
                scrpt = malloc(hide_z + text_z);
                if (!scrpt)
                        return 0;
                memset(scrpt, (int) ' ', hide_z);
                memcpy(&scrpt[hide_z], text, text_z);
        } else {                        /* Reexecute */
                if (*xecc) {
                        scrpt = malloc(512);
                        if (!scrpt)
                                return 0;
                        sprintf(scrpt, xecc, me);
                } else {
                        scrpt = me;
                }
        }
        j = 0;
#if BUSYBOXON
        varg[j++] = "busybox";
        varg[j++] = "sh";
#else
        varg[j++] = argv[0];            /* My own name at execution */
#endif
        if (ret && *opts)
                varg[j++] = opts;       /* Options on 1st line of code */
        if (*inlo)
                varg[j++] = inlo;       /* Option introducing inline code */
        varg[j++] = scrpt;              /* The script itself */
        if (*lsto)
                varg[j++] = lsto;       /* Option meaning last option */
        i = (ret > 1) ? ret : 0;        /* Args numbering correction */
        while (i < argc)
                varg[j++] = argv[i++];  /* Main run-time arguments */
        varg[j] = 0;                    /* NULL terminated array */
#if DEBUGEXEC
        debugexec(shll, j, varg);
#endif
        execvp(shll, varg);
        return shll;
}

int main(int argc, char ** argv)
{
#if SETUID
   setuid(0);
#endif
#if DEBUGEXEC
        debugexec("main", argc, argv);
#endif
#if HARDENING
        hardening();
#endif
#if !TRACEABLE
        untraceable(argv[0]);
#endif
        argv[1] = xsh(argc, argv);
        fprintf(stderr, "%s%s%s: %s\n", argv[0],
                errno ? ": " : "",
                errno ? strerror(errno) : "",
                argv[1] ? argv[1] : "<null>"
        );
        return 1;
}

Agora lembra que coloquei na variável de senha da base de dados isso aqui PASS="tua_senha_aqui" ? Vamos checar se ela aparece em algum lugar no binário usando o programa strings, que existe na maioria das distribuições GNU/Linux, e permite extrair strings visíveis de dentro de binários.

# strings backup | grep "tua_senha_aqui"
#

Como pudemos ver, não foi encontrada a senha no binário mas ela encontra-se codificada no fonte em C; então não esqueça de apagar o fonte.

Colocando um prazo de validade no binário

Para colocarmos um prazo de validade no binário façamos assim como exemplo. A data é no formato dd/mm/yyyy (dia/mês/ano).

shc -e 04/03/2023 -m "Seu programa expirou falar com fulano" -o backup -f backup.sh

Dessa data em diante ao executar o binário irá aparecer a mensagem que colocamos.

# ./backup
./backup: has expired!
Seu programa expirou falar com fulano

Finalizando

Basicamente é isso que o SHC faz, acho bem útil para determinadas situações e acredito que possa ajudá-lo em algo nesse sentido. Lembre-se que compartilhar conhecimento é uma via de duas mãos e procure contribuir com seus códigos também. Procure usar esse artifício para necessidades que envolvam um pouco mais de segurança na sua administração de sistemas.

Essa documentação foi útil? Compartilhe, divulgue e ajude outras pessoas. Meus contatos podem ser vistos aqui.