Compilando Bash: mudanças entre as edições
Sem resumo de edição |
Sem resumo de edição |
||
Linha 13: | Linha 13: | ||
* O binário fica bem maior que o seu arquivo shell script. | * 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. | * 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. | ||
<br><br><br><br><br> | <br><br><br><br><br><br><br><br> | ||
== Instalação == | == 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. | 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. |
Edição das 15h00min de 5 de fevereiro de 2023
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.