Ofuscação de código em Java
- O que é ofuscação?
- Técnicas de Ofuscação de Código
- Ferramentas de ofuscação de código para Java
- Ofuscação em Java
- Resumo
Este tutorial apresenta a ofuscação de código em Java e também lista alguns códigos de exemplo para entender o tópico.
Ofuscação é uma técnica de programação usada para tornar nosso código difícil de entender. Isso é feito para proteger nosso código-fonte de usuários mal-intencionados. Neste tutorial, aprenderemos mais sobre ofuscação.
O que é ofuscação?
- Ofuscação é o processo de tornar um trecho de código menos legível, difícil de entender e demorado.
- A ofuscação não afeta a execução do código, e o código continuará a fazer o que deveria.
- A ofuscação de código é usada para proteger nosso código de hackers e atacantes. Esses usuários mal-intencionados podem tentar fazer engenharia reversa em nosso código e tirar proveito de algumas deficiências de nosso código. Impedir a engenharia reversa de nosso código é um dos principais casos de uso de ofuscação.
- Hackers e atacantes também usam ofuscação para evitar que ferramentas antivírus detectem seu código hostil.
Técnicas de Ofuscação de Código
Existem muitas ferramentas de ofuscação de código e elas usam uma variedade de técnicas para evitar ataques. Em suma, a ofuscação usa lógica redundante e adiciona código indesejado para desviar o leitor ou uma ferramenta de engenharia reversa (como um descompilador).
Vamos discutir algumas das técnicas de ofuscação de código mais comuns.
- Renomeando variáveis e nomes de métodos: renomear variáveis e métodos em alguns nomes de difícil leitura ou usando caracteres não imprimíveis ou invisíveis é uma técnica de ofuscação comumente usada.
- Alterar o fluxo de controle: as ferramentas de ofuscação geralmente alteram o fluxo de controle do código. Isso fará com que o código execute a mesma tarefa, mas se torna difícil de seguir.
- Usando código fictício: algumas ferramentas geralmente incluem código falso que não tem nada a ver com a lógica original. Isso tornará o código difícil de fazer engenharia reversa.
- Alterar regularmente o código ofuscado: se atualizarmos regularmente o código ofuscado, todo o progresso do hacker no código anterior será perdido. O invasor terá que começar do zero no novo código.
- Criptografia: a criptografia de dados (como strings) evita que o hacker entenda o verdadeiro significado do código. A descriptografia pode ser realizada quando o código precisa ser executado.
Ferramentas de ofuscação de código para Java
Java, assim como qualquer outra linguagem de programação, está sujeito a ataques de engenharia reversa. Os descompiladores estão disponíveis para Java que podem facilmente fazer engenharia reversa do byte-code Java compilado. A seguir estão algumas das ferramentas de obfuscator Java mais populares.
ProGuard
JODE
JavaGuard
RetroGuard
jarg
yGuard
Ofuscação em Java
Vamos ofuscar o código simples mostrado abaixo usando uma ferramenta de ofuscação.
public class StringAddition {
public static void main(String args[]) {
String s1 = "a";
String s2 = "b";
String s3 = s1 + s2;
}
}
O código é ofuscado no código a seguir. Variáveis fictícias indesejadas e lógica são colocadas no código ofuscado. A lógica do código original é difícil de entender.
import b.n;
public class StringAddition {
private static final String[] d;
public static void main(final String[] array) {
Label_0054: {
break Label_0054;
Label_0003:
while (true) {
final String str = StringAddition.d[Integer.parseInt("1", 22) << 10017];
try {
new StringBuilder()
.append(str)
.append(StringAddition.d[24 << Integer.parseInt("9k1", 30)])
.toString();
return;
final String x = StringAddition.d[8388608 >>> 4183];
System.out.println(x);
}
// iftrue(Label_0003:, x.hashCode() == 1033634479)
// monitorenter(array)
// monitorenter(array)
catch (EnumConstantNotPresentException i) {
throw n.i = i;
}
}
}
}
static {
final char[] charArray =
"\u0e47\u0e59\u0093\u0cc1¥£®£®\u00d1®®®®½£®A\u00da\u00dc®£®®\u00d1®®®\u00c2\u00dc®A\u00da£\u00d1£®®®\u00d1®®\u00c2£\u00d1A\u00da£®\u00dc®®®®\u00d1®\u00c2£®>\u00da£®£\u00d1®®®®\u00d1\u00c2£®A¥£®£®®®®®®½\u00f6\u00d1b\u00f9\u009e\u00d1\u0080\u008d\u008d\u0083\u00d1\u008d\u008d\u00e1\u009d\u00d1b\u00f9\u0080\u009f\u00dc\u008d\u008d\u008d\u0092\u00d1\u008d\u00e1\u0080\u0099>\u00f9\u0080\u008d\u0090\u00d1\u008d\u008d\u008d\u009e\u00d1\u00e1\u0080\u008d}¥\u0080\u008d\u0080\u009a\u00d1\u008d\u008d\u008d\u00df½\u0080\u008db\u00eb\u00dc\u008d\u0080\u008d\u0094\u00d1\u008d\u008d\u008d\u00e9\u00dc\u008db\u00f9\u00dc\u00d1\u00dc\u00d1\u00d1\u00d1\u00d1\u008d\u008d\u0097\u00dc\u008db\u00da£\u008d\u0080\u008d®®\u008d\u008d\u008d\u00c2£\u008db\u00f9£®\u0080\u008d\u008d®®\u008d\u008d\u00e1£®b\u00f9\u0080®£\u008d\u008d\u008d®®\u008d\u00e1\u0080®A\u00f9\u0080\u008d£®\u008d\u008d\u008d®®\u00e1\u0080\u008dA\u00da\u0080\u008d\u0080®®\u008d\u008d\u008d®\u00c2\u0080\u008db\u00da£®£®®®\u008d\u008d\u00fb½\u0080\u00deA\u00da \u008d\u00d3®®\u00ad\u008d\u00de®\u00c2 \u008d1\u00da£\u00ad\u0080\u00de®®\u00ad\u008d\u00de\u00c2£\u00adbª£® \u008d\u00de®®\u00ad\u008d²£®B\u00f9\u00d3®£\u00ad\u008d\u00de®®\u00ad\u00e1\u00d3®A\u00d9\u0080\u00de£®\u00ad\u008d\u00de®®\u00c1\u0080\u00deA\u00da£®£®®\u00ad\u008d\u00fb\u00d1½£®A\u00da\u00dc®£®®\u00d1®®®\u00c2\u00dc®A\u00da£\u00d1£®®®\u00d1®®\u00c2£\u00d1A\u00da£®\u00dc®®®®\u00d1®\u00c2£®>\u00da£®£\u00d1®®®®\u00d1\u00c2£®A¥£®£®\u00d1®®®®½£®A\u00da\u00dc®£®®\u00d1\u00fb\u00d1\u008d\u00e1\u0093\u00d1b\u00f9\u0080\u0093\u00dc\u008d\u008d\u008d\u0097\u00d1\u008d\u00e1\u0080\u0084>\u00f9\u0080\u008d\u008f\u00d1\u008d\u008d\u008d\u0092\u00d1\u00e1\u0080\u008d\u007f¥\u0080\u008d\u0080\u0085\u00d1\u008d\u008d\u008d\u009e½\u0080\u008db\u00f7\u00dc\u008d\u0080\u008d\u00dc\u00d1\u008d\u008d\u008d\u00e9\u00dc\u008db\u00f9\u008e\u00d1\u0080\u008d\u008d\u0098\u00d1\u008d\u008d\u00e1\u009d\u00d1b\u00f9\u0080\u009d\u00dc\u008d\u008d\u00fb\u00d1\u008d\u008d\u00c2£\u008db\u00f9£®\u0080\u008d\u008d®®\u008d\u008d\u00e1£®b\u00f9\u0080®£\u008d\u008d\u008d®®\u008d\u00e1\u0080®A\u00f9\u0080\u008d£®\u008d\u008d\u008d®®\u00e1\u0080\u008dA\u00da\u0080\u008d\u0080®®\u008d\u008d\u008d®\u00c2\u0080\u008db\u00da£\u008d\u0080\u008d®®\u008d\u008d\u008d\u00c2£\u008db\u00f9£®\u0080\u008d\u00fb\u00d1\u008d\u00de®\u00c2 \u008d1\u00da£\u00ad\u0080\u00de®®\u00ad\u008d\u00de\u00c2£\u00adbª£® \u008d\u00de®®\u00ad\u008d²£®B\u00f9\u00d3®£\u00ad\u008d\u00de®®\u00ad\u00e1\u00d3®A\u00d9\u0080\u00de£®\u00ad\u008d\u00de®®\u00c1\u0080\u00deA\u00da \u008d\u00d3®®\u00ad\u008d\u00de®\u00c2 \u008d1\u00da£\u00ad\u0080\u00fb\u00d1\u00fb\u0e59\u0090"
.toCharArray();
int n = 64 << 5658;
final StackTraceElement stackTraceElement;
final int n2 = (stackTraceElement = new Throwable().getStackTrace()[107 >>> 11463])
.getMethodName()
.hashCode()
& Integer.parseInt("171h3c0", 22) - 149806781;
final char[] charArray2 = stackTraceElement.getClassName().toCharArray();
final char[] array = charArray;
final int n3 = 101 >>> 10951;
++n;
d = new String[array[n3] ^ Integer.parseInt("1g1nna6", 28) - 758393825 ^ n2];
int n4 = 26 >>> Integer.parseInt("gk9", 31);
Label_0101:
while (true) {
int n5;
final char[] value =
new char[n5 = (charArray[n++] ^ Integer.parseInt("ifjj061", 22) - 2122795820 ^ n2)];
int n6 = 72 << 11485;
Label_0334_Outer:
while (true) {
Label_0272: {
if (n5 <= 0) {
break Label_0272;
}
int n7 = charArray[n];
Label_0334:
while (true) {
Label_0388: {
switch (charArray2[n % charArray2.length] ^ (0xC999A060 ^ 0xC999A0AE)) {
case 160: {
break Label_0334;
}
case 162: {
break Label_0334;
}
case 131: {
break Label_0334;
}
case 163: {
break Label_0334;
}
case 167: {
break Label_0334;
}
case 136: {
break Label_0388;
}
case 170: {
break Label_0388;
}
case 186: {
break Label_0388;
}
case 139: {
break Label_0388;
}
case 171: {
break Label_0388;
}
}
while (true) {
value[n6] = (char) n7;
try {
++n6;
++n;
--n5;
// monitorexit(charArray)
n7 ^= -400944133 + 400944374;
continue Label_0334_Outer;
n7 ^= Integer.parseInt("83bdf8k", 22) - 925222572;
continue Label_0334_Outer;
continue Label_0334;
StringAddition.d[n4++] = new String(value).intern();
// iftrue(Label_0101:, n < charArray.length)
return;
n7 ^= Integer.parseInt("6j", 23) << 3840;
continue Label_0334_Outer;
n7 ^= 61440 >>> 11787;
continue Label_0334_Outer;
n7 ^= 364965749 - 364965616;
} catch (Throwable t) {
break;
}
}
} break;
}
}
}
}
}
}
Observe que o código acima pode não ser executado diretamente em um IDE porque um ofuscador também produz arquivos e dependências adicionais que precisam ser resolvidos antes de executar o programa.
Resumo
A ofuscação de código é feita para evitar ataques devido à engenharia reversa. Os invasores e hackers também usam a ofuscação para enganar o software antivírus e outras ferramentas de proteção. Observe que a engenharia reversa de um código não é impossibilitada por ferramentas de ofuscador de código. Eles tornam isso muito difícil e demorado.