Pular para o conteúdo

Testei a clonagem por IA… e é muito pior do que você imagina!

Ver no idioma original →

Autoria: Dave's Garage · Assistir no YouTube

Vídeo de autoria do canal indicado, não da IANIA; todos os direitos pertencem ao criador. Transcrição, resumo e tradução gerados automaticamente; o conteúdo no idioma original é preservado na versão em idioma original.

Idioma original: inglês

Vídeo original: I Tested AI Cloning… and It’s Way Worse Than You Think! · Canal: Dave’s Garage · 20:40 · Assistir no YouTube

Tópicos: Cibersegurança e segurança de software, Engenharia de software com IA, Governança e regulação de IA

Dave Plummer demonstra como usou Ghidra e IA para analisar o executável do Windows Calculator e gerar uma reconstrução funcional em Rust, sem fornecer os arquivos de código-fonte. Ele ressalta que o resultado parece funcionar, mas não foi comprovado como perfeitamente equivalente ao original. Em seguida, discute as implicações éticas e jurídicas de usar um aplicativo existente para criar um substituto, distinguindo uma nova implementação independente de uma reconstrução derivada. Sua conclusão é que mudar a linguagem de programação não apaga a contribuição do software original, embora a legalidade dependa dos elementos copiados e das circunstâncias.

  • O experimento parte do executável do Windows Calculator e usa Ghidra para analisar suas funções e produzir informações que a IA traduz em uma implementação em Rust.
  • A análise de um binário não recupera o código-fonte original, os nomes das variáveis nem os comentários, mas pode revelar parte da lógica e do comportamento do programa.
  • A IA gerou uma calculadora funcional e testes, mas a demonstração não comprova equivalência completa em todos os casos.
  • Uma implementação em outra linguagem não é automaticamente independente: a origem e o processo usado para produzir o novo programa também importam.
  • O direito autoral dos EUA não protege toda função ou método de operação; a análise jurídica precisa distinguir elementos funcionais de expressão protegida.
  • Casos como Sega versus Accolade e Sony versus Connectix mostram que certos usos de engenharia reversa foram considerados permitidos, mas não concedem autorização geral para clonar produtos comerciais.
  • A engenharia de sala limpa pode produzir implementações compatíveis sem copiar a implementação original, embora documentar produtos grandes dessa forma possa exigir muito trabalho.
  • Plummer diferencia projetar um produto a partir de requisitos próprios de usar o binário de outro aplicativo como matéria-prima para criar um substituto.
  • A reconstrução assistida por IA pode ser útil para recuperar software próprio ou migrá-lo, mas levanta outras preocupações quando feita sem autorização.
  • O apresentador defende que um clone derivado seja reconhecido como tal e afirma que compilar o resultado não certifica autoria independente.
Início Capítulo Resumo
00:00 O experimento de reconstrução do Windows Calculator Dave apresenta a proposta de analisar um executável sem código-fonte e reconstruir seu comportamento em Rust, usando a calculadora do Windows como teste.
05:39 Da análise do binário à calculadora em Rust Ele mostra o prompt e o processo de análise com Ghidra, os testes gerados pela IA e a aplicação reconstruída, observando que o resultado ainda não prova equivalência perfeita.
10:19 Código novo não significa autoria independente O vídeo explica o que se perde na compilação e por que traduzir a lógica de um executável para outra linguagem não elimina sua relação com o programa original.
16:00 Licenças, requisitos e responsabilidade Dave discute as ressalvas sobre a licença do Calculator, diferencia requisitos próprios de uma reconstrução derivada e argumenta que clones devem reconhecer sua origem.
19:06 Usos possíveis e conclusão sobre clonagem por IA Ele pondera os usos legítimos da técnica para recuperar ou migrar software e conclui que a mudança de linguagem não apaga a contribuição do aplicativo original.

Agora temos uma aplicação funcional em Rust e uma aproximação bastante próxima da calculadora. — 08:46

Como demonstração de engenharia, isso me deixa impressionado. Como forma de pegar o produto proprietário de outra pessoa e fabricar um substituto não autorizado, acho que deveria ser ilegal. — 12:22

Um compilador produz um executável. Ele não produz um certificado de autoria independente. — 18:04

Uma nova linguagem não me convence de que o trabalho original não contribuiu em nada para o processo. — 20:10

  • Ghidra (ferramenta): Framework de engenharia reversa lançado pela NSA que analisa binários e pode produzir uma representação de alto nível de seu comportamento.
  • Windows Calculator (ferramenta): Aplicativo de calculadora do Windows usado no experimento como origem do executável analisado.
  • Rust (conceito): Linguagem de programação escolhida para implementar a reconstrução da calculadora.
  • NSA (empresa): Agência dos Estados Unidos que lançou o Ghidra, segundo o vídeo.
  • Dave Plummer (pessoa): Engenheiro de software aposentado da Microsoft e apresentador que conduz o experimento e comenta suas implicações.
  • Microsoft (empresa): Empresa associada ao Windows Calculator e à experiência profissional anterior de Dave Plummer.
  • Sega versus Accolade (conceito): Caso judicial citado como exemplo de engenharia reversa permitida, em determinadas circunstâncias, para acessar elementos funcionais não protegidos.
  • Sony versus Connectix (conceito): Caso judicial citado no qual cópias intermediárias do BIOS do PlayStation durante o desenvolvimento de um emulador foram consideradas fair use.
  • engenharia de sala limpa (conceito): Método de desenvolvimento em que uma equipe documenta uma interface sem consultar sua implementação e outra cria uma implementação com base nessa especificação.

00:00 Oi, sou Dave. Bem-vindos à minha oficina. Sou Dave Plummer, engenheiro de software aposentado da Microsoft, desde os tempos do MS-DOS e do Windows 95. A esta altura, você provavelmente já ouviu a notícia de alguém clonando toda a suíte Photoshop e, depois, toda a suíte Microsoft Office. Como se sonhava com a energia nuclear nos anos 50, o software agora é barato demais para ser medido. Aliás, agora é de graça, não é? Bem, hoje vou fazer duas coisas. Vou dar minha opinião sincera sobre se clonar aplicativos com IA é ético e legal e, graças a uma ajudinha da NSA, vou mostrar a você

00:30 exatamente como isso é feito. E tudo começa com uma pergunta simples. Posso fornecer a uma IA um aplicativo Windows pronto, sem fornecer nenhum código-fonte nem símbolos, e fazer com que ela produza exatamente o mesmo aplicativo, mas escrito do zero em Rust? Ou seja, dá para pegar os mesmos controles, cálculos e comportamentos, desde o executável de outra pessoa até um novo executável que faça exatamente o mesmo trabalho? Esse é o experimento de hoje. E, se funcionar, há uma segunda pergunta esperando por trás dessa. Quem realmente leva o crédito por criar o quê?

01:01 Hoje de manhã, comecei pela calculadora da Microsoft, calc.exe. Eu queria passar o programa para uma ferramenta de engenharia reversa, fazer a IA reconstruir seu comportamento com base no código e, então, compilar essa reconstrução em um aplicativo Rust funcional. Agora, entre todos os aplicativos Windows do mundo, por que escolher a calculadora? Bem, primeiro, ela é uma rara peça do Windows que foi disponibilizada sob a licença MIT, então talvez os brutamontes armados não arrombem a minha porta por mexer nela. E o outro motivo é que eu costumava ser responsável pela calc quando trabalhava na Microsoft. Mas não escrevi nenhum dos códigos legais dela. Eu era apenas o gerente de desenvolvimento

01:31 que supervisionava os desenvolvedores que faziam o trabalho de verdade. Mas, acredite ou não, a calculadora é muito complexa por dentro. Ela tem modos aritmético, de programação e de contabilidade, funciona com várias bases numéricas e tem rotinas de matemática de precisão infinita. Há muita coisa acontecendo nos bastidores, coisas que eu estava confiante de que a IA não conseguiria deduzir por inspeção ou lendo sobre o assunto em outro lugar. Em vez disso, ela teria que realmente entender o código no binário da calculadora para progredir de verdade. Mais importante, não acho que seja possível deduzir todos os comportamentos às vezes peculiares da Calc apenas inspecionando o

02:03 aplicativo em execução. Se ela fizer isso, acho que é prova de que leu a receita. E isso pode ser importante quando o objetivo é uma reprodução perfeita. Ela precisa ser realmente idêntica ao funcionamento do original. E o motivo de isso talvez funcionar está bem diante dos nossos olhos. Um executável contém instruções. Toda decisão tomada pelo programa ainda precisa acontecer em algum lugar, em algum código escrito por alguém. Isso nos dá algo para investigar, mesmo quando o arquivo de código-fonte original já não está disponível. A ferramenta que usei foi o Ghidra, a estrutura de engenharia reversa lançada pela

02:33 NSA. Ele pode desmontar instruções de máquina e construir uma descrição de comportamento em um nível mais alto, parecida com C. Essa descrição é uma análise do programa compilado, não uma cópia restaurada do código-fonte original. Porque ele não conhece nenhum dos nomes, dos símbolos nem nada disso. Ele está simplesmente trabalhando de trás para a frente, a partir da lógica binária, e gera código C que seria compilado para produzir aquela lógica, mas os nomes são as melhores suposições possíveis. Internamente, o Ghidra pode traduzir instruções do processador em operações mais simples chamadas P-code. Na verdade, era assim que muitos dos antigos aplicativos do Microsoft

03:04 Office eram escritos. Microinstruções em vez de linguagem assembly, que depois eram montadas ou compiladas — dependendo de como você vê a coisa — em código de máquina. E as operações P-code descrevem coisas como carregar um valor, fazer uma operação aritmética, armazenar um resultado e escolher qual caminho seguir. Isso dá à análise um vocabulário comum para descrever o que o processador está fazendo. Os arquivos intermediários específicos do nosso experimento são importantes, mas o caminho essencial é: executável, análise das operações, Rust reconstruído e, depois, outro executável.

03:35 Imagine que a calculadora recebe um algarismo. Em algum lugar, ela precisa decidir se esse algarismo se junta ao número que já está no visor ou se começa um novo número que você está digitando. Em algum lugar, ela guarda se há um operador pendente. Depois que você aperta igual, o próximo algarismo talvez precise iniciar um novo cálculo. Essas são as transições de estado, e o programa compilado contém os mecanismos que as fazem acontecer. O trabalho da IA é seguir esses mecanismos e expressar em Rust um conjunto equivalente de decisões. Uma leitura da memória pode se tornar um campo em uma estrutura. Um emaranhado de desvios pode

04:05 se tornar uma expressão match. O código-fonte resultante pode ter uma aparência bem diferente e ainda preservar o comportamento do código que forneceu as evidências. Como eu disse, você não vai receber nenhum dos nomes das variáveis, nenhum comentário nem outras conveniências que não sobrevivem à compilação, mas vai receber um projeto de código-fonte funcional, embora um tanto difícil de ler. É claro que a aritmética é só uma parte de um aplicativo Windows. O executável pode conter recursos como layouts de caixas de diálogo, strings, ícones e assim por diante. As importações nos dizem quais chamadas estão sendo feitas para outros componentes. Uma reconstrução convincente precisa levar em conta

04:36 a interface, além do mecanismo de cálculo. Acertar uma soma não nos diz se os atalhos de teclado funcionam ou se o botão de limpar redefine o estado correto. A calculadora é um software particularmente bom para fazer um clone superficial parecer convincente. A maioria de nós consegue organizar os botões, sabe, em algum tipo de editor, e a maioria consegue implementar adição, subtração e assim por diante. A parte difícil é reproduzir o conjunto de decisões acumuladas por trás desses botões. E, portanto, há várias maneiras de dar errado. A análise pode interpretar a função de forma equivocada. O código Rust pode compilar, mas

05:07 implementar as mudanças de estado erradas. A interface pode se parecer com a original enquanto, sem que se perceba, funciona como uma calculadora completamente diferente. Vou mostrar agora o processo de verdade. Veja como o executável vira informações com as quais a IA pode trabalhar e como essas informações se transformam em código-fonte que um compilador Rust aceita. Depois, vamos iniciar o resultado e compará-lo com o original. Mas, primeiro, falando em ferramentas que mostram exatamente o que está acontecendo por dentro do seu computador: se a ventoinha do seu computador acabou de acelerar, se um quadro foi perdido ou se a bateria começou a descarregar sem motivo aparente, a maioria dos gerenciadores de tarefas mostra um

05:39 número que parece razoável depois que tudo já aconteceu. Trinta anos depois de escrever o Gerenciador de Tarefas original do Windows, criei um novo, o Task Manager OG, para identificar o processo enquanto ele ainda está acontecendo. E ele é todo feito em código nativo enxuto. Win32 no Windows, Swift e AppKit no Mac, QT no Linux, tudo usando um único núcleo de medição compartilhado em C++. Não há Electron nem navegador fingindo ser uma ferramenta do sistema. A versão grátis oferece a visualização ao vivo essencial de que você precisa. A versão Pro adiciona o gravador de voo, para você poder registrar a lentidão, voltar na gravação e ver o que a CPU, a GPU, a memória

06:10 e assim por diante fizeram para causar o problema, depois que o pico já passou. Está em tmac.org, se você quiser baixar de graça para Windows, Mac e Linux. Certo, vamos criar uma calculadora. Aqui está meu prompt. Certo, sua missão é reescrever calc em Rust. Vamos fazer isso descompilando o binário para um formato intermediário à sua escolha, traduzindo a lógica completa e corretamente para Rust e, então, compilando esse código Rust para produzir um novo binário chamado AI calc, que deve ser funcionalmente equivalente à calc original, provavelmente escrita em C.

06:41 Então, este é um projeto de tradução de C para Rust sem acesso ao código-fonte. Quero que você itere no projeto até todos os seus testes passarem e o binário resultante seja executado e funcione da mesma maneira que a calc original, tenha aparência pixel a pixel idêntica e assim por diante. Agora, ela vai me perguntar se quero fazer o aplicativo inteiro ou só o inicializador. E, claro, queremos fazer o aplicativo inteiro, o que também significa todas as DLLs das quais ele depende. Agora, vamos passar rapidamente por alguns dos avanços. Dá para ver que ela usou o Ghidra e recuperou 10.195

07:11 funções na DLL de cálculo, o que parece fazer sentido. Em seguida, acredito que está se gabando de suas 131.077 classificações de comandos e dos 8.201 testes de despacho que escreveu. Também tentou 2 + 3 = 5 sem abrir a interface. Isso é tranquilizador. Também diz que o Ghidra terminou de finalizar as exportações da DLL da interface, recuperando 18.959 funções sem falhas de descompilação. Agora, ele tentou algo como 357 sequências de comandos diferentes e 8.032

07:43 exibições intermediárias diferentes e garantiu que correspondem exatamente ao mecanismo original. Nos próprios testes, encontrou vários erros e depois voltou e corrigiu o código para garantir que ele passasse nos casos de teste. Mas devemos encarar isso como um indício de que não se trata de um clone determinístico perfeito da lógica original. Obviamente, ele está fazendo algum tipo de suposição ao longo do caminho, preenchendo algumas lacunas e errando, porque percebeu que o resultado está errado. Portanto, o fato de precisar voltar e reinterpretar ou reparar o código original significa que realmente não podemos

08:15 presumir que haja algo totalmente preciso nesse clone que está sendo construído. Ele pode estar próximo. Pode estar quase perfeito, mas não vai ser perfeito. E, com isso, vou avançar rapidamente pela fase de testes para vermos o que ele realmente produziu como aplicativo. Certo, ele anda como uma calculadora e fala como uma calculadora, mas calcula como uma calculadora? Vamos testar. Vou fazer 123 + 456. Vou precisar pegar minha outra calculadora para verificar se está certo, mas, até confirmar, parece correto

08:46 para mim. Então, agora temos um aplicativo em Rust funcional e bastante parecido com a calculadora. Agora só precisamos conversar sobre o que fizemos. Recriamos a aparência e a funcionalidade da calculadora na demonstração que você acabou de assistir. Pedi que fizesse o trabalho de uma só vez, mas isso descreve minha interação com a IA. Não significa que um workflow automatizado precise executar cada etapa interna sem verificar nem revisar nada. E quero ser preciso quanto ao uso da palavra “perfeitamente”, porque os programadores têm o hábito de nos fazer lamentar essa palavra. O que demonstramos é uma

09:17 reconstrução funcional. Afirmar equivalência completa exigiria uma comparação muito mais ampla, incluindo sequências de entrada obscuras e comportamentos que ainda não testamos aqui. Pode haver uma discrepância à espera por trás de uma combinação de teclas que ninguém tenta desde 1997. Dito isso, a IA também produziu uma suíte de testes abrangente que executa dezenas de milhares de tipos possíveis de cálculos na calculadora para garantir que ela sempre faça exatamente a mesma coisa que a original. Mas, pensando bem, a Intel provavelmente também tinha um conjunto bem robusto de testes matemáticos para o Pentium, então não há

09:48 garantias. Mas essa distinção não torna o resultado algo corriqueiro. A IA passou de um aplicativo pronto para um código-fonte recém-gerado em outra linguagem e, depois, voltou a um aplicativo. Os arquivos de código-fonte originais não foram necessários como entrada. O próprio executável forneceu um caminho até a implementação. Trabalhei com software para Windows durante toda a minha carreira, então tenho um apego bastante forte à ideia de que escrever um aplicativo envolve escrever o aplicativo. Aqui, por outro lado, eu propunha começar na outra ponta da linha de montagem e pedir à máquina que percorresse o caminho de volta, o que parece

