Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
dconstruct — Um desmontador & decompilador experimental para scripts TLOU2 DC. | Kitploit
Ferramentas/GitHubGitHub/deepquantum/dconstruct
Análise EstáticaEngenharia ReversaDepuradoresAnálise de BináriosAnálise de Firmware
GitHubdeepquantum/dconstruct

dconstruct

Um desmontador & decompilador experimental para scripts TLOU2 DC.

Ver Repositório
232há 15 diasRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

Version License: CC BY-NC-ND 4.0

dconstruct

Animação completa de desmontagem e descompilação

Abrir o MP4 de origem

dconstruct é uma ferramenta de engenharia reversa para os arquivos DC-Script usados em The Last of Us Part II. Possui um desmontador e um descompilador.

Ele gera arquivos .asm contendo as estruturas desmontadas e bytecode, bem como arquivos .dcpl (DC Pseudo Language) contendo pseudo-código semelhante a C.

Você também pode fazer edições nos arquivos via linha de comando, incluindo a substituição de estruturas inteiras com pouco esforço. Isso torna extremamente fácil criar mods que simplesmente alteram alguns valores dentro dos arquivos .bin.

Principais funcionalidades

  • Otimizado para velocidade. A desmontagem e descompilação de arquivos são extremamente rápidas.
  • Reconstrução precisa do código-fonte original, especialmente o fluxo de controle.
  • Interpretação automática precisa de todas as estruturas na desmontagem.
  • Desmontagem e descompilação de vários arquivos ao mesmo tempo. Descompilar cada arquivo .bin do jogo leva apenas alguns segundos.
  • Fazer edições via a flag -e, criando novos arquivos que você pode usar para mods.
  • Carregar sidbases personalizados para usar na desmontagem.

Como usar

Primeiro, é recomendado que você mova o diretório dconstruct descompactado para algum local seguro, como C:\Program Files.

Para tornar o dconstruct o mais fácil de usar possível, é recomendado que você adicione o diretório .\bin dentro da pasta dconstruct ao seu PATH. Você pode saber mais aqui, ou seguir estes passos rápidos:

  • Vá na barra de pesquisa do Windows e digite "variáveis de ambiente", você deve obter uma opção que diz "Editar as variáveis de ambiente do sistema".
  • Após selecionar essa opção, você deve obter uma janela com o título "Propriedades do sistema". Acima dos botões "Ok", "Cancelar" e "Aplicar", você deve ver um botão que diz "Variáveis de Ambiente...".
  • Após clicar neste botão, outra janela deve aparecer. Aqui, vá para a segunda tabela (intitulada "Variáveis do sistema") e encontre a entrada com o nome da variável "Path". Clique duas vezes nela.
  • Nesta caixa de diálogo, selecione a opção "Novo" à direita. Agora cole o caminho para o diretório .\bin. Deve se parecer com algo assim:

a

  • Certifique-se de que seu caminho termina em "\bin" e NÃO "\dconstruct".
  • Clique em 'OK' em todas as caixas de diálogo abertas.
  • Para verificar se funcionou, abra um novo prompt de comando e digite dconstruct --about. Você deve ver alguma saída do programa e nenhuma mensagem de erro.

