Moderadores Leandro Fróes Postado Outubro 8, 2017 em 22:50 Moderadores Compartilhar Postado Outubro 8, 2017 em 22:50 Boa noite pessoal! Essas semanas andam meio corridas e não consegui estudar do jeito que gostaria, mas ainda sim bora lá, o importante é estudar, certo? Peço que dêem uma olhada na estrutura do post passado (IMAGE_OPTIONAL_HEADER) e observem o último campo: IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; Para quem manja de C já bate o olho e de cara nota que isso é um array de estruturas chamado DataDirectory de tamanho IMAGE_NUMBEROF_DIRECTORY_ENTRIES e do tipo IMAGE_DATA_DIRECTORY Se dermos uma olhada na biblioteca winnt.h podemos ver que há um valor pré-definido de 16 para o campo IMAGE_NUMBEROF_DIRECTORY_ENTRIES #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 A estrutura 'DataDirectory' segue o seguinte escopo: typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; Esta estrutura possui, respectivamente, RVAs e Tamanhos de tabelas usadas em tempo de execução que podem ser usadas pelo Windows. Aqui está nossa referência: Offset (PE/PE32+) Size Field Description 96/112 8 Export Table The export table address and size. For more information see section 6.3, “The .edata Section (Image Only).” 104/120 8 Import Table The import table address and size. For more information, see section 6.4, “The .idata Section.” 112/128 8 Resource Table The resource table address and size. For more information, see section 6.9, “The .rsrc Section.” 120/136 8 Exception Table The exception table address and size. For more information, see section 6.5, “The .pdata Section.” 128/144 8 Certificate Table The attribute certificate table address and size. For more information, see section 5.7, “The Attribute Certificate Table (Image Only).” 136/152 8 Base Relocation Table The base relocation table address and size. For more information, see section 6.6, "The .reloc Section (Image Only)." 144/160 8 Debug The debug data starting address and size. For more information, see section 6.1, “The .debug Section.” 152/168 8 Architecture Reserved, must be 0 160/176 8 Global Ptr The RVA of the value to be stored in the global pointer register. The size member of this structure must be set to zero. 168/184 8 TLS Table The thread local storage (TLS) table address and size. For more information, see section 6.7, “The .tls Section.” 176/192 8 Load Config Table The load configuration table address and size. For more information, see section 6.8, “The Load Configuration Structure (Image Only).” 184/200 8 Bound Import The bound import table address and size. 192/208 8 IAT The import address table address and size. For more information, see section 6.4.4, “Import Address Table.” 200/216 8 Delay Import Descriptor The delay import descriptor address and size. For more information, see section 5.8, “Delay-Load Import Tables (Image Only).” 208/224 8 CLR Runtime Header The CLR runtime header address and size. For more information, see section 6.10, “The .cormeta Section (Object Only).” 216/232 8 Reserved, must be zero Aqui está nosso array, cada diretório representa um índice nesta lista. Vou pegar apenas um como exemplo, tendo em vista que todos os outros seguem o mesmo modelo Este é o array na posição 1(considerando que estamos começando de zero). Este se chama Import Directory. Mais pra frente vou tentar falar melhor sobre ele, pois o danado é importante pra caramba. A primeira DWORD é o RVA da tabela (relativo ao BaseAddress) quando carregada em memória. A segunda DWORD é o tamanho dela em bytes. Que tal revermos alguns conceitos? Quando estamos olhando os bytes de um arquivo por meio de um editor/dumper hexa, estamos olhando diretamente para os bytes do arquivo em disco. Para quem está familiarizado com a seguinte instrução: FILE *fp; Saiba que isto significa um ponteiro para o primeiro byte do arquivo, isto é, o início em disco. Com um ponteiro para um arquivo podemos manipular(imprimir, alterar, pular) os bytes diretamente através de várias funções que estão a nossa disposição e isso tudo através de uma abstração chamada stream(abstração, interface, chame do que quiser). Nos nossos estudos estamos falando de um binário, não de um arquivo em formato texto! Mais algumas considerações legais: Por acaso o termo “Offset” significa algo pra vocês? Este significa deslocamento (em relação a algo). Lembram do RVA ? Relative Virtual Address? Ele tem a mesma ideia do offset e é relativo ao BaseAddress. Ainda não ficou claro? Vamos lá… Quando executamos um programa é reservado um espaço de memória para ele chamado Virtual Address Space, o Windows cria este espaço para cada processo criado. O ‘VirtualAddress’(VA), também conhecido como Linear Address, pode ser achado facilmente. Lembram que o RVA é o deslocamento relativo ao BaseAddress? Sendo assim: VA = BaseAddress + RVA Vamos para a próxima estrutura!! Lembram do campo 'NumberOfSections' no FileHeader? O valor daquele campo nos mostra uma coisa interessante: o número de entradas na Section Table. Ok, não faz sentido *-*. Bom, no primeiro byte após os headers (logo após o ‘OptionalHeader’) está localizado um array de 'SectionHeaders' (ou Section Table Entries, use o que lhe agradar mais). Podemos referenciar da seguinte forma: struct IMAGE_SECTION_HEADER SectionHeaders[Num_no_Optional] e cada seção com seu respectivo índice no array. A estrutura de cada SectionHeader segue o seguinte escopo: typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; No caso aqui não vou me preocupar em traduzir cada seção, tendo em vista que os campos do cabeçalho são iguais para todas. Vou apenas explicar pegando uma como exemplo e o resto deixo pra vocês Name O primeiro campo é um array de caracteres(uma string) com valor IMAGE_SIZEOF_SHORT_NAME, tá, mas o que é isso? Dê uma olhada neste campo do header winnt: #define IMAGE_SIZEOF_SHORT_NAME 8 Lá está o valor. Tenha em mente que são 8 bytes contando com um caractere nulo no fim da string(este caractere nulo é ignorado caso o nome tenha de fato 8 bytes). Há alguns detalhes a mais nesta definição, mas vou me preocupar apenas com a imagem de um executável, esta que suporta até 8 bytes em UTF-8 Note que cada byte representa um caractere do nome(no caso aqui é .text) e o resto é preenchido com zeros, ou seja, é feito um padding, um preenchimento para chegarmos ao valor definido pela diretiva #define =D Union (Misc) Pra você que estudou um pouco de estrutura de dados, sabe o que é uma union? Resumindo é parecida com uma struct, a questão é que o espaço de memória usado para as variáveis da union é compartilhado (geralmente em momentos diferentes). O compilador cria automaticamente uma variável grande o bastante para conter o maior tipo de variável da union. Voltando ao PE: PhysicalAddress e VirtualSize(Misc) Aqui temos duas DWORDS, uma indicando o endereço no arquivo e outra indicando o tamanho da seção depois que for carregada em memória(em bytes). Se este valor for maior que ‘SizeOfRawData’ a seção é preenchida com zeros. O campo ‘VirtualSize’ só é válido para imagens executáveis e será zero para arquivos objeto. No nosso caso deu 5744 bytes, 0x1670h VirtualAddress Para imagens executáveis é uma DWORD indicando o RVA, o primeiro byte da seção quando carregada em memória(lembrando que temos que somar ao 'BaseAddress'). Para arquivos objeto os compiladores setam este valor para zero Ali no canto esquerdo podemos ver o valor do VirtualAddress somado ao BaseAddress, resultando no primeiro byte da seção após ser carregada em memória =D SizeOfRawData Após o endereço virtual vêm 32 bits para os Tamanho dos Dados ('SizeOfRawData'), que nada mais é do que o tamanho dos dados da seção arredondado para cima, para o próximo múltiplo de 'FileAlignment' (alinhamento de arquivo). No nosso exemplo, o valor encontrado é 0000 1800, faça a conta e veja se é múltiplo mesmo =D. Caso a seção possua apenas dados não-inicializados este campo é preenchido com zeros(como é o caso da seção .bss ) PointerToRawData Este campo é bem interessante(não que os outros não sejam, claro). Para executáveis é uma DWORD indicando o offset dentro do arquivo(e deve ser múltiplo de 'FileAlignment') até os dados da seção propriamente ditos. Caso a seção possua apenas dados não-inicializados este campo é preenchido com zeros, de novo… No offset 400h na esquerda podemos ver justamente o início da seção .text em nosso arquivo PointerToRelocations, PointerToLinenumbers, NumberOfRelocations e NumberOfLineNumbers Aqui os dois primeiros campos são DWORDS e os seguintes WORDS. Todas estas informações somente são utilizadas para arquivos objeto, ou seja, estarão zeradas no nosso caso. Os executáveis não possuem um diretório de remanejamento base especial e a informação de número de linha, se é que está presente, geralmente está localizada num segmento especial para debugging ou em qualquer outro lugar. Para deixar um pouco mais claro(bem por cima): COFF Relocations (que só acontece em arquivos objeto) é a forma como os dados da seção devem ser modificados quando colocados na imagem e, posteriormente, carregados em memória. Characteristics Uma DWORD com uma porção de flags dizendo características da seção. Podemos dizer que é uma enum. Segue a documentação: Flag Value Description 0x00000000 Reserved for future use. 0x00000001 Reserved for future use. 0x00000002 Reserved for future use. 0x00000004 Reserved for future use. IMAGE_SCN_TYPE_NO_PAD 0x00000008 The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files. 0x00000010 Reserved for future use. IMAGE_SCN_CNT_CODE 0x00000020 The section contains executable code. IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 The section contains initialized data. IMAGE_SCN_CNT_UNINITIALIZED_ DATA 0x00000080 The section contains uninitialized data. IMAGE_SCN_LNK_OTHER 0x00000100 Reserved for future use. IMAGE_SCN_LNK_INFO 0x00000200 The section contains comments or other information. The .drectve section has this type. This is valid for object files only. 0x00000400 Reserved for future use. IMAGE_SCN_LNK_REMOVE 0x00000800 The section will not become part of the image. This is valid only for object files. IMAGE_SCN_LNK_COMDAT 0x00001000 The section contains COMDAT data. For more information, see section 5.5.6, “COMDAT Sections (Object Only).” This is valid only for object files. IMAGE_SCN_GPREL 0x00008000 The section contains data referenced through the global pointer (GP). IMAGE_SCN_MEM_PURGEABLE 0x00020000 Reserved for future use. IMAGE_SCN_MEM_16BIT 0x00020000 Reserved for future use. IMAGE_SCN_MEM_LOCKED 0x00040000 Reserved for future use. IMAGE_SCN_MEM_PRELOAD 0x00080000 Reserved for future use. IMAGE_SCN_ALIGN_1BYTES 0x00100000 Align data on a 1-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_2BYTES 0x00200000 Align data on a 2-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_4BYTES 0x00300000 Align data on a 4-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_8BYTES 0x00400000 Align data on an 8-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_16BYTES 0x00500000 Align data on a 16-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_32BYTES 0x00600000 Align data on a 32-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_64BYTES 0x00700000 Align data on a 64-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_128BYTES 0x00800000 Align data on a 128-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_256BYTES 0x00900000 Align data on a 256-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_512BYTES 0x00A00000 Align data on a 512-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 Align data on a 1024-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 Align data on a 2048-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 Align data on a 4096-byte boundary. Valid only for object files. IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 Align data on an 8192-byte boundary. Valid only for object files. IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 The section contains extended relocations. IMAGE_SCN_MEM_DISCARDABLE 0x02000000 The section can be discarded as needed. IMAGE_SCN_MEM_NOT_CACHED 0x04000000 The section cannot be cached. IMAGE_SCN_MEM_NOT_PAGED 0x08000000 The section is not pageable. IMAGE_SCN_MEM_SHARED 0x10000000 The section can be shared in memory. IMAGE_SCN_MEM_EXECUTE 0x20000000 The section can be executed as code. IMAGE_SCN_MEM_READ 0x40000000 The section can be read. IMAGE_SCN_MEM_WRITE 0x80000000 The section can be written to. Nesta parte não vou colocar o valor que deu no meu, vou apenas destacar um fato interessante que é: a seção .text possui permissão de leitura e execução (os bits 29 e 30 estão sempre setados nela), pelo menos deveriam Muito obrigado por aguentar até aqui, espero que tenha sido claro e como sempre, qualquer feedback só mandar bala. Queria também avisar que coloquei todo esse material no meu github (https://github.com/leandropf/pecoff). Sei que não é lá essas coisas, apenas um mero mortal descrevendo os campos, mas ainda sim quem sabe não ajude alguém ou no mínimo dê uma direção . Abraços e bom domingo! Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados
Arquivado
Este tópico foi arquivado e está fechado para novas respostas.