Moderadores Leandro Fróes Postado Agosto 30, 2017 em 01:58 Moderadores Compartilhar Postado Agosto 30, 2017 em 01:58 E aqui estamos para mais um trecho do que venho estudando sobre o formato PE!! Esses dias estava pensando: o editor hexa me mostra tanto os bytes quanto suas representações em ASCII (caso haja), mas e se eu mesmo visse? Ai lembrei da função fseek e fread. A primeira, tratando-se de um binário, pula para o offset em específico e a outro lê os bytes. Dei uma leve lida sobre e fiz esse programinha só pra fazer um “PoC” do que estamos vendo: #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]){ FILE *f; //ponteiro para um arquivo unsigned char buffer[4]; // espaço em memória que iremos colocar os bytes lidos f = fopen(argv[1], "rb"); // abrindo o arquivo binário que recebemos como primeiro parâmetro do nosso programa com permissão de leitura (rb); if(fopen == NULL){ // simples teste para ver se conseguimos abrir o arquivo printf("Erro\n"); exit(1); } fseek(f, 0x80, SEEK_SET); // pulamos para o offset da assinatura PE. O parâmetro SEEK_SET indica que estamos pulando a partir do começo do arquivo fread(buffer, 4, 1, f); // estamos colocando 1 elemento em buffer para leitura e este elemento possui 4 bytes do arquivo (f) puts(buffer); // imprimindo a string dentro de buffer fclose(f); // fechando o arquivo return 0; } Este tipo de teste (leitura de bytes) pode ser feito em qualquer lugar do arquivo, poderíamos ter imprimido os próprios bytes também, por que não tentar? . Caso queira saber um pouco mais [1]. Dando sequência aos nossos estudos temos a struct IMAGE_NT_HEADERS que segue o seguinte escopo segundo a documentação da Microsoft: typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER OptionalHeader; } IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; Vimos no post anterior a existência da assinatura PE e comprovamos vendo a própria assinatura com o programinha em C ali em cima. Podemos observar que o segundo campo tem nome de FileHeader e é do tipo IMAGE_FILE_HEADER, ou seja, uma struct. Ela que iremos analisar typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; IMAGE_MACHINE Logo após a assinatura do PE temos a especificação de que tipo de máquina o executável está previsto para rodar, este campo é uma WORD(16 bits) e aqui está a especificação exata[2]: IMAGE_FILE_MACHINE_UNKNOWN 0x0 The contents of this field are assumed to be applicable to any machine type IMAGE_FILE_MACHINE_AM33 0x1d3 Matsushita AM33 IMAGE_FILE_MACHINE_AMD64 0x8664 x64 IMAGE_FILE_MACHINE_ARM 0x1c0 ARM little endian IMAGE_FILE_MACHINE_ARM64 0xaa64 ARM64 little endian IMAGE_FILE_MACHINE_ARMNT 0x1c4 ARM Thumb-2 little endian IMAGE_FILE_MACHINE_EBC 0xebc EFI byte code IMAGE_FILE_MACHINE_I386 0x14c Intel 386 or later processors and compatible processors IMAGE_FILE_MACHINE_IA64 0x200 Intel Itanium processor family IMAGE_FILE_MACHINE_M32R 0x9041 Mitsubishi M32R little endian IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16 IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS with FPU IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 with FPU IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC little endian IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 Power PC with floating point support IMAGE_FILE_MACHINE_R4000 0x166 MIPS little endian IMAGE_FILE_MACHINE_RISCV32 0x5032 RISC-V 32-bit address space IMAGE_FILE_MACHINE_RISCV64 0x5064 RISC-V 64-bit address space IMAGE_FILE_MACHINE_RISCV128 0x5128 RISC-V 128-bit address space IMAGE_FILE_MACHINE_SH3 0x1a2 Hitachi SH3 IMAGE_FILE_MACHINE_SH3DSP 0x1a3 Hitachi SH3 DSP IMAGE_FILE_MACHINE_SH4 0x1a6 Hitachi SH4 IMAGE_FILE_MACHINE_SH5 0x1a8 Hitachi SH5 IMAGE_FILE_MACHINE_THUMB 0x1c2 Thumb IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS little-endian WCE v2 Já inverteram os bytes e descobriram a nossa? Isso mesmo, 0x014c com o nome IMAGE_FILE_MACHINE_I386 NumberOfSections Nossa próxima WORD define o número de seções que nosso binário possui (e o tamanho da section table). Se você não faz ideia do que seja uma seção fique tranquilo que vamos ver tudo isso com o tempo. Lembrando que estamos lidando com base 16 (hexadecimal). Uma simples conversão para a base 10 nos diz que temos 15 sections. 000Fh = 15. TimeDataStamp No campo seguinte temos a DWORD de nome TimeDataStamp(carimbo de data e hora). Praticamente corresponde ao número de segundos decorridos a partir de 1 de Janeiro de 1970 00:00:00, em UTC - o formato utilizado pela maioria dos compiladores C para time_t. Invertendo nossos bytes temos 5997 35E9, isto em decimal fica 1.503.081.961 segundos (credo). Sabemos que um dia tem 24h, que cada hora tem 60 min, e que cada min tem 60 segundos, resumindo 24*60*60 = 86.400 segundos por dia. Fazendo 1.503.081.961/ 86.400 temos 17.396 DIAS desde 01/01/1970 e isso corresponde a mais ou menos 47 ANOS (credo 2 ) e realmente, se somarmos todos esses dias com a data de 01/01/1970… Criei esse executável na data informada No caso eram 18:45, o sistema não está com o horário de Brasília, mas você pegou a ideia! PointerToSymbolTable e NumberOfSymbols Estas duas DWORDS são, respectivamente, ponteiro para a tabela de símbolos e número de símbolos. O primeiro campo é o offset para a tabela de símbolos(em bytes) e o segundo é o número de entradas na tabela de símbolos. SizeOfOptionalHeader Esta WORD é o tamanho do cabeçalho opcional. Caso estejamos tratando de um arquivo objeto este campo estará zerado. Para nós agora ele é simplesmente o tamanho do IMAGE_OPTIONAL_HEADER. Temos 00E0, ou seja, 224 em decimal, 224 bytes. Nao acredita? #include <stdio.h> #include <windows.h> int main(){ printf("O tamanho do header eh de: %d bytes\n", sizeof(IMAGE_OPTIONAL_HEADER)); } Characteristics Aqui temos uma máscara de bits (16 no caso), sabe o registrador EFLAGS[3]? É por ai a ideia. Como a documentação da Microsoft é bem enxuta quanto a isso vou simplesmente dar Ctrl+C Ctrl+V na tabela Flag Value Description IMAGE_FILE_RELOCS_STRIPPED 0x0001 Image only, Windows CE, and Microsoft Windows NT® and later. This indicates that the file does not contain base relocations and must therefore be loaded at its preferred base address. If the base address is not available, the loader reports an error. The default behavior of the linker is to strip base relocations from executable (EXE) files. IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 Image only. This indicates that the image file is valid and can be run. If this flag is not set, it indicates a linker error. IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 COFF line numbers have been removed. This flag is deprecated and should be zero. IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 COFF symbol table entries for local symbols have been removed. This flag is deprecated and should be zero. IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 Obsolete. Aggressively trim working set. This flag is deprecated for Windows 2000 and later and must be zero. IMAGE_FILE_LARGE_ADDRESS_ AWARE 0x0020 Application can handle > 2‑GB addresses. 0x0040 This flag is reserved for future use. IMAGE_FILE_BYTES_REVERSED_LO 0x0080 Little endian: the least significant bit (LSB) precedes the most significant bit (MSB) in memory. This flag is deprecated and should be zero. IMAGE_FILE_32BIT_MACHINE 0x0100 Machine is based on a 32-bit-word architecture. IMAGE_FILE_DEBUG_STRIPPED 0x0200 Debugging information is removed from the image file. IMAGE_FILE_REMOVABLE_RUN_ FROM_SWAP 0x0400 If the image is on removable media, fully load it and copy it to the swap file. IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 If the image is on network media, fully load it and copy it to the swap file. IMAGE_FILE_SYSTEM 0x1000 The image file is a system file, not a user program. IMAGE_FILE_DLL 0x2000 The image file is a dynamic-link library (DLL). Such files are considered executable files for almost all purposes, although they cannot be directly run. IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 The file should be run only on a uniprocessor machine. IMAGE_FILE_BYTES_REVERSED_HI 0x8000 Big endian: the MSB precedes the LSB in memory. This flag is deprecated and should be zero. No nosso caso: Nossos bytes invertidos ficam 01 07 e isso em binário fica 0000 0001 0000 0111 Hexa 01 07 Binário 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 Bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Agora basta ver com o que o nosso binário bate: IMAGE_FILE_RELOCS_STRIPPED – Há informacoes de remanejamento IMAGE_FILE_EXECUTABLE_IMAGE – É um executável IMAGE_FILE_LINE_NUMS_STRIPPED – A numeracao de linhas foi eliminada IMAGE_FILE_32BIT_MACHINE – A máquina é baseada em uma arquitetura de 32 bits Fico por aqui e queria só falar duas coisas: 1 - Para quem curte estudar pelo blog numaboa[4] aconselho baixar os PDFs pois esses dias aparentemente estava fora do ar e não é a primeira vez que vejo isso acontecer. O material vale muito a pena ser guardado. 2 - A outra é que pretendo colocar isso tudo no meu github essa semana, para quem quiser baixar etc. Como sempre, correções, dicas e opiniões são sempre bem-vindas. Obrigado e boa noite [1] https://www.youtube.com/watch?v=oZeezrNHxVo&list=PLIfZMtpPYFP5qaS2RFQxcNVkmJLGQwyKE [2] https://www.microsoft.com/en-us/download/details.aspx?id=19509 [*] https://msdn.microsoft.com/en-us/library/windows/desktop/ms680198(v=vs.85).aspx [3] https://en.wikipedia.org/wiki/FLAGS_register [4] http://numaboa.com.br/ Link para o comentário Compartilhar em outros sites More sharing options...
Moderadores Leandro Fróes Postado Agosto 30, 2017 em 03:46 Autor Moderadores Compartilhar Postado Agosto 30, 2017 em 03:46 Estava faltando uns trechos pq meu editor estava bugado, mas já está certinho Link para o comentário Compartilhar em outros sites More sharing options...
Eduardo Bittencourt Postado Agosto 30, 2017 em 18:28 Compartilhar Postado Agosto 30, 2017 em 18:28 Da hora mano, você estuda também binários ELF? Link para o comentário Compartilhar em outros sites More sharing options...
Moderadores Leandro Fróes Postado Agosto 30, 2017 em 19:52 Autor Moderadores Compartilhar Postado Agosto 30, 2017 em 19:52 Não manin, mas pretendo Link para o comentário Compartilhar em outros sites More sharing options...
Marciano Calvi Ferri Postado Fevereiro 12, 2018 em 14:04 Compartilhar Postado Fevereiro 12, 2018 em 14:04 Fala Leandro, Por acaso vc fez uma cópia do site numaboa.com.br? Lá no discord, se eu não entendi errado, alguém tinha copiado, mas não sei quem foi. Abraço, T+. Link para o comentário Compartilhar em outros sites More sharing options...
Moderadores Leandro Fróes Postado Fevereiro 12, 2018 em 15:09 Autor Moderadores Compartilhar Postado Fevereiro 12, 2018 em 15:09 1 hora atrás, Marciano Calvi Ferri disse: Fala Leandro, Por acaso vc fez uma cópia do site numaboa.com.br? Lá no discord, se eu não entendi errado, alguém tinha copiado, mas não sei quem foi. Abraço, T+. Fala mano, então, não fiz não (na real eu imprimi alguns artigos dela na época que estava lendo). Quem fez foi o @Gribel Abraço! Link para o comentário Compartilhar em outros sites More sharing options...
sayseven Postado Maio 11, 2019 em 20:29 Compartilhar Postado Maio 11, 2019 em 20:29 Mano vc poderia mandar a copia do numaboa.com.br ? Link para o comentário Compartilhar em outros sites More sharing options...
Moderadores Leandro Fróes Postado Maio 13, 2019 em 01:20 Autor Moderadores Compartilhar Postado Maio 13, 2019 em 01:20 Fala @sayseven blz? Cara, eu não tenho uma cópia do site não, mas se eu não me engano alguém por aqui tem, já tentou perguntar no nosso canal do discord? Eu lembro que o máximo que eu fiz foi imprimir alguns artigos da vovó Vicki ? Link para o comentário Compartilhar em outros sites More sharing options...
Administradores Fernando Mercês Postado Maio 13, 2019 em 14:55 Administradores Compartilhar Postado Maio 13, 2019 em 14:55 Eu acho que tenho. Vou procurar. Esse merece ficar online sempre! Link para o comentário Compartilhar em outros sites More sharing options...
fredericopissarra Postado Maio 13, 2019 em 19:46 Compartilhar Postado Maio 13, 2019 em 19:46 Apenas um detalhe... O header PE não começa, necessariamente, no offset 0x80. Isso depende do tamanho do DOS Stub. A especificação do PE diz, claramente, que é necessário ler o offset do header PE no offset 0x3C do arquivo. Além disso, enquanto uma demonstração simples possa usar, sem problemas, streaming. Como a manipulação é binária, seria interessante evitar buffering e usar file descriptors ao invés do tipo FILE. Eis um exemplo do código inicial modificado (que checa qualquer possibilidade de erros, no caso de tentar usá-lo com um arquivo que não tem formato PE): // test.c // Compila apenas no Visual Studio ou GCC para Windows (MinGW, CygWin). #if defined(_MSC_VER) || defined(__WINNT__) # include <io.h> /* Windows não tem basename()! */ # define basename(...) (__VA_ARGS__) #else # ifdef __GNUC__ /* Esse bloco é para outro systema que não seja Windows ou MinGW */ # define _GNU_SOURCE # include <unistd.h> # include <string.h> # else # error Need MSVC, MinGW, Cygwin or GCC to compile! # endif #endif #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <fcntl.h> #include <ctype.h> static void show_buffer ( void *, size_t ); int main ( int argc, char **argv ) { int fd; uint32_t pe_pos; char buffer[4]; if ( argc != 2 ) { fprintf ( stderr, "Uso: %s <exefile>\n", basename ( *argv ) ); return EXIT_FAILURE; } // abrindo o arquivo binário que recebemos como primeiro parâmetro // do nosso programa com permissão de leitura. if ( ( fd = open ( *++argv, O_RDONLY ) ) < 0 ) { perror ( "open" ); return EXIT_FAILURE; } // pulamos para o offset 0x3C para descobrir o offset do header PE. if ( lseek ( fd, 0x3c, SEEK_SET ) == -1 ) { perror ( "lseek 0x3c" ); close ( fd ); return EXIT_FAILURE; } // O offset tem 32 bits de tamanho! if ( read ( fd, &pe_pos, sizeof ( uint32_t ) ) <= 0 ) { close ( fd ); fputs ( "ERRO lendo do offset do header PE.\n", stderr ); return EXIT_FAILURE; } // Pula para o offset do header PE. if ( lseek ( fd, pe_pos, SEEK_SET ) == -1 ) { perror ( "lseek pe_hdr" ); close ( fd ); return EXIT_FAILURE; } // Le a assinatura PE (4 bytes)... if ( read ( fd, buffer, sizeof buffer ) <= 0 ) { close ( fd ); fputs ( "ERRO lendo do offset do PE header.\n", stderr ); return EXIT_FAILURE; } close ( fd ); // Mudei isso apenas para mostrar os 4 bytes lidos! show_buffer ( buffer, sizeof buffer ); return EXIT_SUCCESS; } // Mostra o conteúdo apontado por p (size bytes) // no formato de uma string em C. static void show_buffer ( void *p, size_t size ) { char *q; q = p; while ( size-- ) { if ( isprint ( *q ) ) putchar ( *q ); else printf ( "\\x%02hhx", *q ); q++; } putchar ( '\n' ); } Link para o comentário Compartilhar em outros sites More sharing options...
sayseven Postado Maio 25, 2019 em 14:19 Compartilhar Postado Maio 25, 2019 em 14:19 @Leandro Fróes blz, tudo bem mano, obg assim msm ^^ Link para o comentário Compartilhar em outros sites More sharing options...
LCavalini Postado Dezembro 4, 2019 em 00:08 Compartilhar Postado Dezembro 4, 2019 em 00:08 Em 13/05/2019 em 11:55, Fernando Mercês disse: Eu acho que tenho. Vou procurar. Esse merece ficar online sempre! Fernando Mercês, você encontrou o material da Vovó Vicky? Seria muito legal ter esse conteúdo disponível novamente. 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.