Execute um comando como este na linha de comando para gerar seu primeiro arquivo desmontado:```shell dconstruct my_bin_file.bin

root@kitploit:~
Isto irá então gerar um ficheiro chamado `my_bin_file.bin.asm` no mesmo diretório que o seu ficheiro de entrada. Pode então abrir esse ficheiro usando um editor de texto/código. Recomendo usar algo como VSCode que oferece funcionalidades avançadas de pesquisa e é bom a lidar com ficheiros grandes. O bloco de notas padrão do Windows não é recomendado.

Para descompilar um ficheiro, adicione a flag `--decompile` ao executar o comando.

# Argumentos da linha de comandos

- `-i` - ficheiro ou pasta de entrada. Pode ser omitido se for passado o caminho de entrada como primeiro argumento.

- `-o` - caminho de saída. Se o seu caminho de entrada for uma pasta, este não pode ser um ficheiro. Se não for especificada uma saída, o ficheiro .txt será colocado junto ao ficheiro de entrada. Se a entrada for uma pasta e não for especificada uma saída, o programa criará um diretório "output" no diretório de trabalho atual e colocará todos os ficheiros lá.

- A sidbase é carregada de `sidbase.bin` localizado junto ao executável.

- `--no_decompile` - não emite código pseudo decompilado para um ficheiro .dcpl. O ficheiro será colocado junto ao ficheiro .asm. Isto é falso por predefinição.

- `--no_optimize` - não otimiza e limpa o código dcpl. envolve a inlining de chamadas de funções, remoção de variáveis não utilizadas, transformação de loops for compatíveis em loops foreach e transformação de algumas cadeias if-else em expressões match.

- `--pascal_case` - converte os nomes das funções dos jogos para pascal case na saída dcpl, por exemplo, get-boolean -> GetBoolean.

- `--graphs` - emite ficheiros .svg contendo grafos de fluxo de controlo para todas as funções descompiladas. Cada ficheiro .bin tem a sua própria pasta contendo todos os seus grafos. Isto **significativamente** atrasa a velocidade de descompilação, por isso não é recomendado quando se descompila um grande número de ficheiros ao mesmo tempo.

- `--emit_once` - proíbe que a mesma estrutura seja emitida duas vezes na desmontagem. Se uma estrutura aparecer múltiplas vezes, apenas a primeira instância será totalmente emitida, e todas as outras ocasiões serão substituídas por uma tag `ALREADY_EMITTED`. Isto pode reduzir significativamente o tamanho do ficheiro.

- `-e` - faz uma edição. Mais informações na secção abaixo.

- `--edit_file` - fornece um ficheiro de edição. um ficheiro de edição contém uma edição por linha. usa a mesma sintaxe que a flag -e.

# O que é um desassemblador?

Um [desassemblador](https://en.wikipedia.org/wiki/Disassembler) é uma ferramenta que lê instruções binárias (também conhecido como [bytecode](https://en.wikipedia.org/wiki/Bytecode) ou [código de máquina](https://en.wikipedia.org/wiki/Machine_code)) e traduz cada uma numa versão legível por humanos chamada de [mnemónico](https://en.wikipedia.org/wiki/Assembly_language#Mnemonics). Os desassembladores geralmente não tentam interpretar muito sobre o significado destas instruções e apenas as transformam 1-1 nas suas versões legíveis. Por exemplo, as instruções:```arm
15 00 00 00
4A 01 01 00
43 31 01 00
1C 00 00 01

são desmontados nas seguintes versões legíveis por humanos:```arm LookupPointer r0, 0 LoadStaticU64Imm r1, 1 Move r49, r1 CallFf r0, r0, 1

root@kitploit:~
Todos os números no bytecode são escritos em [hexadecimal](https://en.wikipedia.org/wiki/hexadecimal). A primeira coluna em cada linha representa o `opcode`, ou o tipo de instrução a ser executada. A próxima coluna é o registo de destino, onde o resultado da operação será armazenado. As duas últimas colunas são os operandos 1 e 2, que são registos ou números literais sobre os quais a operação será realizada. Nem todas as instruções usam todos os 4 bytes; por exemplo, a primeira instrução `LookupPointer` precisa apenas de um operando.

O desmontador dconstruct também adiciona algumas informações adicionais destinadas a tornar a leitura das instruções um pouco mais fácil. Ele também insere rótulos (e.g. `L_0`) para tornar mais fácil rastrear a ramificação no código.```arm
15 00 00 00   LookupPointer        r0, 0         r0 = ST[0] -> <is-player-abby?>
4A 01 01 00   LoadStaticU64Imm     r1, 1         r1 = ST[1] -> <player>
43 31 01 00   Move                 r49, r1       r49 = player
1C 00 00 01   CallFf               r0, r0, 1     r0 = is-player-abby?(player)
2F 0D 00 00   BranchIfNot          r0, 0xD       IF NOT r0 => L_0

Isso é útil quando você deseja visualizar o conteúdo bruto do arquivo sem que o programa faça muitas suposições. Mas pode ser difícil de ler para grandes blocos de código, pois não há estrutura alguma. É aí que entra um descompilador.

O que é um descompilador?

