A Aldeia Numaboa ancestral ainda está disponível para visitação. É a versão mais antiga da Aldeia que eu não quis simplesmente descartar depois de mais de 10 milhões de pageviews. Como diz a Sirley, nossa cozinheira e filósofa de plantão: "Misericórdia, ai que dó!"

Se você tiver curiosidade, o endereço é numaboa.net.br.

Leia mais...

Oficina

Bloco de Notas com linhas numeradas

Seg

28

Mai

2007


20:28

(22 votos, média 4.05 de 5) 


Enxertando o código no executável

Já temos um projeto de código, agora é preciso incluí-lo no executável. Mais uma vez, vamos por partes para não nos perdermos.

Inserindo o código da altura da janela

É preciso encontrar espaço ocioso no executável que possa ser utilizado para incluir o código. Usando o PE Explorer (faça o download do trial na Heaven Tools), verificamos o seguinte nos cabeçalhos das seções:

NomeTam.Virtual End.VirtualTam.DadosPonteiro CaracterísticasSobra
.text00003EFC 004010000000400000001000 60000020104 (260)
.data0000083C 004050000000100000005000 C00000407C4 (1988)
.idata00000E22 004060000000100000006000 400000401DE (478)
.rsrc00006000 004070000000600000007000 40000040-0-
.reloc00000AAE 0040D000000010000000D000 42000040552 (1362)
  • Procurando espaço livre

Vamos tomar a seção .data como exemplo. Esta seção foi dimensionada para ocupar um espaço de 1000 (tamanho dos dados) a partir do endereço 405000. Seu tamanho virtual é 83C e o espaço total disponível é de 1000, indicando que ainda há 7C4 bytes livres (1000 - 83C = 7C4). Tudo isto no sistema hexadecimal. Transformando os números para o sistema decimal, apenas por curiosidade, sabemos que o espaço reservado é de 4096, o espaço ocupado é de 2108, restando portanto 1988 bytes livres.

A segunda maior sobra de espaço se encontra na seção .reloc, onde há 1362 (552 em hexa) bytes disponíveis. Vamos escolher a seção .reloc para abrigar nosso código adicional. Ele cabe perfeitamente neste espaço livre, portanto, não vai haver a necessidade de ampliar o tamanho da seção escolhida.

  • Calculando o tamanho do salto

Segue-se agora uma longa jornada de cálculos. O primeiro deles será determinar o endereço do primeiro salto. Conforme visto anteriormente, foi decidido fazer um desvio no ponto onde o programa põe na pilha o valor da altura e da largura da janela-filha "edit". Reveja o trecho de código obtido através do debugador OllyDbg (note as referências preciosas que o programa fornece!):

0040121B 6A 01 PUSH 1 ;Erase = TRUE 0040121D A1 04504000 MOV EAX,DWORD PTR DS:[405004] 00401222 6A 00 PUSH 0 ;pRect = NULL 00401224 50 PUSH EAX ;hWnd => 000002A8 (class='Edit', ;wndproc=80573CEC, parent=00000414) 00401225 FF15 F4644000 CALL DWORD PTR DS:[<&USER32.InvalidateRect>] 0040122B 6A 01 PUSH 1 ;Repaint = TRUE 0040122D FF7424 0C PUSH DWORD PTR SS:[ESP+C] ;Height 00401231 FF7424 0C PUSH DWORD PTR SS:[ESP+C] ;Width 00401235 6A 00 PUSH 0 ;Y = 0 00401237 6A 00 PUSH 0 ;X = 0 00401239 F35 04504000 PUSH DWORD PTR DS:[405004] ;hWnd = 000002A8 (class='Edit', ;wndproc=80573CEC, parent=00000414) 0040123F FF15 F8644000 CALL DWORD PTR DS:[<&USER32.MoveWindow>] MoveWindow 00401245 C2 0800 RETN 8

Image O OllyDbg está disponível na seção de downloads em Informática / Debuggers.

Portanto, faremos um salto incondicional - jmp do endereço 40122D para o início do espaço vago da seção .reloc. Pelo cabeçalho de seções verificamos que o endereço virtual inicial de .reloc é 40D000 e nós queremos colocar o código adicional AAEh bytes adiante. Basta somar ao endereço virtual da seção o tamanho do código para obter o endereço inicial do código adicional, ou seja, 40D000 + AAE = 40DAAE. Nosso salto, então, deverá ser de 40122D para 40DAAE, o que corresponde a um salto de C881 bytes. Como sabemos que nossa instrução, por ser um salto longo, conterá 5 bytes, precisamos descontar os mesmos para calcular o valor correto para o salto: 40DAAE - 40122D - 5 = C87C.