10:19 uma técnica útil de recuperação, até que o aplicativo que você está recuperando pertence a outra pessoa. Para entender o que aconteceu, acompanhe o percurso de um programa comum pelo processo. Um desenvolvedor escreve o código-fonte. O compilador transforma esse código em código de máquina, e o linker reúne as partes em um executável, com as referências apropriadas a bibliotecas, serviços do sistema operacional e assim por diante. Há muitos detalhes entre essas etapas, mas essa é a jornada que importa aqui. Durante esse percurso, muita coisa é descartada. Os nomes úteis das variáveis desaparecem. Os comentários certamente

10:50 não são necessários para executar o programa. E uma função que você passou um dia tentando separar cuidadosamente de outra função pode acabar sendo incorporada a ela de qualquer forma. Várias maneiras diferentes de escrever uma operação podem resultar nas mesmas instruções após a otimização. Consequentemente, reverter esse processo não recupera o código-fonte original. Se alguém compila um programa que contém uma variável chamada total, não há necessariamente um total secreto escondido no executável, à espera de ser descompactado. O compilador manteve o que o computador precisava, o que raramente inclui uma explicação do que o desenvolvedor estava

11:20 pensando depois da terceira xícara de café. Mas não precisamos recuperar as frases originais do desenvolvedor para recuperar parte do que essas frases fizeram o computador executar. E é essa possibilidade que torna este experimento interessante. E nossa primeira constatação importante: diferentes textos de código-fonte podem descrever o mesmo cálculo. Você pode mudar a linguagem, renomear todas as variáveis e reorganizar as funções, mantendo uma conexão muito significativa com o programa original. Ver Rust no editor não nos diz o quanto o programa foi projetado de forma independente. O que nos traz de volta àquela

11:50 frase que, de início, fez isso parecer tranquilizador: “Não estamos usando nenhum código original”. Mas o que queremos dizer com código? Se estamos falando dos arquivos de código-fonte originais, eu não os tenho. Não os forneci e, mais tarde, solicitei que o código fosse verificado quanto a plágio e garanti que ele não estivesse usando código externo como exemplo, só por precaução. Mas um executável é código compilado. Desmontá-lo não o transforma num conjunto de fatos sem relação, e traduzir uma análise para Rust não apaga de onde essa análise veio. Precisamos distinguir texto de código-fonte novo de autoria independente. Este é o

12:22 ponto em que minha reação muda. Como demonstração de engenharia, tudo isso me deixa de queixo caído. Como proposta para pegar o produto proprietário de outra pessoa e fabricar um substituto não autorizado, acho que deveria ser ilegal. Dependendo do que foi copiado e de como, a legislação vigente talvez já o torne ilegal. Minha reação é chamar isso de pirataria, e mudar a linguagem de programação não melhora minha opinião. Esse é apenas meu julgamento ético, porque não sou advogado, e minhas opiniões gratuitas têm um preço condizente. Mas a resposta jurídica tem uma complicação que precisamos levar

12:52 a sério, especialmente se quisermos apresentar um argumento sólido. A lei de direitos autorais dos Estados Unidos não concede propriedade sobre todas as funções que um programa executa. A Seção 102 da Lei de Direitos Autorais exclui ideias, processos e métodos de operação da proteção autoral. A Microsoft não pode ser dona da adição só porque a calculadora soma números. Outra pessoa pode escrever uma calculadora, inclusive uma muito boa, sem pedir permissão à Microsoft para fazer cálculos. O código que expressa essas funções pode ser protegido, assim como outras formas de expressão original. A proteção pode se estender

13:24 além do texto literal do código-fonte, e é por isso que mudar o nome de todas as variáveis não é uma saída universal. A análise jurídica precisa separar a expressão protegível dos requisitos funcionais e de outros elementos que os direitos autorais não abrangem. E isso pode ser difícil num programa criado quase inteiramente para realizar uma tarefa. Porém, a analogia à qual sempre volto é a tradução. Traduza um romance para outro idioma e terá palavras novas, mas isso não faz de você o autor original. Você não pode reivindicar a obra como sua, porque ela se baseia na contribuição criativa de outra pessoa que

13:55 escreveu o original. O software torna a analogia um pouco mais complicada, porque os direitos autorais não protegem o cálculo subjacente. Ainda assim, usar uma nova linguagem, por si só, nos diz muito pouco sobre se a expressão protegida sobreviveu a esse percurso. E os tribunais já permitiram algumas formas de engenharia reversa. Em Sega contra Accolade, o tribunal permitiu a desmontagem, nas circunstâncias daquele caso, para chegar a elementos funcionais não protegidos necessários à compatibilidade. Em Sony contra Connectix, a cópia intermediária da BIOS do PlayStation durante o desenvolvimento do emulador foi considerada uso justo.

14:26 Usar o programa original durante o desenvolvimento não decidiu automaticamente o caso contra o desenvolvedor. Essas decisões não concedem uma autorização geral para duplicar aplicativos comerciais. A Sega deixou expressamente em aberto as alegações de violação relacionadas aos produtos finais. Elas significam, sim, que o fato de um binário ter entrado no processo não é uma descrição completa da legislação dos Estados Unidos, por mais que eu tenha uma opinião a respeito. Há excelentes motivos para investigar binários, desde analisar malware até criar substitutos compatíveis. Passo tempo suficiente mantendo computadores antigos funcionando para apreciar isso. Décadas atrás, uma empresa chamada Phoenix criou sua própria versão de

14:57 o BIOS do IBM PC, basicamente um equivalente funcional para que fabricantes de clones pudessem construir PCs em torno dele. É claro que a IBM ficou indignada e processou a Phoenix, mas a Phoenix não havia copiado o trabalho da IBM. O que eles fizeram, em vez disso, ficou conhecido como engenharia de sala limpa ou sala branca: um engenheiro documenta a API sem jamais olhar para o código que a implementa, e depois outro engenheiro, ou uma equipe de engenheiros, cria uma API exatamente de acordo com essa especificação. Feito corretamente, o resultado deve ser um substituto perfeito, mesmo que seja implementado de uma maneira completamente diferente. E, no fim, o tribunal decidiu a favor da Phoenix