Um descompilador é o inverso de um compilador. Um compilador é um programa que recebe código escrito por humanos (como C, Java, C++, ...) e produz instruções de máquina. No caso de TLOU2 e muitos outros jogos da ND, a linguagem de script usada é chamada 'DC', que é basicamente uma versão da linguagem de programação Racket, e a "máquina" é o próprio jogo que executa as instruções enquanto o jogo está rodando. Essencialmente, os programadores escrevem DC e usam um compilador para transformar esse código nos arquivos .bin que são enviados com o jogo.

Um descompilador pega o código desmontado acima e produz o que é conhecido como pseudocódigo. Pseudocódigo é uma tentativa de reconstruir o código-fonte original que foi usado para gerar as instruções brutas. Isso tem como objetivo tornar a compreensão do código significativamente mais fácil, no entanto, o processo de geração de pseudocódigo é bastante complexo, pois existem muitas versões diferentes de código-fonte que podem gerar o bytecode final, além de otimizações que ocorrem durante a compilação.

Atualmente, a saída do descompilador dconstruct não é sintaticamente semelhante ao DC original. DC (ou seja, Racket) é uma linguagem de programação funcional com uma sintaxe única que é f*cking ilegível para programadores que não estão acostumados com ela. Por esse motivo, escolhi fazer o pseudocódigo se parecer mais com C por enquanto, o que deve ser mais fácil de ler para a maioria das pessoas. No entanto, está planejada a criação de mais sintaxes, incluindo Racket e uma versão em Python.

Exemplos

A função sqrt-sign()

Bytes originais```arm

43 00 31 00 15 01 00 00 43 02 00 00 43 31 02 00 1B 01 01 01 43 02 00 00 40 03 01 00 24 02 02 03 2F 0B 02 00 40 02 02 00 2D 0C 00 00 40 02 03 00 43 03 02 00 15 04 04 00 43 05 01 00 43 31 05 00 1C 04 04 01 07 03 03 04 43 01 03 00 00 01 01 00

root@kitploit:~
A partir disso, é virtualmente impossível saber o que o código está fazendo.

## Código desmontado com rótulos e tabela de símbolos```arm
sqrt-sign = script-lambda [0x9A8D8] {
    [1 args]
    0000   0x09A928   43 00 31 00   Move                 r0, r49       r0 = arg_0
    0001   0x09A930   15 01 00 00   LookupPointer        r1, 0         r1 = ST[0] -> <absf>
    0002   0x09A938   43 02 00 00   Move                 r2, r0        r2 = arg_0
    0003   0x09A940   43 31 02 00   Move                 r49, r2       r49 = arg_0
    0004   0x09A948   1B 01 01 01   Call                 r1, r1, 1     r1 = absf(arg_0)
    0005   0x09A950   43 02 00 00   Move                 r2, r0        r2 = arg_0
    0006   0x09A958   40 03 01 00   LoadStaticFloatImm   r3, 1         r3 = ST[1] -> <0.000000>
    0007   0x09A960   24 02 02 03   FGreaterThanEqual    r2, r2, r3    r2 = r2 >= r3
    0008   0x09A968   2F 0B 02 00   BranchIfNot          r2, 0xB       IF NOT r2 => L_0
    0009   0x09A970   40 02 02 00   LoadStaticFloatImm   r2, 2         r2 = ST[2] -> <1.000000>
    000A   0x09A978   2D 0C 00 00   Branch               0xC           GOTO => L_1
  L_0:
    000B   0x09A980   40 02 03 00   LoadStaticFloatImm   r2, 3         r2 = ST[3] -> <-1.000000>
  L_1:
    000C   0x09A988   43 03 02 00   Move                 r3, r2        r3 = -1.000000
    000D   0x09A990   15 04 04 00   LookupPointer        r4, 4         r4 = ST[4] -> <sqrt>
    000E   0x09A998   43 05 01 00   Move                 r5, r1        r5 = RET_absf
    000F   0x09A9A0   43 31 05 00   Move                 r49, r5       r49 = RET_absf
    0010   0x09A9A8   1C 04 04 01   CallFf               r4, r4, 1     r4 = sqrt(RET_absf)
    0011   0x09A9B0   07 03 03 04   FMul                 r3, r3, r4    -1.000000 = -1.000000 * RET_sqrt
    0012   0x09A9B8   43 01 03 00   Move                 r1, r3        r1 = -1.000000
    0013   0x09A9C0   00 01 01 00   Return               r1            Return

    SYMBOL TABLE:
    0000   0x09A9C8    function: absf
    0001   0x09A9D0    float: 0.000000
    0002   0x09A9D8    float: 1.000000
    0003   0x09A9E0    float: -1.000000
    0004   0x09A9E8    function: sqrt
}