De posse deste valor, vamos compor a instrução lembrando que a distância do salto é indicada em 4 bytes na ordem inversa, ou seja, 00 00 C8 7C será indicado como 7C C8 00 00:

Instrução Código hexadecimalObservação
JMP E9Salto incondicional longo
byte 1 7C
byte 2 C8
byte 3 00
byte 4 00Resultado: E9 7CC80000

Para o salto de retorno é preciso pular alguns bytes "para trás". No exemplo anterior, pulamos 51324 bytes "para frente", no retorno teremos que saltar 51343 bytes "para trás", ou seja, -51343 (menos 51343). Em hexadecimal, 401235 - 40DABF - 5 = FFFF3771.

  • Alterando o código para o salto

O programa original deve sofrer as seguintes alterações para a introdução do salto:

Endereço Código originalAlterar para
0040122D FF7424 0C PUSH DWORD PTR SS:[ESP+C]E9 7C C8 00
00401231 FF7424 0C PUSH DWORD PTR SS:[ESP+C]00 90 90 90
00401235 6A 00 PUSH 0

Observe que ocupamos apenas o primeiro byte (FF) da instrução no endereço 401231 para poder completar nossa instrução de salto. Restaram os códigos 74, 24 e 0C que foram anulados com três instruções NOP (90) para manter íntegro o tamanho do código original e não desestruturar outros endereçamentos existentes. Com o salto devidamente inserido, este bloco de código passa a ser:

Endereço Salto adicionado
0040122D E9 7CC80000JMP NOTEPAD.0040DAAE
00401232 90NOP
00401233 90NOP
00401234 90NOP
00401235 6A 00PUSH 0
  • Adicionando o código para alterar o tamanho da janela "edit"

Quando alcançar a linha 40122D, o salto é efetuado e a execução do código continua no endereço 40DAAE, exatamente o ponto onde vamos inserir o bloco 1 do código adicional. Nele, antes de refazermos as operações das linhas 40122D e 401231 que foram suprimidas para poder inserir o salto, a altura da janela "edit" é diminuída em 20 pixels. Para tanto, utilizamos o registrador EAX:

Endereço HexaOperaçãoObservações
0040DAAEE9 7CC80000 MOV EAX,DWORD PTR SS:[ESP+C]; Obtém o valor da altura
0040DAB283E8 14 SUB EAX,14; Subtrai 14h = 20d da altura
0040DAB5A3 70DB4000 MOV DWORD PTR DS:[40DB70],EAX; Guarda nova altura em 40DB70
0040DABA50 PUSH EAX; Nova altura na pilha
0040DABBFF7424 0C SS:[ESP+C]; Largura no topo da pilha
0040DABFE9 7137FFFF JMP NOTEPAD.00401235; Retorna ao ponto de chamada

Use um editor hexadecimal (Hackman ou Hacker's View, por exemplo) e faça as alterações propostas numa cópia do programa notepad.exe (o Hacker's View permite a entrada de código assembly e calcula os jumps, o que facilita muito o trabalho). Qualquer um dos programas sugeridos mostra o código a partir da posição 0 (zero) e NÃO pelo endereço virtual. Portanto, é preciso conhecer a posição dos endereços virtuais pelo seu deslocamento (offset) a partir da posição zero. Isto se consegue subtraindo a base da imagem (00400000) do endereço pretendido. Por exemplo, o deslocamento do endereço 40122D é 122D (40122D - 400000 = 122D). Caso você encontre dificuldades, o W32Dasm indica no rodapé o offset de cada linha de código wink

  • Testando a primeira etapa

Após fazer as modificações sugeridas é aconselhável testar o programa modificado. Tudo que esperamos é que a janela-filha "edit" tenha uma altura menor do que a janela principal. Se tudo correu bem, a janela do novo bloco de notas tem um "rodapé" de 20 pixels (a diferença de altura entre as duas janelas), o qual será usado para imprimir o texto com a indicação dos números das linhas.

notepad
Nova janela do bloco de notas

Informações adicionais