2

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...
1

Como já deu para notar, eu gosto de inventar linguagens.

Cara,
Eu fiquei com a impressão de que você gosta mesmo é de escrever código assembly. Eu não entendo quase nada de assembly mas imagino que nesses casos o interessante mesmo foi 'maximizar performance' e 'economizar recurso de hardware'.

Eu me interesso por assembly a muito tempo mas acho difícil o 'acesso inicial'. Eu me sinto sem saber como começar.

Eu mantenho um projeto procedimentos (link no perfil) e aproveito essa oportunidade para te convidar a enviar um pull request / colaboração open source. Os procedimentos no caso seriam 'como proceder para iniciar com assembly no windows' ou algo como 'como misturar linguagem bat e assembly'.

2

Nossa, naquela época eu era viciado em programar em assembly. Eu programava alguma coisa em assembly praticamente todo dia. Mas faz muito tempo que não faço nada diretamente em assembly.

Eu me interesso por assembly a muito tempo mas acho difícil o 'acesso inicial'. Eu me sinto sem saber como começar.

Eu escrevi um livro gratuito de assembly x86-64 para a Mente Binária: https://mentebinaria.gitbook.io/assembly

Também já fiz uma apresentação de introdução ao baixo nível, que dá uma boa visão geral de arquitetura de processadores: https://www.youtube.com/watch?v=E7TEz60UA90

Se tiver interesse em aprender, creio que estes materiais irão lhe ajudar.