15:29 em grande parte porque a própria API era pública e nenhuma implementação real da IBM foi usada. Mas o BIOS do PC original contém apenas cerca de 12 pontos de entrada, eu acho. Um aplicativo como o Photoshop tem milhares de pontos de interface. Certamente seria possível fazer engenharia de sala limpa do Photoshop, mas só o trabalho de produzir a especificação seria proibitivamente grande. Uma maneira aparentemente possível de contornar isso seria usar automação para operar o aplicativo original em tempo real, descobrir tudo o que há para saber sobre ele e, então, construir algo a partir disso. Não acho que isso seja exatamente possível ainda, mas um dia,

16:00 é claro, será. Há outra complicação neste exemplo específico. A Microsoft publicou o código-fonte da Calculadora moderna do Windows sob a licença MIT em 2019. Isso não estabelece a licença de todos os calc.exe históricos no repositório, que exclui certos componentes e dados. Não fornecer arquivos de código-fonte é algo que podemos estabelecer sobre este experimento. Provar que um modelo nunca encontrou código-fonte público relacionado durante o treinamento é uma questão bem diferente. E eu perguntei, e ele me garantiu que não, mas nunca se sabe. As imagens mostram o workflow que nós

16:31 usamos. Elas não nos dão uma biografia completa do que o modelo estava fazendo nos bastidores. Mas a questão mais ampla continua válida, mesmo com essas ressalvas. Suponha que a entrada seja um aplicativo proprietário cujo dono não autorizou a reescrita. Suponha que o objetivo seja reproduzir sua implementação e aparência características com precisão suficiente para substituí-lo. Deveríamos poder inserir esse produto em um tradutor automatizado, mudar sua linguagem e declarar que o resultado é um trabalho novo e independente? Acho que isso merece muito mais escrutínio do que está recebendo atualmente. Isso importa para mim pessoalmente por causa do

17:01 Task Manager T-Clock. Quando usei IA para ajudar a criar aquilo, especificamente não inseri um aplicativo existente no processo para depois simplesmente pedir uma tradução. Em vez disso, escrevi uma especificação de 107 páginas descrevendo exatamente o que eu queria e, depois, foram necessárias outras 400 a 500 PRs no GitHub para chegar àquele ponto. Isso significou tomar decisões sobre o produto e expressá-las antes de pedir à IA que as implementasse. Uma especificação também não é automaticamente inocente, porque você poderia incluir nela a expressão protegida de outra pessoa e usar essa etapa extra

17:32 para disfarçar a cópia. Começar com um prompt também não prova que algo é legal. Mas há uma diferença significativa entre projetar o comportamento que você quer e usar a implementação de outro aplicativo como matéria-prima para o seu. Essa é a distinção que quero preservar. Quando o caminho é: meus requisitos, código gerado, aplicativo compilado, posso dizer que a IA me ajudou a implementar meu projeto. Mas, quando o caminho começa com um binário existente, passa pela análise desse binário e termina com um substituto para ele, quero que o resultado seja identificado como um clone

18:04 derivado daquele aplicativo. A permissão pode torná-lo perfeitamente legítimo. Ainda assim, ele tem um ancestral. Minha objeção é usar a etapa de tradução para alegar que o trabalho original não contribuiu em nada. Se o seu processo depende do aplicativo de outra pessoa ou de qualquer tipo de contribuição criativa alheia, reconheça e aceite essa dependência. E, se você está reproduzindo expressão protegida, chamar o resultado de Rust não dá permissão. Um compilador produz um executável. Ele não produz um certificado de autoria independente. Agora, estenda o experimento mental para

18:34 o Photoshop ou para pegar o Final Cut do Mac e produzir uma versão para Windows. Esses são problemas de engenharia muito maiores, pelo menos para fazê-los funcionar direito. E, se você está curioso, pelo que vi, os grandes substitutos tendem a não funcionar muito bem. Porque um aplicativo grande depende de bibliotecas, recursos, formatos de arquivo, plugins e serviços do sistema operacional que não vão se transformar, por gentileza, em Rust portátil só porque alguém pediu com educação. A Calculadora não demonstra que podemos portar o Final Cut amanhã. Não, qualquer prazo que eu desse seria especulação. O que isso demonstra é

19:06 por que devemos prestar atenção à direção que as coisas estão tomando. Tradicionalmente, a engenharia reversa exigia muito trabalho especializado. A IA pode ajudar a interpretar as evidências e transformá-las em outra implementação. Se isso se tornar mais rápido e confiável, a economia de criar um substituto autorizado poderá mudar, mesmo que os princípios legais continuem familiares. E também há possibilidades valiosas aqui. Um desenvolvedor que seja dono de um aplicativo poderia usar essas técnicas para recuperar trabalho perdido ou ajudar a migrá-lo. Com permissão, reconstruir software antigo em uma linguagem de fácil manutenção poderia ser uma ferramenta fantástica. A mesma

19:38 capacidade se torna bem menos atraente quando o dono do aplicativo é tratado simplesmente como um detalhe inconveniente. Começamos perguntando se uma IA conseguiria partir de um executável do Windows, fazer o caminho inverso e chegar a um aplicativo em Rust. Neste experimento, ela produziu uma reconstrução funcional. A resposta sobre se é um equivalente perfeito ainda depende de verificação, e a resposta sobre a legalidade depende de mais do que a linguagem em que o compilamos. Na minha opinião, inserir o aplicativo proprietário de alguém em uma reescrita automatizada para fabricar um substituto não autorizado deveria ser

20:10 ilegal. As leis existentes talvez já proíbam casos específicos. Não vou fingir que só um binário determina isso. Mas uma nova linguagem não me convence de que o trabalho original não contribuiu em nada para o processo. E agora que você assistiu ao processo e entende melhor como ele funciona, pense em como se sentiria se o aplicativo submetido a ele fosse seu. Se você achou o episódio de hoje interessante ou divertido, lembre-se de que estou aqui principalmente pelos inscritos e pelas curtidas. Então, ficaria honrado se você considerasse deixar um de cada antes de ir hoje. Confira um episódio de Shop Talk, em que respondemos às melhores perguntas e compartilhamos as melhores ideias da semana sobre o

