Como o C / C ++ é mais difícil de decompilar do que o C #?

4

Veja a resposta principal aqui: Ofuscação no nível do código-fonte mais eficaz que os ofuscadores? , especificamente "Codifique-o em uma linguagem que não é fácil de descompilar como C / C ++"

Eu estou olhando para escrever um novo aplicativo que será vendido por US $ 500 por licença, então eu gostaria de evitar descompiladores.

O C # deve ser evitado ou está usando um ofuscador suficiente para evitar esse tipo de coisa?

    
por Michael 01.02.2013 / 22:16
fonte

3 respostas

13

Os assemblies C # contêm metadados que os assemblies c ++ não contêm, o que pode ajudar na descompilação. C # também compila para baixo para um idioma intermediário que mapeia muito melhor para o código-fonte original que a saída de código de máquina do C ++. Os ofuscadores podem ajudar, mas você não pode evitar engenharia reversa; você só pode dificultar.

Na prática, ninguém quer seu código de graça de qualquer maneira. As empresas querem ser legitimamente licenciadas; eles não querem se dar ao trabalho (ou exposição legal) de hackear seu código para obter uma licença gratuita. Por US $ 500 por licença, é improvável que você esteja segmentando consumidores comuns, portanto, os únicos interessados em hackear seu software serão aqueles que ainda não estão no seu mercado-alvo.

Portanto, tome precauções sensatas, como ter um esquema de licenciamento, códigos de instalação, telefone residencial ou o que for mais recente para proteger seu software e concentre seus esforços na adição de novos recursos para tornar seu software melhor e mais atraente, escolhendo o linguagem que fornece a melhor produtividade possível.

NB: Se você não está sendo roubado ocasionalmente pelos hackers, seu software não é importante o suficiente. Nesse ponto, você provavelmente pode contratar alguém para emitir avisos de remoção e trabalhar em melhores soluções tecnológicas.

    
por 01.02.2013 / 22:31
fonte
6

Fundamentalmente, qualquer programa executável pode ser desmontado e inspecionado. A facilidade com que uma engenharia reversa pode recriar o código-fonte original depende de quantas informações ou metadados sobre o código-fonte original existem no executável. A engenharia reversa pode descobrir os nomes das variáveis originais, funções, estruturas de dados, etc.? Um compilador basicamente "compacta" o código-fonte, transformando-o em um formato mais acessível à execução de máquinas, como código de máquina nativo ou código de byte, que é processado por um tempo de execução intermediário. Mas, em geral, a compactação é com perdas, o que significa que muitas informações sobre o código-fonte original simplesmente não estão lá. No entanto, certas saídas do compilador são mais com perdas do que outras.

C e C ++ geralmente compilam diretamente para código de máquina nativo. Mas nem o padrão C nem o C ++ descrevem o layout de um executável binário criado pelo compilador. Um otimizador do compilador C ++, por exemplo, está livre para fazer muitas coisas para aumentar o desempenho, incluindo a otimização de determinadas declarações de variáveis ou a remoção de funções e classes inteiras. Muito pouca informação sobre o código C ++ original necessariamente precisa existir no executável binário. Um engenheiro reverso ainda seria capaz de desmontá-lo, mas retirar qualquer código C ou C ++ da montagem seria um ato de adivinhação e interpretação.

C #, no entanto, compila para CIL (Common Intermediate Language). Normalmente, muito mais informações sobre o código fonte original, como conceitos orientados a objetos, incluindo estrutura de classes, podem ser obtidas da leitura do CIL do que da leitura, digamos, do código de máquina x86 altamente otimizado produzido a partir de um compilador C ++.

    
por 01.02.2013 / 22:39
fonte
2

C # não deve necessariamente ser evitado. Eu trabalho para o PreEmptive Solutions em sua equipe Dotfuscator , embora essa seja uma resposta bastante imparcial. (sem um único plug :))

O C # é inerentemente mais fácil de decompilar em código-fonte porque contém metadados e a maioria dos códigos C # deve estar de acordo com um conjunto de regras chamado "código verificável". Os decompiladores aproveitam a adesão a essas regras, juntamente com os metadados anexados, para tornar a descompilação muito melhor do que os decompiladores equivalentes de C ++. É difícil entrar em um entendimento completo do IL, mas basicamente cada classe em seu código acabará tendo metadados. É como o .Net impede que você tenha que enviar arquivos de cabeçalho ou de símbolos para alguém usar uma montagem / API que você escreve. E para o bit de código verificável, isso basicamente significa que você só pode usar o código que o tempo de execução do .Net pode verificar é "seguro". O tempo de execução é limitado em seus recursos de análise estática, portanto, há muito código que pode ser verificado como "seguro e correto", mas não será verificável pelo tempo de execução. Decompilers aproveitam esse conjunto de regras.

Se você estiver enviando um produto em C # e tiver o IP que deseja proteger, basicamente precisará usar um produto ofuscante. É o mesmo em idiomas / tempos de execução semelhantes, como Java. Produtos de ofuscação para .Net fazem uma variedade de coisas:

  • Ofuscar fluxo de controle (transformar instruções em loops com goto e reordenar tudo)
  • Injete instruções inúteis de não operação para "ocultar" o código real
  • Renomeie os metadados para que isso realmente não ajude. (transformando nomes de classes como FooBar em a )
  • Altere como as classes são estruturadas (movendo 5 métodos em um único método usando todos os argumentos dos 5 métodos)
  • Injete código ou metadados não verificáveis (embora isso geralmente seja facilmente derrotado por desfavorecidos)
  • Criptografar sequências para que elas não sejam apenas texto simples
  • Criptografar recursos, como arquivos de configuração anexados, páginas XAML, etc.
  • Adicionar proteção contra adulteração (detecção de que o aplicativo foi alterado)

Dependendo do ofuscador que você usa, esses métodos podem fazer com que, para todos os efeitos, o código seja uma enorme "caixa preta" sem mergulhar na IL e ofuscar a mão (muito demorado)

O C ++ tem a vantagem de que a ofuscação não é tão importante. Não há metadados, então os decompiladores têm muito mais dificuldade. No entanto, ainda há muitos hackers que podem ler o assembly x86. E os aplicativos C ++ são muito comuns. (bom) obfuscators C ++ também são muito mais difíceis de encontrar. Isso é porque eles são tão difíceis de ofuscar quanto descompilar. .Net tem um conjunto de regras que os ofuscadores usam para ler o seu código, e ofuscá-lo. C ++ não possui essas regras.

Então, em resumo

  • C # basicamente requer ofuscação
  • C ++ é muito mais difícil de descompilar, mas falta suporte a ofuscação
  • Não importa qual você escolher, sempre é possível quebrar . Tudo o que você pode fazer é atrasá-lo ou torná-lo indesejável para crack devido à quantidade de tempo necessária

Além disso, como mais uma nota. Obfuscadores C # que produzem código verificável basicamente fornecem um aplicativo que será executado em todos os lugares, contanto que eles tenham uma versão nova o suficiente de .Net. Obfuscadores C # que não produzem código verificável geralmente funcionam em todos os lugares, mas não são garantidos para. É possível que a Microsoft saia com alguma otimização JIT na próxima versão do .Net que irá quebrar seu código ofuscado não verificável. C ++ código inerentemente não costuma correr "em todos os lugares", mas geralmente faz. O código C ++ ofuscado provavelmente funcionará onde quer que você pretenda, mas não é garantido. Escrever C ++ correto e thread-safe é bastante difícil, muito menos preocupante com um ofuscador que estraga tudo.

    
por 02.02.2013 / 06:01
fonte