Discuta este tópico no fórum

Se este conteúdo te ajudou, deixe um presente!

domingo, 24 de abril de 2011

Luiz 1 x 0 SW de gerenciamento de celular

Como responsável da área da computação em casa, eu estava realizando a migração do celular da mulher. Bem, vamos dizer que é um celular exótico: gradiente fabricado pela francesa Sagem. Para a época, o celular era muito bom e ainda funciona bem. Agora voltando ao assunto...

A ferramenta de exportação foi terceirizada para uma empresa que, claro, não suporta mais este celular e nem vende o produto que o fazia. Com muita luta, achei uma versão demo que faz o que eu queria, exceto pelo fato de ser limitada a 6 contatos (o celular tem algumas centenas deles). Procura aqui, ali e nada de solução. Conclui que eu teria que fazer isto sozinho!

Tem um debugger para windows muito bom: w32dsm. Faz milagres. Pena que eu não tive assembly x86 na universidade. Com ele, busquei qualquer referencia a string "contacts" na memoria e coloquei um breakpoint depois de cada uma. Rodei o programa e foi contando o breakpoint que batia 6 vezes. E não é que eu achei?!

String Resource ID=17035: "Reading contacts: Mobile memory"

Desta forma, existe algum loop do tipo:

while ??? {
    ???
    chamada1()
    ???
}
chamada1 ( ) { chamada2 () }
(...)
chamadaX () { char[] str = "Reading contacts: Mobile memory" }

Com esta informação, fuirastreando (stepover) as chamadas "ret" do assembly que representam o retorno da chamada de função até o ponto onde o stepover bateu novamente no breakpoint da string. Isto me indicou que eu havia chegado no loop de leitura dos contatos. Voltei para as intruções do loop e analisei uma passada completa. O resultado não foi nada inovador. Algumas comparações no começo do loop, muita coisa no meio e um incremental no final: o bom e velho "for":


for (i-0;???;i++) {
    ???
    chamada1()
    ???
}
Bastou observar com cuidado para ver qual comparação gerava o jump para fora do loop. Na sexta iteração, achei uma comparação interessante entre o EAX (neste caso, i) e uma região da memória EBP+018. Mais sugestivo é que a comparação é >=. Quando ambos eram 6, o processo saia do loop. Olhando este EAX+018, ele possui o valor 6 desde o início do loop.


a=6;
for (i-0;???;i++) {
    if (i >= a) break;
    chamada1()
    ???
}
Agora é a parte fácil :-) Durante um loop qualquer, ainda pelo debugger, troquei o valor da memória para algo como 0x1000, retirei o breakpoint e fui para o abraço. Se fosse fazer algo permanente, teria que trocar a intrução do jump para uma nop ou modificar a comparação para que esta sempre desse negativa.

Já tinha feito algo parecido no passado mas com if e não for. O loop é muito mais fácil de identificar.

O pior de tudo: vou ganhar só um "ah tah... obrigada" por todo este trabalho :-(

3 comentários: