Técnicas AntiCracking – Parte II – Eliminação de Informação Simbólica
Se um desenvolvedor deseja se inteirar de como age um cracker deve testar se seu programa gera informações simbólicas antes de lançá-lo no mercado. Ainda que não seja possível remover toda essa informação da estrutura de um programa, modificar alguns pontos críticos pode ser crucial para o sucesso ou não da proteção.
A eliminação total não ocorre porque programamos em linguagens de alto nível, como C e C++, que são convertidas em instruções processáveis através de um compilador. É o compilador que acaba gerando dados que servem como “pontos de referências” para quem investiga um código disassemblado.
Os compiladores costumam gerar informações simbólicas – para representar as lincagens – quando convertem as relações de importação e exportação de tabelas e extensões. Um programa com grande uso de DLLs, onde cada uma exporta uma grande quantidade de funções, necessitará de uma lista relacionando onde estão as funções exportadas, normalmente indicando o que elas fazem, o que é de grande serventia para os crackers.
Para confundir as referências que possam ser lógicas para o cracker, vale a pena exportar as funções com números ao invés de nomes. Essa pequena medida é eficiente no atraso do trabalho de um cracker, especialmente se usadas linguagens de orientadas a objetos, como C++ e Turbo Pascal.
Pessoalmente, nas poucas vezes que me deparei com códigos numéricos referenciando subrotinas acabei desistindo do trabalho devido à exaustiva e tediosa tarefa de só me ter números com pouco sentido.
A questão da informação simbólica é diferente com as linguagens que geram um assembly em bytecode. Estas linguagens muitas vezes usam códigos nominais internos para a referenciação dos endereços. Então, todos nomes internos são preservados quando o programa é compilado. Por esta estrutura nominal, os bytecodes são mais facilmente decompilados que os códigos binários.
As strings não podem ser simplesmente eliminadas, mas elas podem ser recolocadas com outras strings de forma que as referências cruzadas não fiquem prejudicadas.
Veja o código que mantém as informações simbólicas:
#include < stdio .h >
#define NMAX 1000
#define APR0 "O CRIVO DE ERASTOTENES\n"
#define APR1 "Codigo com informacao simbolica explicita\n"
#define APR2 "www.sawp.com.br \n\n"
int pilhaCrivo[NMAX];
void apresentacao(){
printf(APR0);
printf(APR1);
printf(APR2);
}
void fazListaDeNumeros(){
int i=0;
for (i=2; i< =NMAX; i++) {
pilhaCrivo[i]=i;
}
}
void mostra(void){
int i,j;
for (i=2; i<=NMAX; i++) {
if (pilhaCrivo[i]==i) {
printf("%d \n", i);
for (j=i+i; j<=NMAX; j+=i) {
pilhaCrivo[j]=0;
}
}
}
}
int main() {
apresentacao();
fazListaDeNumeros();
mostra();
return 1;
}
Agora veja o código abaixo, onde as informações simbólicas foram removidas:
#include < 8203099666.h >
#include < 1010011010.h >
#include < 75981212.h >
using std::string;
using std::cout;
#define N32MMX2 1000
#define APR1 "Htinlt%htr%nsktwrfhft%xnrgtqnhf%j}uqnhnyf3"
#define APR2 "|||3xf|u3htr3gw"
#define APR0
T%HWN[T%IJ%JWFXYTYJSJX
int PH040x12[N32MMX2];
void rot13_d3c0d3(string & INx990012){
const int kkk=5;
int a5c11c0d3;
for(int i=0;i< inx990012 .length();i++) {
a5c11c0d3 = static_cast< int >(INx990012[i])- kkk;
INx990012[i] = static_cast< char >(a5c11c0d3);
}
}
void st4rt3R_09833(){
string h0xx3232122[] = {APR0, APR1, APR2};
rot13_d3c0d3(h0xx3232122[0]);
rot13_d3c0d3(h0xx3232122[1]);
rot13_d3c0d3(h0xx3232122[2]);
cout < < h0xx3232122[0] < < "\n" < < h0xx3232122[1] < < "\n" < < h0xx3232122[2] < < "\n\n";
}
void HP00x98765432(){
int i=0;
for (i=2; i <= N32MMX2; i++) {
PH040x12[i]=i;
}
}
void IB00x98701234(void){
int i,j;
for (i=2; i <= N32MMX2; i++) {
if (PH040x12[i]==i) {
printf("%d \n", i);
for (j=i+i; j <= N32MMX2; j+=i) {
PH040x12[j]=0;
}
}
}
}
int main() {
st4rt3R_09833();
HP00x98765432();
IB00x98701234();
return 1;
}
Da mesma forma, comparemos o código em assembly:
.file "main.c"
.section .rdata,"dr"
LC0:
.ascii "O CRIVO DE ERASTOTENES\12\0"
.align 4
LC1:
.ascii "Codigo com informacao simbolica explicita\12\0"
LC2:
.ascii "www.sawp.com.br \12\12\0"
.text
.globl _apresentacao
.def _apresentacao; .scl 2; .type 32; .endef
_apresentacao:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $LC0, (%esp)
call _printf
movl $LC1, (%esp)
call _printf
movl $LC2, (%esp)
call _printf
leave
ret
.globl _fazListaDeNumeros
.def _fazListaDeNumeros; .scl 2; .type 32; .endef
_fazListaDeNumeros:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $0, -4(%ebp)
movl $2, -4(%ebp)
L3:
cmpl $1000, -4(%ebp)
jg L2
movl -4(%ebp), %edx
movl -4(%ebp), %eax
movl %eax, _pilhaCrivo(,%edx,4)
leal -4(%ebp), %eax
incl (%eax)
jmp L3
L2:
leave
ret
.section .rdata,"dr"
LC3:
.ascii "%d \12\0"
.text
.globl _mostra
.def _mostra; .scl 2; .type 32; .endef
_mostra:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $2, -4(%ebp)
L7:
cmpl $1000, -4(%ebp)
jg L6
movl -4(%ebp), %eax
movl _pilhaCrivo(,%eax,4), %eax
cmpl -4(%ebp), %eax
jne L9
movl -4(%ebp), %eax
movl %eax, 4(%esp)
movl $LC3, (%esp)
call _printf
movl -4(%ebp), %eax
addl -4(%ebp), %eax
movl %eax, -8(%ebp)
L11:
cmpl $1000, -8(%ebp)
jg L9
movl -8(%ebp), %eax
movl $0, _pilhaCrivo(,%eax,4)
movl -4(%ebp), %edx
leal -8(%ebp), %eax
addl %edx, (%eax)
jmp L11
L9:
leal -4(%ebp), %eax
incl (%eax)
jmp L7
L6:
leave
ret
.def ___main; .scl 2; .type 32; .endef
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
call __alloca
call ___main
call _apresentacao
call _fazListaDeNumeros
call _mostra
movl $1, %eax
leave
ret
.comm _pilhaCrivo, 4000 # 4000
.def _printf; .scl 2; .type 32; .endef
Agora o mesmo código sem informações simbólicas explícitas:
.file "main.cpp"
.text
.align 2
.def __ZSt17__verify_groupingPKcjRKSs; .scl 3; .type 32; .endef
__ZSt17__verify_groupingPKcjRKSs:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl 16(%ebp), %eax
movl %eax, (%esp)
call __ZNKSs4sizeEv
decl %eax
movl %eax, -4(%ebp)
movl 12(%ebp), %eax
decl %eax
movl %eax, -12(%ebp)
leal -12(%ebp), %eax
movl %eax, 4(%esp)
leal -4(%ebp), %eax
movl %eax, (%esp)
call __ZSt3minIjERKT_S2_S2_
movl (%eax), %eax
movl %eax, -8(%ebp)
movl -4(%ebp), %eax
movl %eax, -16(%ebp)
movb $1, -17(%ebp)
movl $0, -24(%ebp)
L2:
movl -24(%ebp), %eax
cmpl -8(%ebp), %eax
jae L5
cmpb $0, -17(%ebp)
je L5
movl -16(%ebp), %eax
movl %eax, 4(%esp)
movl 16(%ebp), %eax
movl %eax, (%esp)
call __ZNKSsixEj
movsbl (%eax),%edx
movl 8(%ebp), %eax
addl -24(%ebp), %eax
movsbl (%eax),%eax
cmpl %eax, %edx
sete %al
movb %al, -17(%ebp)
leal -16(%ebp), %eax
decl (%eax)
leal -24(%ebp), %eax
incl (%eax)
jmp L2
L5:
cmpl $0, -16(%ebp)
je L6
cmpb $0, -17(%ebp)
je L6
movl -16(%ebp), %eax
movl %eax, 4(%esp)
movl 16(%ebp), %eax
movl %eax, (%esp)
call __ZNKSsixEj
movsbl (%eax),%edx
movl 8(%ebp), %eax
addl -8(%ebp), %eax
movsbl (%eax),%eax
cmpl %eax, %edx
sete %al
movb %al, -17(%ebp)
leal -16(%ebp), %eax
decl (%eax)
jmp L5
L6:
movl $0, 4(%esp)
movl 16(%ebp), %eax
movl %eax, (%esp)
call __ZNKSsixEj
movsbl (%eax),%edx
movl 8(%ebp), %eax
addl -8(%ebp), %eax
movsbl (%eax),%eax
cmpl %eax, %edx
jg L8
movzbl -17(%ebp), %eax
andl $1, %eax
movb %al, -25(%ebp)
jmp L9
L8:
movb $0, -25(%ebp)
L9:
movzbl -25(%ebp), %eax
movb %al, -17(%ebp)
movzbl -17(%ebp), %eax
leave
ret
.lcomm __ZSt8__ioinit,16
.globl _PH040x12
.bss
.align 32
_PH040x12:
.space 4000
.text
.align 2
.globl __Z12rot13_d3c0d3RSs
.def __Z12rot13_d3c0d3RSs; .scl 2; .type 32; .endef
__Z12rot13_d3c0d3RSs:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $5, -4(%ebp)
movl $0, -12(%ebp)
L11:
movl 8(%ebp), %eax
movl %eax, (%esp)
call __ZNKSs6lengthEv
cmpl %eax, -12(%ebp)
jae L10
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call __ZNSsixEj
movsbl (%eax),%eax
subl $5, %eax
movl %eax, -8(%ebp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call __ZNSsixEj
movl %eax, %edx
movl -8(%ebp), %eax
movb %al, (%edx)
leal -12(%ebp), %eax
incl (%eax)
jmp L11
L10:
leave
ret
.def __Unwind_SjLj_Resume; .scl 2; .type 32; .endef
.def ___gxx_personality_sj0; .scl 2; .type 32; .endef
.def __Unwind_SjLj_Register; .scl 2; .type 32; .endef
.def __Unwind_SjLj_Unregister; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "T%HWN[T%IJ%JWFXYTYJSJX\0"
.align 4
LC1:
.ascii "Htinlt%htr%nsktwrfhft%xnrgtqnhf%j}uqnhnyf3\0"
LC2:
.ascii "|||3xf|u3htr3gw\0"
LC3:
.ascii "\12\0"
LC4:
.ascii "\12\12\0"
.text
.align 2
.globl __Z13st4rt3R_09833v
.def __Z13st4rt3R_09833v; .scl 2; .type 32; .endef
__Z13st4rt3R_09833v:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $172, %esp
movl $___gxx_personality_sj0, -84(%ebp)
movl $LLSDA1426, -80(%ebp)
leal -76(%ebp), %eax
leal -24(%ebp), %edx
movl %edx, (%eax)
movl $L47, %edx
movl %edx, 4(%eax)
movl %esp, 8(%eax)
leal -108(%ebp), %eax
movl %eax, (%esp)
call __Unwind_SjLj_Register
leal -40(%ebp), %eax
movl %eax, -112(%ebp)
movl -112(%ebp), %edx
movl %edx, -116(%ebp)
movl $2, -120(%ebp)
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcEC1Ev
leal -56(%ebp), %eax
movl %eax, 8(%esp)
movl $LC0, 4(%esp)
movl -116(%ebp), %eax
movl %eax, (%esp)
movl $4, -104(%ebp)
call __ZNSsC1EPKcRKSaIcE
jmp L16
L15:
movl -128(%ebp), %edx
movl %edx, -124(%ebp)
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcED1Ev
movl -124(%ebp), %eax
movl %eax, -128(%ebp)
L17:
jmp L27
L16:
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcED1Ev
addl $4, -116(%ebp)
decl -120(%ebp)
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcEC1Ev
leal -56(%ebp), %eax
movl %eax, 8(%esp)
movl $LC1, 4(%esp)
movl -116(%ebp), %edx
movl %edx, (%esp)
movl $3, -104(%ebp)
call __ZNSsC1EPKcRKSaIcE
jmp L20
L19:
movl -128(%ebp), %eax
movl %eax, -132(%ebp)
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcED1Ev
movl -132(%ebp), %edx
movl %edx, -128(%ebp)
L21:
jmp L27
L20:
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcED1Ev
addl $4, -116(%ebp)
decl -120(%ebp)
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcEC1Ev
leal -56(%ebp), %eax
movl %eax, 8(%esp)
movl $LC2, 4(%esp)
movl -116(%ebp), %eax
movl %eax, (%esp)
movl $2, -104(%ebp)
call __ZNSsC1EPKcRKSaIcE
jmp L24
L23:
movl -128(%ebp), %edx
movl %edx, -136(%ebp)
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcED1Ev
movl -136(%ebp), %eax
movl %eax, -128(%ebp)
L25:
jmp L27
L24:
leal -56(%ebp), %eax
movl %eax, (%esp)
call __ZNSaIcED1Ev
decl -120(%ebp)
jmp L28
L27:
movl -128(%ebp), %edx
movl %edx, -140(%ebp)
cmpl $0, -112(%ebp)
je L30
movl $2, %eax
subl -120(%ebp), %eax
movl %eax, -144(%ebp)
movl -144(%ebp), %eax
sall $2, %eax
movl -112(%ebp), %edx
addl %eax, %edx
movl %edx, -144(%ebp)
L31:
movl -144(%ebp), %eax
cmpl %eax, -112(%ebp)
je L30
subl $4, -144(%ebp)
movl -144(%ebp), %edx
movl %edx, (%esp)
movl $0, -104(%ebp)
call __ZNSsD1Ev
jmp L31
L30:
movl -140(%ebp), %eax
movl %eax, -128(%ebp)
L33:
movl -128(%ebp), %edx
movl %edx, (%esp)
movl $-1, -104(%ebp)
call __Unwind_SjLj_Resume
L28:
leal -40(%ebp), %eax
movl %eax, (%esp)
movl $1, -104(%ebp)
call __Z12rot13_d3c0d3RSs
leal -40(%ebp), %eax
addl $4, %eax
movl %eax, (%esp)
call __Z12rot13_d3c0d3RSs
leal -40(%ebp), %eax
addl $8, %eax
movl %eax, (%esp)
call __Z12rot13_d3c0d3RSs
leal -40(%ebp), %eax
movl %eax, 4(%esp)
movl $__ZSt4cout, (%esp)
call __ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSbIS4_S5_T1_E
movl $LC3, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
leal -40(%ebp), %edx
addl $4, %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call __ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSbIS4_S5_T1_E
movl $LC3, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
leal -40(%ebp), %edx
addl $8, %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call __ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSbIS4_S5_T1_E
movl $LC4, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
jmp L36
L47:
leal 24(%ebp), %ebp
movl -104(%ebp), %eax
movl %eax, -156(%ebp)
movl -100(%ebp), %edx
movl %edx, -128(%ebp)
cmpl $1, -156(%ebp)
je L23
cmpl $2, -156(%ebp)
je L19
cmpl $3, -156(%ebp)
je L15
L35:
movl -128(%ebp), %eax
movl %eax, -148(%ebp)
leal -40(%ebp), %eax
testl %eax, %eax
je L38
leal -40(%ebp), %edx
movl %edx, -152(%ebp)
addl $12, -152(%ebp)
L39:
leal -40(%ebp), %eax
cmpl -152(%ebp), %eax
je L38
subl $4, -152(%ebp)
movl -152(%ebp), %eax
movl %eax, (%esp)
movl $0, -104(%ebp)
call __ZNSsD1Ev
jmp L39
L38:
movl -148(%ebp), %edx
movl %edx, -128(%ebp)
L41:
movl -128(%ebp), %eax
movl %eax, (%esp)
movl $-1, -104(%ebp)
call __Unwind_SjLj_Resume
L36:
leal -40(%ebp), %eax
testl %eax, %eax
je L14
leal -40(%ebp), %edx
movl %edx, -152(%ebp)
addl $12, -152(%ebp)
L45:
leal -40(%ebp), %eax
cmpl -152(%ebp), %eax
je L14
subl $4, -152(%ebp)
movl -152(%ebp), %eax
movl %eax, (%esp)
movl $-1, -104(%ebp)
call __ZNSsD1Ev
jmp L45
L14:
leal -108(%ebp), %eax
movl %eax, (%esp)
call __Unwind_SjLj_Unregister
addl $172, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
.section .gcc_except_table,"dr"
LLSDA1426:
.byte 0xff
.byte 0xff
.byte 0x1
.uleb128 LLSDACSE1426-LLSDACSB1426
LLSDACSB1426:
.uleb128 0x0
.uleb128 0x0
.uleb128 0x1
.uleb128 0x0
.uleb128 0x2
.uleb128 0x0
.uleb128 0x3
.uleb128 0x0
LLSDACSE1426:
.text
.align 2
.globl __Z13HP00x98765432v
.def __Z13HP00x98765432v; .scl 2; .type 32; .endef
__Z13HP00x98765432v:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $0, -4(%ebp)
movl $2, -4(%ebp)
L49:
cmpl $1000, -4(%ebp)
jg L48
movl -4(%ebp), %edx
movl -4(%ebp), %eax
movl %eax, _PH040x12(,%edx,4)
leal -4(%ebp), %eax
incl (%eax)
jmp L49
L48:
leave
ret
.section .rdata,"dr"
LC5:
.ascii "%d \12\0"
.text
.align 2
.globl __Z13IB00x98701234v
.def __Z13IB00x98701234v; .scl 2; .type 32; .endef
__Z13IB00x98701234v:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $2, -4(%ebp)
L53:
cmpl $1000, -4(%ebp)
jg L52
movl -4(%ebp), %eax
movl _PH040x12(,%eax,4), %eax
cmpl -4(%ebp), %eax
jne L55
movl -4(%ebp), %eax
movl %eax, 4(%esp)
movl $LC5, (%esp)
call _printf
movl -4(%ebp), %eax
addl -4(%ebp), %eax
movl %eax, -8(%ebp)
L57:
cmpl $1000, -8(%ebp)
jg L55
movl -8(%ebp), %eax
movl $0, _PH040x12(,%eax,4)
movl -4(%ebp), %edx
leal -8(%ebp), %eax
addl %edx, (%eax)
jmp L57
L55:
leal -4(%ebp), %eax
incl (%eax)
jmp L53
L52:
leave
ret
.def ___main; .scl 2; .type 32; .endef
.align 2
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
call __alloca
call ___main
call __Z13st4rt3R_09833v
call __Z13HP00x98765432v
call __Z13IB00x98701234v
movl $1, %eax
leave
ret
.section .text$_ZSt3minIjERKT_S2_S2_,"x"
.linkonce discard
.align 2
.globl __ZSt3minIjERKT_S2_S2_
.def __ZSt3minIjERKT_S2_S2_; .scl 2; .type 32; .endef
__ZSt3minIjERKT_S2_S2_:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 12(%ebp), %eax
movl 8(%ebp), %edx
movl (%eax), %eax
cmpl (%edx), %eax
jae L62
movl 12(%ebp), %eax
movl %eax, -4(%ebp)
jmp L61
L62:
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
L61:
movl -4(%ebp), %eax
leave
ret
.text
.align 2
.def __Z41__static_initialization_and_destruction_0ii; .scl 3; .type 32; .endef
__Z41__static_initialization_and_destruction_0ii:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
cmpl $65535, 12(%ebp)
jne L64
cmpl $1, 8(%ebp)
jne L64
movl $__ZSt8__ioinit, (%esp)
call __ZNSt8ios_base4InitC1Ev
L64:
cmpl $65535, 12(%ebp)
jne L63
cmpl $0, 8(%ebp)
jne L63
movl $__ZSt8__ioinit, (%esp)
call __ZNSt8ios_base4InitD1Ev
L63:
leave
ret
.align 2
.def __GLOBAL__I_PH040x12; .scl 3; .type 32; .endef
__GLOBAL__I_PH040x12:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $65535, 4(%esp)
movl $1, (%esp)
call __Z41__static_initialization_and_destruction_0ii
leave
ret
.section .ctors,"w"
.align 4
.long __GLOBAL__I_PH040x12
.text
.align 2
.def __GLOBAL__D_PH040x12; .scl 3; .type 32; .endef
__GLOBAL__D_PH040x12:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $65535, 4(%esp)
movl $0, (%esp)
call __Z41__static_initialization_and_destruction_0ii
leave
ret
.section .dtors,"w"
.align 4
.long __GLOBAL__D_PH040x12
.def __ZNSt8ios_base4InitD1Ev; .scl 2; .type 32; .endef
.def _printf; .scl 2; .type 32; .endef
.def __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc; .scl 2; .type 32; .endef
.def __ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSbIS4_S5_T1_E; .scl 2; .type 32; .endef
.def __ZNSsD1Ev; .scl 2; .type 32; .endef
.def __ZNSsC1EPKcRKSaIcE; .scl 2; .type 32; .endef
.def __ZNSaIcED1Ev; .scl 2; .type 32; .endef
.def __ZNSaIcEC1Ev; .scl 2; .type 32; .endef
.def __ZNSsixEj; .scl 2; .type 32; .endef
.def __ZNKSs6lengthEv; .scl 2; .type 32; .endef
.def __ZNSt8ios_base4InitC1Ev; .scl 2; .type 32; .endef
.def __ZNKSsixEj; .scl 2; .type 32; .endef
.def __ZNKSs4sizeEv; .scl 2; .type 32; .endef
</p>
Ambos códigos realizam a mesma tarefa: exibir a mensagem “O CRIVO DE ERASTOTENES. Codigo com informacao simbolica explicita. www.sawp.com.br” e em seguida-se calcula os números primos existentes de 2 à 1000.
Contudo, claramente observamos no segundo código que as strings não visíveis. Isso faz com que seja quase impossível para o cracker saber sobre o que se trata aquela informação, pois ele precisaria do código responsável pela decriptação da informação simbólica. No caso, a função responsável por tornar o texto visível para o usuário e invisível para o cracker é a “rot13_d3c0d3”.
Para quem tiver curiosidade, rot13_d3c0d3 substitui um caractere por outro que têm seu asccii-13. Veja:
void rot13ASC_decode(string & input){
const int key=13;
int asciicode;
for(int i=0;i < input .length();i++) {
asciicode = static_cast< int >(input[i])- key;
input[i] = static_cast< char >(asciicode);
}
}
</p>
Normalmente os crackers se deparam com codificações reversíveis, como BASE64, rot13,rot64, algum algoritmo derivado de Cifras de César-Vigenere ou algum algoritmo de transposição.
Notamos então que colocar as constantes em texto explícito é uma forma extremamente vulnerável por deixar pontos de referências para os crackers se localizarem na nossa aplicação.
Observamos também que o código assembly com as informações simbólicas removidas é muito mais extenso e possui muito mais instruções que o código original. Isso reforça uma das desvantagens descritas na PARTE 1 sobre anti-cracking: sempre há perda de desempenho ao implementar técnicas anticracking.
Este é um ponto importante e que deve sempre estar na cabeça do desenvolvedor. No nosso pequeno exemplo já tivemos um considerável aumento de instruções. E este crescimento é propagado quão maior for o código da aplicação, representando significativa perda de eficiência.
Deve-se ficar claro que o código aqui apresentado é apenas para exemplificar. Alguém que necessite proteger sua aplicação, certamente está trabalhando em um projeto grande, com vários arquivos-fontes, muitas classes e funções. Então, obviamente, não há como eliminar as informações simbólicas “na mão”.
O que as empresas que empregam técnicas anti-cracking fazem é construir parsers especiais e scripts especiais de compilação. Desta forma, o código ao invés de ser enviado direto para o compilador, são transformados por estes scripts em um código de sem informações simbólicas destes e só então são compilados.