20:40 canal. Enquanto isso, espero ver você na próxima vez, bem aqui na garagem do Dave. >> Faça isso, Glen. Faça isso. Faça isso.

Transcrição original

[00:00] Hey, I’m Dave. Welcome to my shop. I’m Dave Plummer, retired software engineer from Microsoft going back to the MS-DOS and Windows 95 days. And by now, you’ve likely heard the news of someone cloning the entire Photoshop suite and then the entire Microsoft Office suite. Just as they dreamed for nuclear power back in the ’50s, software is now too cheap to meter. Heck, it’s free now, right? Well, I’m going to do two things today. I’m going to give you my hot take on whether AI cloning of applications is ethical and legal and thanks to a little help from the NSA, I will then show you

[00:30] precisely how it is done. And it all starts with a simple question. Can I give an AI a finished Windows application without supplying any of its source code or symbols and have the AI produce the exact same application but written completely anew in Rust? And so, can you take the same controls, calculations, and actual behavior all the way from somebody else’s executable to a new executable that does the exact same job? That’s the experiment today. And if it works, there’s a second question waiting behind that. Who actually gets credit for creating what?

[01:01] This morning I started with Microsoft’s calculator, calc.exe. I wanted to feed the program into a reverse engineering tool, have the AI reconstruct its behavior based on the code, and then compile that reconstruction into a working Rust application. Now, of all the Windows applications in the world, why pick on calculator? Well, for one, it’s a rare piece of Windows that has been placed under the MIT license, so maybe the jackbooted thugs won’t kick in my door for messing with it. And the other reason is that I used to own calc when I worked at Microsoft. Now, I didn’t write any of the cool code in it though. I was just the dev manager

[01:31] overseeing the developers doing the real work. But believe it or not, calculator is very complex internally. It has arithmetic and programming and accounting modes and works in multiple number bases and has infinite precision mathematics routines. There’s a lot going on under the surface, stuff that I was confident the AI could not deduce from inspection or by reading about it elsewhere. Instead, it would have to actually understand the code in in calculator binary to make any real progress. More important, I don’t think you could deduce all of Calc’s sometimes quirky behaviors purely by inspecting the

[02:03] running application. If it does it, I think it’s proof that it’s read the recipe. And that can matter when a perfect reproduction is the goal. It has to be really identical to the operation of the original. And the reason this might work is hiding in plain sight. An executable contains instructions. Every decision the program makes still has to happen somewhere in some code that somebody wrote. That gives us something to investigate even after the original source file is no longer available. Now, the tool I used was Ghidra, the reverse engineering framework released by the

[02:33] NSA. It can disassemble machine instructions and construct a higher-level C-like description of their behavior. The description is an analysis of the compiled program rather than a restored copy of the original source code. Cuz it doesn’t know any of the names or the symbols or anything. It’s just working backwards from the binary logic, and it kicks out C code that would compile to that logic, but the names are going to be best guesses. Internally, Ghidra can translate processor instructions into simpler operations called P-code. That’s actually how many of the old Microsoft

[03:04] applications for Office were written. Microinstructions instead of assembly language, which was then assembled or compiled, depending how you look at it, into machine code. And so, P-code operations describe things like loading a value, doing arithmetic, storing a result, and choosing which path to follow. It gives the analysis a common vocabulary for what the processor is doing. The particular intermediate files in our experiment matter, but the essential route is executable, analysis of its operations, reconstructed Rust, and then another executable.

[03:35] Imagine the calculator receives a digit. Somewhere it has to decide that that digit extends the number already on the display or whether it starts a new number that you’re typing in. Somewhere remembers whether an operator is pending. After you press equals, the next digit may need to begin a fresh calculation. Those are the state transitions, and the compiled program contains the machinery that makes them happen. The AI’s job is to follow that machinery and express an equivalent set of decisions in Rust. A load from memory might become a field in a structure. A tangle of branches may

[04:05] become a match expression. The resulting source can look quite different while preserving the behavior of the code that supplied the evidence. Now, like I said, you’re not going to get any of the variable names, none of the comments, and the other niceties that do not survive compilation, but you do get a working, if somewhat unreadable, source code project. Of course, arithmetic is only part of a Windows application. The executable can contain resources such as dialog layouts, strings, icons, and so on. Well, imports tell us about what calls are being made into other components. A convincing reconstruction has to account

[04:36] for the interface as well as the calculation engine. Getting a sum right doesn’t tell us whether the keyboard shortcuts work or whether the clear button resets to the right state. A calculator is a particularly good piece of software at making a superficial clone look respectable. Most of us can arrange the buttons, you know, in some kind of editor, and most of us can implement addition and subtraction, and so on. The difficult part is reproducing the accumulated decisions behind those buttons. And so, it has several opportunities to fail. The analysis might misunderstand the function. The Rust might compile but

[05:07] implement the wrong state changes. The interface might resemble the original while quietly behaving like an entirely different calculator. I’m going to show you the actual process now. Watch how the executable becomes information that the AI can work with and how that information becomes the source code that a Rust compiler will accept. Then, we’ll launch the result and compare it with the original. But first, speaking of tools that show you exactly what’s happening under your hood, if your computer’s fan just spun up or a frame dropped or the battery started draining for no obvious reason, most task managers will show you a

[05:39] number that looks okay after the fact. 30 years after writing the original Windows Task Manager, I built a new Task Manager OG to name the process while it’s still happening. And it’s tight native code all the way down. Win32 on Windows, Swift and AppKit on the Mac, QT on Linux, all over one shared C++ measuring core. There’s no electron, no browser pretending to be a system tool. The free version gives you the important live view that you need. Pro adds the flight recorder so you can actually record the slowdown, scrub back through it, and see what the CPU, GPU, or memory

[06:10] and so on did to cause the actual damage after the spike is gone. It’s at tmac.org if you want the free download for Windows, Mac, and Linux. All right, let’s make a calculator. Here is my prompt. Okay, your mission is to rewrite calc in Rust, which we are going to do by decompiling the binary to an intermediate format of your choosing, then translating the logic completely and accurately to Rust, then compiling that Rust code to produce a new binary called AI calc, that should be functionally equivalent to the original calc, which was likely authored in C.