O código agora é muito mais legível, mas mesmo o único branch é irritante de ler se você não está acostumado a ler assembly.

Grafo de fluxo de controle

Sem entrar em muitos detalhes aqui, um Grafo de Fluxo de Controle (CFG) divide o código assembly em "nós" ao longo das várias instruções de branch. Isso é fundamental quando analisamos o código para descobrir onde o "fluxo" do programa pode divergir em diferentes caminhos, o que pode exigir que emitamos variáveis, instruções if, loops for, etc.. Esses gráficos precisam ser gerados em segundo plano, mas você pode imprimi-los em imagens usando a flag --graphs do programa.

Código pseudo final```rust

u64? sqrt-sign(f32 arg_0) { f32 var_1; if (arg_0 >= 0.00) { var_1 = 1.00; } else { var_1 = -1.00; } return var_1 * sqrt(absf(arg_0)); }

root@kitploit:~
O propósito da função está agora muito claro: obtemos o valor absoluto do argumento, extraímos a raiz quadrada desse valor e depois multiplicamos pelo sinal original do argumento. Por exemplo, `sqrt-sign(-9) = -3`.

## Passos de otimização

O dconstruct aplica automaticamente passos de otimização ao pseudo-código. Aqui estão alguns exemplos:

### Inline de chamada de função

#### Antes```c
u64? set-arrow-explosive-handle-rootvars() {
    u64? var_0 = get-uint64(fx-handle, self);
    u64? var_1 = get-float(kill, self);
    set-effect-float(var_0, killradius, var_1);
    u64? var_2 = get-uint64(fx-handle, self);
    u64? var_3 = get-float(strong, self);
    set-effect-float(var_2, strongradius, var_3);
    u64? var_4 = get-uint64(fx-handle, self);
    u64? var_5 = get-float(weak, self);
    u64? var_6 = set-effect-float(var_4, weakradius, var_5);
    return var_6;
}

Depois```c

u64? set-arrow-explosive-handle-rootvars() { set-effect-float(get-uint64(fx-handle, self), killradius, get-float(kill, self)); set-effect-float(get-uint64(fx-handle, self), strongradius, get-float(strong, self)); return set-effect-float(get-uint64(fx-handle, self), weakradius, get-float(weak, self)); }

root@kitploit:~
### Laços foreach

### Antes```c#
u64? bmm-deactivate-all(u64? arg_0) {
    u64? var_0 = darray-count(arg_0);
    begin-foreach();
    for (u64 i = 0; i < var_0; i++) {
        u64? var_1 = darray-at(arg_0, i);
        u16 var_2;
        if (var_1 && *(u16*)(var_1 + 12) == 7) {
            var_2 = *(u64*)var_1;
        } else if (var_1 && *(u16*)(var_1 + 12) == 5) {
            var_2 = *(u64*)var_1;
        } else if (var_1 && *(u16*)(var_1 + 12) == 4) {
            var_2 = *(u64*)var_1;
        } else {
            var_2 = 0;
        }
        net-send-event-all(deactivate, var_2);
    }
    u64? var_3 = end-foreach();
    return var_3;
}

Depois```c#

u64? bmm-deactivate-all(u64? arg_0) { foreach (u64? var_1 : arg_0) { u16 var_2; if (var_1 && (u16)(var_1 + 12) == 7) { var_2 = (u64)var_1; } else if (var_1 && (u16)(var_1 + 12) == 5) { var_2 = (u64)var_1; } else if (var_1 && (u16)(var_1 + 12) == 4) { var_2 = (u64)var_1; } else { var_2 = 0; } net-send-event-all(deactivate, var_2); } }

root@kitploit:~
### Expressões de correspondência

### Antes```scala
string #C57EE0A64537AE8F(u16 arg_0) {
    string var_0;
    if (arg_0 == 0) {
        var_0 = "Militia";
    } else if (arg_0 == 1) {
        var_0 = "Scars";
    } else if (arg_0 == 2) {
        var_0 = "Rattlers";
    } else if (arg_0 == 3) {
        var_0 = "Infected";
    } else if (arg_0 == 4) {
        var_0 = "Max Num Factions";
    } else {
        var_0 = "Invalid";
    }
    return var_0;
}

