Compilando Shell Scripts com o SHC
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.