[06:41] So, this is a C to Rust translation project without access to the source code. I want you to iterate on the project until all of your tests pass, and the resulting binary executes and operates in the same way as the original calc, looks pixel perfect, etc. Now, it’s going to ask me if I want to do the entire application or just the launcher. And of course, we want to do the entire application, which means all of its dependent DLLs that it needs as well. Now, we’ll just skim through some of its progress. You can see it’s used Ghidra, and it’s recovered 10,195

[07:11] functions in the calculation DLL, which sounds about right. Next, I believe it’s bragging about its 131,077 command classifications and the 8,201 dispatch tests that it wrote. It also tried 2 + 3 = 5 without opening the UI. Now, that’s reassuring. It also says that Ghidra has finished finalizing the UI DLL exports, recovering 18,959 functions with no decompilation failures. Now, it has tried something like 357 different command sequences and 8,032

[07:43] different intermediate displays and made sure that they match the original engine exactly. Now, in its own testing, it has found a number of errors which it has then gone back and fixed the code to make sure that it passes the test cases. But, we should take that as an indication that it is not a perfect deterministic clone of the original logic. It’s obviously making some kind of assumptions along the way and it’s filling in some blanks and it’s doing it wrong because it’s noticed in the outcome is wrong. So, the fact that it has to go back and reinterpret or repair the original code means we really can’t

[08:15] assume that there’s anything fully accurate about this clone that it’s building. It might be close. It might be near perfect, but it’s not going to be perfect. And with that, I’m just going to fast forward through the test phase and let’s see what it actually produced for an application. All right, it walks like a calculator and it talks like a calculator, but does it calculate like a calculator? Let’s give it a shot. We’ll do 1 2 3 + 4 5 6. I’ll have to get my other calculator out to verify if this is correct, but pending verification, it looks correct

[08:46] to me. So, now we have a working Rust application and it’s a close approximation of calculator. Now, we just have to talk about what we made. We recreated calculator’s appearance and functionality in the demonstration that you just watched. I asked for the job in one shot, but that describes my interaction with the AI. It doesn’t mean an automated workflow has to accomplish every internal step without checking or revising anything. And I want to be precise about the word perfectly because programmers have a habit of making us regret that word. What we’ve demonstrated is a working

[09:17] reconstruction. Claiming complete equivalence would require a much broader comparison including obscure input sequences and behaviors that we have not yet exercised here. There could still be a discrepancy waiting behind a key combination that nobody has tried since 1997. That said, however, the AI also produced a comprehensive test suite that runs tens of thousands of possible types of computations through the calculator to make sure it always does exactly the same thing as the original. But then again, Intel probably had a pretty robust set of math tests for the Pentium, too, so there really are no

[09:48] guarantees. But distinction doesn’t make the result ordinary. The AI crossed from a finished application to newly generated source in another language and then back to an application. The original source files weren’t required as an input. The executable itself supplied a route into their implementation. Now, I spent my career working on Windows software, so I have a fairly strong attachment to the idea that writing an application involves writing the application. Whereas here, I was proposing to start at the other end of the assembly line and ask the machine to work its way backwards, which sounds

[10:19] like a useful recovery technique right up until the application you’re recovering belongs to somebody else. To understand what happened, follow an ordinary program on its trip with the door. A developer writes source code. The compiler turns that source into machine code and the linker brings the pieces together into an executable with the appropriate references to libraries and operating system services and so on. There are plenty of details in between, but that’s the journey that matters here. During that journey, a lot gets thrown away. Your helpful variable names disappear. Your comments certainly

[10:50] aren’t required to run the program. And a function that you spent a day trying to carefully separate from another function might wind up getting inlined into it anyway. Several different ways of writing an operation can end up producing the same instructions after optimization. Consequently, reversing that process doesn’t deliver the original source. If somebody compiles a program containing a variable called total, there isn’t necessarily a secret total hidden inside the executable waiting to be unzipped. The compiler kept what the computer needed, which rarely includes an explanation of what the developer was

[11:20] thinking after the third cup of coffee. But we don’t need to recover the developer’s original sentences to recover some of what those sentences made the computer do. And that’s the opening that makes this experiment interesting. And our first important realization. Different source texts can describe the same computation. You can change the language, rename every variable, and reorganize the functions while keeping a very substantial connection to the program that you started with. Seeing a Rust in the editor doesn’t tell us how independently the program was designed. Which brings us back to that

[11:50] phrase that initially made this sound reassuring, “We’re using none of the original code.” But what do we mean by code? If we mean the original source files, I don’t have those. Didn’t hand them over, and I later ordered the code for plagiarism and made sure that it wasn’t using external code as samples just in case. But an executable is compiled code. Disassembling it doesn’t turn it into an unrelated set of facts, and translating an analysis into Rust doesn’t erase where the analysis came from. We need to distinguish new source text from independent authorship. This is the

[12:22] point where my reaction changes. As an engineering demonstration, this whole thing blows my mind. As a proposed way to take somebody else’s proprietary product and manufacture an unauthorized substitute, I think it should be illegal. Depending on what has been copied and how, existing law may already make it so. My instinct is to call that piracy, and changing the programming language doesn’t improve my opinion of it. That’s just my ethical judgment, cuz I’m not a lawyer, and my free opinions are priced accordingly. But the legal answer has a complication that we need to take

[12:52] seriously, especially if we’re going to make a strong argument. American copyright law doesn’t grant ownership of every function that a program performs. Section 102 of the Copyright Act excludes ideas, processes, and methods of operation from copyright protection. Microsoft doesn’t get to own addition because calculator adds numbers together. Someone else is allowed to write a calculator, including a very good one, without asking Microsoft’s permission to calculate. The code expressing these functions can be protected, as can other original expression. Some protection can extend

[13:24] beyond literal source text, which is why changing every variable name isn’t a universal escape hatch. Legal analysis has to separate protectable expression from functional requirements and other elements that copyright doesn’t cover. And that can be a difficult exercise in a program built almost entirely to accomplish a task. The analogy I keep coming back to though is translation. Translate a novel into another language and you get new words, but you haven’t thereby become the original author. You can’t claim that as your own work cuz it relies on the creative input of another person who