Após```scala

string #C57EE0A64537AE8F(u16 arg_0) { return match (arg_0) { 0 -> "Militia" 1 -> "Scars" 2 -> "Rattlers" 3 -> "Infected" 4 -> "Max Num Factions" else -> "Invalid" }; }

root@kitploit:~
## Exemplo de uma estrutura desmontada```c
*ellie-weapons* = symbol-array [0x00190] {
  [0] int: 6
  [1] int: 0
  [2] array [0x198] {size: 6} {
    [0] anonymous struct [0x780] {
      [0] sid: pistol-beretta
    }
    [1] anonymous struct [0x788] {
      [0] sid: pistol-revolver-taurus
    }
    [2] anonymous struct [0x790] {
      [0] sid: rifle-remington-bolt
    }
    [3] anonymous struct [0x798] {
      [0] sid: bow-ellie
    }
    [4] anonymous struct [0x7a0] {
      [0] sid: shotgun-remington-pump
    }
    [5] anonymous struct [0x7a8] {
      [0] sid: rifle-mpx5
    }
  }
}

Edição

Editando arquivos DC usando a flag -e

Você pode usar a flag -e para aplicar edições a arquivos DC. Essas edições são salvas em uma nova cópia do arquivo original, deixando o original intocado. Várias flags -e podem ser especificadas ao mesmo tempo para fazer várias edições de uma vez.

Alternativamente, você pode fornecer ao programa um caminho para um arquivo de edição. Um arquivo de edição contém uma edição por linha. Ele usa a mesma sintaxe da flag -e, mas deve ser um pouco mais fácil de usar se você quiser aplicar várias edições de uma vez.

A edição ocorre antes da desmontagem e descompilação, então a edição aparecerá nos arquivos gerados.

Sintaxe para Edições

Cada edição segue esta sintaxe:```xml

[]= ``` - ``: O endereço de memória da estrutura que você deseja editar (em hexadecimal, começando com `0x`. É mais fácil copiar e colar de uma versão desmontada do arquivo que você deseja editar). - ``: O índice da variável membro dentro da estrutura. Equivalente ao número que você pode ver à esquerda do membro. - ``: O novo valor a ser atribuído a esse membro. Deve ter o mesmo tamanho. (ints e floats têm tamanho 4, sids/structs têm tamanho 8). O programa NÃO verificará se as estruturas são do mesmo tipo.

Exemplo

Suponha que você tenha uma estrutura como esta:```c++ [4] firearm-gameplay-def [0x11C28] { [0] float 0.7 // might represent the rate of fire, so i want to lower it for my mod ... }

root@kitploit:~
Para substituir a primeira variável membro (índice 0) pelo valor float 0.5, o comando de edição seria:

`-e 0x11C28[0]=0.5`

A estrutura que queremos editar está em `0x11C28`, e queremos a primeira variável membro (o 0 à esquerda do float). Em seguida, colocamos o novo valor após o `=`, 0.5 neste caso. Se a edição for bem-sucedida, o programa mostrará uma mensagem indicando que o valor foi alterado de `0.7->0.5`.

Para um arquivo de edição, simplesmente remova o `-e` e coloque uma edição por linha:

### edit_file.txt

0x11C28[0]=0.5

0x11C28[1]=0.2

...

## Tipos de Variáveis Membro

As estruturas podem ter diferentes tipos de variáveis membro:

- `float` - Especifique valores decimais com um ponto (ex.: 0.5).

- `int` - Especifique valores inteiros sem ponto (ex.: 42).

- `sid` (identificador de string) - (mais informações abaixo)

- `string` - atualmente não suportado para substituição

- `structure` - substituindo um ponteiro (mais informações abaixo)

### Substituindo sid por pesquisa de nome:

`-e 0xABC[5]=ellie`

Isso procura o valor "ellie" no sidbase atual. Se não existir, um aviso é emitido e nenhuma edição é aplicada. Se o valor for encontrado, o valor hash real (um número grande) substituirá o valor atual na variável membro.

### Substituindo sid por substituição manual direta de hash:

`-e 0xABC[5]=#XXXXXXXXXXXXXXXX`

O # indica um valor hash bruto, que será aplicado diretamente sem pesquisa.

