Como faço para bloquear classes Java compiladas para evitar a descompilação?
Sei que deve ser um tema muito bem discutido na Internet, mas não consegui chegar a nenhuma conclusão após referi-los.
Muitas pessoas sugerem o ofuscador, mas eles apenas renomeiam classes, métodos e campos com sequências de caracteres difíceis de lembrar, mas e os valores constantes sensíveis?
Por exemplo, você desenvolveu o componente de criptografia e descriptografia com base em uma técnica de criptografia baseada em senha. Agora, neste caso, qualquer pessoa comum de Java pode usar JAD para descompilar o arquivo de classe e recuperar facilmente o valor da senha (definido como constante), bem como o salt e, por sua vez, pode descriptografar os dados escrevendo um pequeno programa independente!
Ou esses componentes sensíveis deveriam ser construídos em código nativo (por exemplo, VC ++) e chamá-los via JNI ?
fonte
Respostas:
Alguns dos ofuscadores de bytecode Java mais avançados fazem muito mais do que apenas mutilar o nome da classe. Zelix KlassMaster , por exemplo, também pode embaralhar seu fluxo de código de uma forma que o torna realmente difícil de seguir e funciona como um excelente otimizador de código ...
Além disso, muitos dos obfuscators também são capazes de embaralhar suas constantes de string e remover o código não utilizado.
Outra solução possível (não necessariamente excluindo a ofuscação) é usar arquivos JAR criptografados e um carregador de classe customizado que faz a descriptografia (de preferência usando a biblioteca de tempo de execução nativa).
Terceiro (e possivelmente oferecendo a proteção mais forte) é usar compiladores antecipados nativos como GCC ou Excelsior JET , por exemplo, que compilam seu código Java diretamente para um binário nativo específico de plataforma.
Em qualquer caso, você deve se lembrar disso, como diz o ditado estoniano "As fechaduras são para animais". O que significa que cada bit de código está disponível (carregado na memória) durante o tempo de execução e com habilidade, determinação e motivação suficientes, as pessoas podem e irão descompilar, decodificar e hackear seu código ... Seu trabalho é simplesmente tornar o processo tão desconfortável quanto você pode e ainda mantém a coisa funcionando ...
fonte
Contanto que eles tenham acesso aos dados criptografados e ao software que os descriptografa, basicamente não há como tornar isso totalmente seguro. Uma maneira de resolver isso antes é usar alguma forma de caixa preta externa para lidar com criptografia / descriptografia, como dongles, servidores de autenticação remota, etc. Mas mesmo assim, dado que o usuário tem acesso total ao seu próprio sistema, isso só torna as coisas difícil, não impossível - a menos que você possa vincular seu produto diretamente à funcionalidade armazenada na "caixa preta", como, digamos, servidores de jogos online.
fonte
Isenção de responsabilidade: não sou um especialista em segurança.
Parece uma má ideia: você está permitindo que alguém criptografe as coisas com uma chave 'oculta' que você deu a ele. Não acho que isso possa ser seguro.
Talvez as chaves assimétricas possam funcionar:
Não tenho certeza, mas acredito que o cliente pode realmente criptografar a chave de licença com a chave pública que você deu a ele. Você pode então descriptografá-lo com sua chave privada e criptografá-lo novamente.
Você pode manter um par separado de chaves públicas / privadas por cliente para ter certeza de que está realmente recebendo as coisas do cliente certo - agora você é responsável pelas chaves ...
fonte
Não importa o que você faça, ele pode ser 'descompilado'. Heck, você pode simplesmente desmontá-lo. Ou observe um despejo de memória para encontrar suas constantes. Você vê, o computador precisa conhecê-los, então seu código também precisará.
O que fazer em relação a isto?
Tente não enviar a chave como uma constante codificada em seu código: mantenha-a como uma configuração por usuário. Torne o usuário responsável por cuidar dessa chave.
fonte
@jatanp: ou melhor ainda, eles podem descompilar, remover o código de licença e recompilar. Com Java, realmente não acho que haja uma solução adequada e à prova de hack para esse problema. Nem mesmo um pequeno dongle do mal poderia impedir isso com Java.
Meus próprios gerentes de negócios se preocupam com isso, e eu penso demais. Mas, novamente, vendemos nosso aplicativo para grandes empresas que tendem a respeitar as condições de licenciamento - geralmente um ambiente seguro graças aos contadores de grãos e advogados. O próprio ato de descompilar pode ser ilegal se sua licença for escrita corretamente.
Portanto, devo perguntar: você realmente precisa de proteção reforçada como está procurando para sua aplicação? Como é sua base de clientes? (Corporações? Ou as massas de jogadores adolescentes, onde isso seria mais um problema?)
fonte
Se você está procurando uma solução de licenciamento, pode verificar a API TrueLicense . Baseia-se no uso de chaves assimétricas. No entanto, isso não significa que seu aplicativo não pode ser crackeado. Cada aplicativo pode ser quebrado com bastante esforço. O que é realmente importante, como Stu respondeu , é descobrir o quão forte você precisa de proteção.
fonte
Não acho que exista nenhum método antipirataria offline eficaz. A indústria de videogames tentou descobrir isso muitas vezes e seus programas sempre foram quebrados. A única solução é que o programa seja executado online ligado aos seus servidores, para que possa verificar a chave do lincense, e que exista apenas uma ligação ativa do licenciado de cada vez. É assim que World of Warcraft ou Diablo funcionam. Mesmo difícil, existem servidores privados desenvolvidos para contornar a segurança.
Dito isso, não acredito que médias / grandes corporações usem software copiado ilegal, porque o custo da licença para elas é mínimo (talvez, não sei quanto você vai cobrar por seu programa) em comparação com o custo de uma versão de teste.
fonte
Você pode usar a criptografia por código de bytes sem medo.
O fato é que o artigo citado acima “Cracking Java byte-code encryption” contém uma falácia lógica. A principal reivindicação do artigo é que antes de executar todas as classes, todas as classes devem ser descriptografadas e passadas para o
ClassLoader.defineClass(...)
método . mas isso não é verdade.A suposição perdida aqui é fornecida que eles estão sendo executados em um ambiente de tempo de execução Java autêntico ou padrão . Nada pode obrigar o aplicativo Java protegido não apenas a iniciar essas classes, mas até mesmo descriptografá-las e passá-las para
ClassLoader
. Em outras palavras, se você está no JRE padrão, você não pode interceptar odefineClass(...)
método porque o java padrão não tem API para este propósito, e se você usa JRE modificado com patchClassLoader
ou qualquer outro “truque de hacker”, não pode fazê-lo porque está protegido O aplicativo java não funcionará de todo e, portanto, você não terá nada para interceptar. E absolutamente não importa qual “localizador de patch” é usado ou qual truque é usado pelos hackers. Esses detalhes técnicos são uma história bem diferente.fonte
P: Se eu criptografar meus arquivos .class e usar um carregador de classe personalizado para carregá-los e descriptografá-los na hora, isso impedirá a descompilação?
R: O problema de impedir a descompilação do byte-code Java é quase tão antigo quanto a própria linguagem. Apesar de uma série de ferramentas de ofuscação disponíveis no mercado, os programadores Java novatos continuam a pensar em maneiras novas e inteligentes de proteger sua propriedade intelectual. Neste artigo de perguntas e respostas do Java, eu desfaço alguns mitos em torno de uma ideia frequentemente refeita em fóruns de discussão.
A extrema facilidade com que os arquivos .class Java podem ser reconstruídos em fontes Java que se assemelham muito aos originais tem muito a ver com os objetivos e compensações de design de byte-code Java. Entre outras coisas, o byte code Java foi projetado para compactação, independência de plataforma, mobilidade de rede e facilidade de análise por interpretadores de byte-code e compiladores dinâmicos JIT (just-in-time) / HotSpot. Indiscutivelmente, os arquivos .class compilados expressam a intenção do programador de forma tão clara que podem ser mais fáceis de analisar do que o código-fonte original.
Várias coisas podem ser feitas, se não para evitar a descompilação completamente, pelo menos para torná-la mais difícil. Por exemplo, como uma etapa de pós-compilação, você pode massagear os dados .class para tornar o código de byte mais difícil de ler quando descompilado ou mais difícil de descompilar em código Java válido (ou ambos). Técnicas como executar sobrecarga extrema de nome de método funcionam bem para o primeiro, e manipular o fluxo de controle para criar estruturas de controle que não são possíveis de representar por meio da sintaxe Java funcionam bem para o último. Os ofuscadores comerciais mais bem-sucedidos usam uma combinação dessas e de outras técnicas.
Infelizmente, ambas as abordagens devem realmente alterar o código que a JVM executará, e muitos usuários temem (com razão) que essa transformação possa adicionar novos bugs em seus aplicativos. Além disso, a renomeação de método e campo pode fazer com que as chamadas de reflexão parem de funcionar. Alterar os nomes reais da classe e do pacote pode interromper várias outras APIs Java (JNDI (Java Naming and Directory Interface), provedores de URL, etc.). Além dos nomes alterados, se a associação entre os deslocamentos do código de byte de classe e os números da linha de origem for alterada, a recuperação dos rastreamentos de pilha de exceção originais pode se tornar difícil.
Depois, há a opção de ofuscar o código-fonte Java original. Mas, fundamentalmente, isso causa um conjunto semelhante de problemas. Criptografar, não ofuscar?
Talvez o acima tenha feito você pensar: "Bem, e se, em vez de manipular o código de byte, eu criptografar todas as minhas classes após a compilação e descriptografá-las instantaneamente dentro da JVM (o que pode ser feito com um carregador de classes personalizado)? Então a JVM executa meu código de byte original e ainda não há nada para descompilar ou fazer engenharia reversa, certo? "
Infelizmente, você estaria errado, tanto ao pensar que foi o primeiro a ter essa ideia quanto ao pensar que ela realmente funciona. E o motivo não tem nada a ver com a força do seu esquema de criptografia.
fonte