[13:55] have written the original. Now, software makes the analogy a little more complicated because copyright doesn’t own the underlying computation. Still, a new language by itself tells us very little about whether protected expression survived that trip. And courts have already allowed some reverse engineering. In Sega versus Accolade, the court allowed disassembly under the circumstances of that case to reach unprotected functional elements needed for compatibility. In Sony versus Connectix, intermediate copying of the PlayStation BIOS during development of the emulator was held to be fair use.

[14:26] Using the original program during development did not automatically settle the case against the developer. Now, those decisions don’t issue a general permission slip to duplicate commercial applications. Sega expressly left open infringement claims about the finished products. They do mean that whether a binary entered the process isn’t a complete statement of American law, no matter how I feel. There are excellent reasons to investigate binaries from analyzing malware to building compatible replacements. I spend enough time keeping old computers alive to appreciate that. Decades ago, a company called Phoenix made their own version of

[14:57] the IBM PC BIOS, basically a work-alike so that clone manufacturers could build PCs around them. IBM was of course outraged and sued, but Phoenix had not copied IBM’s work. What they had done instead was known as clean room engineering or white room and where one engineer documents the API without ever looking at the code that implements it and then another engineer or team of engineers creates an API precisely to that specification. Done correctly, it should be a perfect replacement even if implemented completely differently. And the court ultimately ruled in Phoenix’s

[15:29] favor in large part because the API itself was public and none of IBM’s actual implementation was involved. But the original PC BIOS contains only about 12 entry points, I think it is. An application like Photoshop has thousands of interface points. You certainly could clean room Photoshop, but the work just in producing the spec would be prohibitively large. One ostensible way around it would be to use automation to drive the original application in real time and figure out everything there is to know about it and then build from that. I don’t think that’s quite possible yet, but one day,

[16:00] of course, it will be. There’s another wrinkle with this particular example. Microsoft published the modern Windows Calculator source code under the MIT license in 2019. That doesn’t establish the license of every historical calc.exe in the repository excludes certain components and data. Not supplying source files is something we can establish about this experiment. Proving that a model has never encountered related public source during training is a very different proposition. And I asked it and it assured me, but you never know. The footage shows the workflow that we

[16:31] used. It doesn’t give us a complete biography of what the model was doing behind the scenes. But the broader question survives those qualifications. Suppose the input is a proprietary application whose owner has not authorized the rewrite. Suppose the goal is to reproduce its distinctive implementation and appearance closely enough to replace it. Should we be able to feed that product into an automated translator, change its language, and declare the result new and independent work? I think that deserves considerably more scrutiny than it’s currently receiving. This matters me personally because of

[17:01] Task Manager T-Clock. When I used AI to help build that, I specifically did not feed an existing application into the process and then just asked for a translation. Instead, I wrote a 107-page specification describing exactly what I wanted and then it took another 400 to 500 GitHub PRs to get it to that point. That meant making decisions about the product and expressing those decisions before asking the AI to implement them. A specification isn’t automatically innocent, either, cuz you could put somebody else’s protected expression into a specification and use the extra

[17:32] step to disguise the copying. Even starting from a prompt isn’t proof of legality. But there’s a meaningful difference between designing the behavior you want and using another application’s implementation as the raw material for your own. That’s the distinction that I want us to preserve. When the route is my requirements, generated code, compiled application, I can describe the AI as helping me implement my design. But when the route starts with an existing binary, proceeds through analysis of that binary, and ends with a replacement of that binary, I want the result identified as a clone

[18:04] derived from that application. Permission may make it perfectly legitimate. It still has an ancestor. My objection is to using the translation step to claim the original work contributed nothing. If your process depends on somebody else’s application or creative input of any kind, acknowledge and embrace that dependency. And if you’re reproducing protected expression, calling the output Rust doesn’t supply permission. A compiler produces an executable. It does not produce a certificate of independent authorship. Now, extend the thought experiment to

[18:34] Photoshop or taking Final Cut from the Mac and producing a Windows version. Those are much bigger engineering problems, at least to get them right and have them work. And if you’re curious, the big replacements tend not to work very well, from what I’ve seen. Cuz a large application depends on libraries, assets, file formats, plugins, and operating system services that won’t obligingly turn into portable Rust simply because they’re asked nicely. Calculator doesn’t demonstrate that we can port Final Cut tomorrow. No, any timetable I give you would be speculation. What it does demonstrate is

[19:06] why we should pay attention to the direction of travel. Reverse engineering has traditionally demanded a great deal of specialized work. AI can assist with interpreting the evidence and turning it into another implementation. If that becomes faster and more reliable, the economics of making an authorized substitute could change even while the legal principles remain familiar. And there are valuable possibilities here, too. A developer who owns an application could use these techniques to recover lost work or help migrate it. With permission, reconstructing old software in a maintainable language could be a terrific tool. The same

[19:38] capability becomes much less appealing when the application’s owner is simply treated as an inconvenient detail. We began by asking whether an AI could work backwards from a Windows executable and forward again into a Rust application. In this experiment, it produced a working reconstruction. The answer of a perfect equivalent still depends on verification, and the answer about legality depends on more than the language that we compiled it in. My view is that feeding somebody a proprietary application into an automated rewrite to manufacture an unauthorized substitute should be

[20:10] illegal. Existing law may already prohibit particular cases. I won’t pretend a binary alone decides that. But a new language does not persuade me that the original work contributed nothing to the process. And now that you’ve watched the process and have a better understanding of it, consider how you’d feel if the application going through it were yours. If you found today’s episode interesting or entertaining, remember I’m mostly in this for the subs and likes. So, I’d be honored if you would consider leaving me one of each before you go today. Check out an episode of Shop Talk where we answer all of the week’s best questions and insights about the

[20:40] channel. In the meantime and in between time, I hope to see you next time, right here in Dave’s Garage. >> Do it, Glen. Do it. Do it.