### Substituindo estruturas membro

Se uma estrutura contém outra estrutura como membro, você pode substituir toda a estrutura membro atribuindo a ela o endereço de outra estrutura.

Por exemplo, suponha que você tenha o seguinte:```c++
[4] weapon-gameplay-def [0x0C523] {
    ...
    [7] firearm-gameplay-def [0x11C28] {
        ...
    }
}

Portanto, weapon-gameplay-def contém um firearm-gameplay-def. Para substituir o firearm-gameplay-def dentro do weapon-gameplay-def por um firearm-gameplay-def diferente localizado no endereço 0x0ABC, a edição será:

-e 0x11C28[7]=0x0ABC

Extensão de linguagem DCPL para VS Code

O VS Code suporta a criação de extensões personalizadas para adicionar realce de sintaxe a linguagens personalizadas. O dconstruct vem com um arquivo .vsix que adiciona esse suporte para a extensão de arquivo .dcpl. Por ser uma linguagem de uso único não realmente destinada à programação do dia a dia, não estou enviando a extensão para o marketplace e, em vez disso, a estou distribuindo como um arquivo .vsix bruto. Para instalar esta extensão no seu VS Code, execute o seguinte comando:```shell code --install-extension <path/to/extension/dcpl-lint-0.0.1.vsix>

root@kitploit:~
ou abra a paleta de comandos com CTRL+SHIFT+P e digite "Instalar extensão via VSIX" e selecione o arquivo .vsix.

Após isso, seu código .dcpl deve ficar algo assim:

![dcpl_code](https://assets.kitploit.com/production/public/readmes/13048/8b4ab26ab7952a91a015d1376d3101bcad17c65602ed9c2b5c1587cb1d1a9f3c.png)

# Problemas conhecidos

O descompilador atualmente não está 100% completo e, portanto, está em um estado "experimental". Se você receber avisos durante a descompilação, não se preocupe, pois essas funções não são suportadas atualmente, mas esperançosamente serão no futuro. Junto com estas, há mais problemas conhecidos no momento:

- funções de expressão única com curto-circuito pesado (particularmente aquelas dentro de structs) ainda não foram implementadas. Comecei a trabalhar no algoritmo para estas, mas não sei quanto tempo levará para terminar, embora isso esteja no topo da lista de prioridades.
- certos tipos estão incorretos, particularmente tipos de argumentos.
- blocos if vazios em instruções if/else podem causar indentação estranha. isso novamente não é sempre minha culpa, pois existem certos ramos que na verdade não fazem nenhum trabalho real, o que é difícil de detectar.

Junto com estes, há alguns problemas que provavelmente não serão corrigidos:

- retornar lixo quando não se sabe se uma função é void ou não
- toneladas de código redundante

# Funcionalidades planejadas

- um formato de saída completo em Racket e Python

# Agradecimentos especiais

- **icemesh** – por fornecer as [estruturas subjacentes para os arquivos DC](https://github.com/icemesh/dc/tree/main/t2) e [seu desmontador](https://github.com/icemesh/t2-dc-disasm), que serviu amplamente como inspiração.

- **Specilizer** – por sua DC-Tool, também uma inspiração para este programa.

- **uxh** – por conhecimento em scripting.

- **bigdragon** & **Wedge** por testes beta

- Toda a comunidade de modding no Discord – por serem amigáveis e prestativos.

## Suporte

Todas as minhas ferramentas e mods sempre serão 100% gratuitos, mas programas como este exigem muito trabalho.

Se você gostaria de me apoiar, pode visitar meu Ko-fi:

[![Ko-fi](https://img.shields.io/badge/Donate-Ko--fi-ff5f5f.svg)](https://ko-fi.com/deepquantum)

## Licença

Os arquivos que você criar usando este mod são inteiramente seus e você é livre para fazer com eles o que quiser. Créditos seriam apreciados, mas não são estritamente exigidos.

O programa em si está licenciado sob a
[Licença Creative Commons Atribuição-NãoComercial-SemDerivações 4.0 Internacional](https://creativecommons.org/licenses/by-nc-nd/4.0/).

Isso significa que você tem permissão para compartilhar o programa com outras pessoas, desde que dê créditos, mas atualmente não tem permissão para modificá-lo nem monetizá-lo.
Baixar ferramenta