0

Sim, eu faço gambiarras em shellscript

Isso não é um conteúdo educativo, só quero compartilhar uma das coisas que eu sempre gostei de fazer: gambiarras em shellscript.

Essa paixão começou no Batch - shellscript do Windows, aquele arcaico que veio antes do Powershell. Batch era bastante limitado e até coisas simples, como printar um texto colorido, exigia fazer gambiarras. Hoje em dia eu uso Linux e faço gambiarras em Bash.

Vou falar abaixo de algumas das gambiarras que eu mais gostei de fazer (o que não significa que sejam bem feitas).

Superset de Batch

Obs.: Eu excluí esse projeto há muitos anos atrás.

Em 2016 eu desenvolvi um superset de Batch, cujo o crime está eternamente registrado no batch-satti: https://batch-satti.forumeiros.com/t3382-projeto-batch-construct-compilador-batch

O superset permitia escrever códigos como este:

#include "io.bat"

:start
    printc 0A "Ola " 09 "mundo!" \n
    #quit

E o resultado era um texto colorido impresso na tela:

Ou esse outro troço feio aqui:

#declare sqr

:start
    echo Resultado: {sqr 9} >tst.txt
    
    echo O conteudo do arquivo tst.txt^> $(type tst.txt)
    #quit

:sqr
    #return {(%~1)*(%~1)}

Que resultava nisso:

O objetivo do projeto era simples: converter arquivos .bat em arquivos executáveis, só que com recursos extras (daí o motivo de ter virado um superset).

Era um projeto mal feito, mas a parte mais interessante é que o executável de saída tinha apenas 3 KB. Pois eu não criava um auto extrator como outros projetos semelhantes faziam, eu montava o executável do zero em assembly usando o FASM.

Outra coisa interessante é que o superset permitia executar Powershell entre as diretivas #ps e #endps. O que não deveria ser possível, pois por motivos de segurança o Windows bloqueia a execução de scripts Powershell. Mas na época eu bolei um jeito de fazer bypass nisso e conseguia rodar o script sem precisar ter a execução de scripts Powershell liberada no sistema do usuário.

Tudo na base da mais pura gambiarra. O texto colorido era impresso com uma gambiarra usando findstr, o Powershell era executado usando uma gambiarra para dar bypass na restrição de segurança, o próprio código do projeto compilava o superset para Batch usando a mais pura gambiarra (eu não tinha muita experiência escrevendo compiladores na época). E depois gerava um executável pequeno gambiarrado em assembly.

Não vou mentir, foi legal fazer esse projeto e brincar de escrever executáveis em um Batch tunado. :D

DSL em Bash

Ferramentas para templates de arquivos de texto é bem comum... Mas e que tal uma ferramenta para templates de arquivos binário? Para suprir essa ideia nonsense que eu fiz uma DSL (Domain-Specific Language) implementada em Bash. O script pode ser lido aqui: https://github.com/Silva97/cli-tools/blob/master/new

Como já deu para notar, eu gosto de inventar linguagens. Por mais esquisito e sem utilidade que seja, meu script Bash consegue interpretar um código como o abaixo e gerar um binário ELF a partir dele:

if .out == "/dev/stdout"
    error "Please specifie 'out' file. This is a binary file not text."
    help
endif

set max = "2048"
set max = .max    # Maximum size of the file


## ELF header ##
x    7f 45 4c 46 # Magic number
x    02          # Class
x    01          # Data
x    01          # Version
x    01          # OS ABI
x    00          # ABI Version
dump 7           # Reserved


b16 2          # Type
b16 0x3e       # Machine
b32 1          # Version
b64 0x401078   # Entry point
b64 64         # Program header offset
b64 0xffffffff # Section header offset
b32 0          # Flags
b16 64         # ELF header size
b16 56         # Program header entry size
b16 1          # Program header count
b16 64         # Section header entry size
b16 2          # Section header count
b16 1          # Section header strtab section index

## Program header ##

# Entry 0
b32 1          # Type (load)
b32 7          # Flags (0b111 = RWX)
b64 0          # Offset
b64 0x401000   # Virtual address
b64 0x401000   # Physical address
b64 $max       # In file size
b64 $max       # In memory size
b64 0          # Alignment



## Code ##
align 120


if .file
    file .file
elif .code
    str .code
    x 90              # NOP
    x b8 3c 00 00 00  # mov eax, 60
    x 31 ff           # xor edi, edi
    x 0f 05           # syscall
else
    error "Please specifie a 'file' or 'code' option."
    help
endif

if $size > $max
    error "Maximum size exceeded."
    help
endif

O binário resultante é propositalmente capado para ficar bem pequeno. Um hello world como este:

org  0x401078
bits 64

mov rax, 1
mov rdi, 1
mov rsi, txt
mov rdx, TSIZE
syscall

mov rax, 60
xor rdi, rdi
syscall

txt:  db  `Hello World!\n\0`
TSIZE equ $-txt

Pode ser inserido em um binário ELF assim:

$ nasm hello.asm -o hello
$ new bin-elf64 file=hello out=test

E o arquivo binário test de saída seria um ELF de apenas 171 bytes de tamanho.


Também já fiz outras gambiarras interessantes, mas que prefiro não mostrar. Como o valva, que era um projeto de gerenciador de pacotes para Bash... Feito em Bash. Incluindo ferramentas de build e execução de testes.

Vocês já fizeram projetos malucos assim em shellscript? Estou curioso para saber das gambiarras da galera. Compartilha aí nos comentários. :D

Carregando publicação patrocinada...