Jump to content

Marioh

Apoiador Byte
  • Content Count

    21
  • Joined

  • Last visited

  • Country

    Brazil

Everything posted by Marioh

  1. Bom, não vou dizer que manjo de redes mas uma ferramenta otima para olhar esse tráfego é o tcpdump, com ele é possivel capturar esse tráfego de rede, podendo ver tudo que ta "passando" pela rede. O eriberto mota tem um site com umas dicas, e um livro relativamente curto e muito bacana no assunto.
  2. Assim, acho que a dúvida é mais na lógica que na linguagem em si. Posso estar errado, mas o pessoal tende a achar deselegante pedir correção de trabalho escolar. Tendo dito isso, consumo anual é 12 x consumo mensal, não ?
  3. Na verdade eu tentei fazer tudo pela stack mesmo, e até onde eu sei não se empilha byte por causa do alinhamento (até onde eu sei...), então eu ia fazer com DWORD e depois só multiplicar por 4, mas deixei QWORD mesmo já que é uma "gambiarra" anyway. Muito f**a seu artigo, precisei ler com mais calma da segunda vez! Suspeitamente parecido com LaTex... (segundo paragrafo, acho que tem um erro ortográfico) Valeu mesmo @fredericopissarra !
  4. Valeu felipe, nem fazia ideia dessa CQO.
  5. Se eu nao me engano no README-hacking explica.
  6. Tava mexendo no nasm fazendo umas funções e resolvi fazer uma função que imprime numeros em decimal. Até onde eu sei a instrução div divide o rax pelo valor em outro registrador, colocando o resultado da divisão no rax e o resto no rdx, porém se na hora da divisão o rdx não estiver zerado alguma coisa maluca acontece e é essa minha duvida. Oque que rola se o rdx não estiver zerado e fizermos uma div ? Aqui o código da função: _printnum: push rbp mov rbp, rsp sub rsp, 8 mov r10, 10 push r10 ; quebra de linha mov qword [rbp - 8], 1 ; length _prntn_lp_bgn: mov rdx, 0 idiv r10 add rdx, 0x30 push rdx inc qword[rbp - 8] cmp rax, 0 jne _prntn_lp_bgn mov rax, qword[rbp - 8] mov r10, 8 mul r10 mov rdx, rax ;gambiarra da stack mov rax, 1 mov rdi, 1 mov rsi, rsp syscall mov rax, qword [rbp - 8] ; length mov rsp, rbp pop rbp ret Sem a linha mov rdx, 0 logo depois do loop o bagulho buga todo. (Nem reparem na gambiarra que eu fiz na stack, dicas são muito bem vindas)
  7. Marioh

    Link de acesso

    Estou vendo pelo youtube: MBConf
  8. Cá estava eu programando com o nasm, tentando (apenas tentando mesmo) reproduzir os wrappers de systemcall que existem na glibc, quando me deparei com o tamanho de um bináriozinho em assembly que só retorna um valor, um "hello world" no nasm, ali no canto do diretório. O binário tinha 4.2K, nada realmente muito pesado, mas para um programa que não utiliza nenhuma biblioteca e só retorna um valor me pareceu muito estranho. Código do programa: BITS 32 global _start _start: mov eax, 1 mov ebx, 10 int 0x80 Para compilar e testar: [mario@zrmt rivendell]$ nasm -f elf32 elrond.asm [mario@zrmt rivendell]$ ld -m elf_i386 -s elrond.o -o elrond [mario@zrmt rivendell]$ ./elrond [mario@zrmt rivendell]$ echo $? 10 Aqui vai o hexdump do binário: [mario@zrmt rivendell]$ hexdump -C elrond 00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 02 00 03 00 01 00 00 00 00 90 04 08 34 00 00 00 |............4...| 00000020 20 10 00 00 00 00 00 00 34 00 20 00 02 00 28 00 | .......4. ...(.| 00000030 03 00 02 00 01 00 00 00 00 00 00 00 00 80 04 08 |................| 00000040 00 80 04 08 74 00 00 00 74 00 00 00 04 00 00 00 |....t...t.......| 00000050 00 10 00 00 01 00 00 00 00 10 00 00 00 90 04 08 |................| 00000060 00 90 04 08 0c 00 00 00 0c 00 00 00 05 00 00 00 |................| 00000070 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00001000 b8 01 00 00 00 bb 2a 00 00 00 cd 80 00 2e 73 68 |......*.......sh| 00001010 73 74 72 74 61 62 00 2e 74 65 78 74 00 00 00 00 |strtab..text....| 00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00001040 00 00 00 00 00 00 00 00 0b 00 00 00 01 00 00 00 |................| 00001050 06 00 00 00 00 90 04 08 00 10 00 00 0c 00 00 00 |................| 00001060 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 |................| 00001070 01 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| 00001080 0c 10 00 00 11 00 00 00 00 00 00 00 00 00 00 00 |................| 00001090 01 00 00 00 00 00 00 00 |........| 00001098 Da pra perceber que de 0x72 à 0xfff todos os bytes são 0. Humm... suspeito. Não sou especialista e posso estar terrívelmente errado, mas não lembro dessa quantidade de zeros no manual do formato ELF. Se abrirmos o binário com o readelf veremos o seguinte: [mario@zrmt rivendell]$ readelf elrond -h ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x8049000 Start of program headers: 52 (bytes into file) Start of section headers: 4128 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 2 Size of section headers: 40 (bytes) Number of section headers: 3 Section header string table index: 2 Três Section Headers, dois Program Headers e mais um bando de coisa. Como não precisamos das seções para executar o programa irei ignorá-las por agora. Não precisamos das seções para executar o programa devido ao fato de que elas são feitas para auxiliar o linker no momento de construção do binário. Como o binário já está construído e nenhuma das seções representa objetos dinâmicos, elas podem ser ignoradas. Então vamos diminuir esse programa aí. Primeiramente, devemos descobrir o endereço base do programa, para isto, basta pegar o entrypoint (0x8049000) e diminuir o offset do Program Header que tem a flag de executável (que vai conter o devido código do programa). Lembrando que o entrypoint é composto pelo endereço base do programa (para ser mapeado em memória) + “endereço” (no arquivo) do primeiro byte que corresponde ao código executável. O que vamos fazer aqui é achar esse primeiro byte, que pode ser encontrado no Program Header, onde se tem a flag de executável que recebe o nome de p_offset. Vejamos o readelf -l: [mario@zrmt rivendell]$ readelf -l elrond Elf file type is EXEC (Executable file) Entry point 0x8049000 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x08048000 0x08048000 0x00074 0x00074 R 0x1000 LOAD 0x001000 0x08049000 0x08049000 0x0000c 0x0000c R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text Para ajudar: de acordo com o manual o campo p_offset é “O offset do início do arquivo onde o primeiro byte do segmento se encontra”. Como estamos lidando com um segmento executável esse primeiro byte vai ser o início do nosso código. Então dá para ver que o segundo Program Header (que possui a flag de executável) tem offset 0x001000! Então o endereço base é 0x08048000 (0x08049000 - 0x00001000) ! Já que temos o endereço base podemos excluir os zeros (caso contrário o programa ficaria quebrado e não iríamos conseguir analisá-lo com o readelf), alto lá! Apenas os inúteis! Mas quais são os inúteis ? Todos os que os Program Headers apontam, pois esses serão os bytes do programa mapeados em memória, então vamos deixar eles lá. Vou usar o hyx como editor hexa, mas o hte também funciona. Após excluirmos todos os zeros entre 0x74 e 0x1000: [mario@zrmt rivendell]$ hyx elrond 0000> 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 0010: 02 00 03 00 01 00 00 00 00 90 04 08 34 00 00 00 |............4...| 0020: 20 10 00 00 00 00 00 00 34 00 20 00 02 00 28 00 | .......4. ...(.| 0030: 03 00 02 00 01 00 00 00 00 00 00 00 00 80 04 08 |................| 0040: 00 80 04 08 74 00 00 00 74 00 00 00 04 00 00 00 |....t...t.......| 0050: 00 10 00 00 01 00 00 00 00 10 00 00 00 90 04 08 |................| 0060: 00 90 04 08 0c 00 00 00 0c 00 00 00 05 00 00 00 |................| 0070: 00 10 00 00 00 b8 01 00 00 00 bb 2a 00 00 00 cd |...........*....| 0080: 80 00 2e 73 68 73 74 72 74 61 62 00 2e 74 65 78 |...shstrtab..tex| 0090: 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |t...............| 00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 00 00 |................| 00c0: 00 01 00 00 00 06 00 00 00 00 90 04 08 00 10 00 |................| 00d0: 00 0c 00 00 00 00 00 00 00 00 00 00 00 10 00 00 |................| 00e0: 00 00 00 00 00 01 00 00 00 03 00 00 00 00 00 00 |................| 00f0: 00 00 00 00 00 0c 10 00 00 11 00 00 00 00 00 00 |................| 0100: 00 00 00 00 00 01 00 00 00 00 00 00 00 |.............| Ahh muito mais enxuto! Porém o bicho tá todo quebrado. Se executarmos: [mario@zrmt rivendell]$ ./elrond Bus error (core dumped) Um “Bus error” não é nada mais que uma tentativa de read ou write em um espaço de memória desalinhado. Como citado no manual os mapeamentos tem que ser alinhados com as páginas de memória, ou seja, 4KB. Vamos consertá-lo! Vamos ter que consertar: o entrypoint e o mapeamento do segundo Program Header, ou seja, seu endereço virtual, físico e seu offset. Como estamos alterando as posições dos segmentos (isto é, o nome oficial para o que um Program Header mapeia) teremos que alterar seu mapeamento no arquivo junto com o entrypoint (que aponta para o primeiro byte de um segmento executável). Na verdade, o endereço físico pode ser ignorado, o manual cita que os “System V” ignoram endereços físicos de aplicações, mas iremos adicioná-los em prol da completude. Revisando... o entrypoint vai ser o endereço base mais o offset do segundo Program Header, e esse offset vai ser 0x75 (lembre-se que era 0x1000, mas com a retirada dos zeros entre 0x74 e 0x1000 efetivamente reduzimos o entrypoint em 0xFFF - 0x74 = 0xF8B, logo, o entrypoint vai ser 0x1000 - 0xF8B = 0x75) então nosso entrypoint vai ser 0x08048075. Esse também vai ser o endereço virtual e o endereço físico do header. Então troquemos: O entrypoint no Header ELF por 0x08048075 O offset do section header por 0x00000075 Os endereços virtuais e físicos do segundo Program Header por 0x08048075 Agora mais do que nunca teremos que ter atenção. Saque seu editor de hexa preferido e lembre-se que estamos lidando com little endian. Vou usar o hyx, que é um editor hexa um pouco parecido com o vi: No terminal de cima temos o arquivo original sem os zeros, já no de baixo temos o arquivo já alterado. Para ajudar: Vermelho: Entrypoint Amarelo: Offset do Header Verde: Endereço Virtual do Header Azul: Endereço Físico do Header Agora se executarmos: [mario@zrmt rivendell]$ ./elrond [mario@zrmt rivendell]$ echo $? 10 Como disse lá em cima, não alterei as seções e nesse caso (binário já linkado e sem bibliotecas dinâmicas) elas não são importantes. Tente ler elas pra ver o que acontece. No fim passamos de 4.2k para ... [mario@zrmt rivendell]$ ls -lh elrond -rwxr-xr-x 1 mario mario 269 --- -- --:-- elrond 269! Achei que a galera poderia gostar dessa pequena aventura, acho bem interessante principalmente para aprender bem sobre o formato. Se gostarem tenho planos pra parte dois!
  9. @fredericopissarra Uma duvida, a arquitetura de harvard seria assim?
  10. Bom, o jeito que eu entendo os casts é simplesmente um modo de interpretar os bytes dentro daquele endereço. No código la o cara usa um char justamente pra poder acessar byte por byte, lembrando que na aritimética de ponteiro quando uma soma é feita, na verdade estamos somando n+(sizeof(elemento)). Acho que o @fredericopissarra deve saber explicar melhor. Fiz um programinha aqui: #include<stdio.h> #include<stdlib.h> int main(void){ FILE *fd = fopen("number","r"); unsigned long int li; fread(&li, sizeof(li), 1, fd); // os tamanhos so pra ajudar //printf("char: %zu\n", sizeof(char)); //printf("short: %zu\n", sizeof(short)); //printf("int: %zu\n", sizeof(int)); //printf("%zu\n", sizeof(long int)); // aqui vem os casts printf("%hhu\n",(unsigned char) li ); printf("%hu\n",(unsigned short) li ); printf("%u\n",(unsigned int) li ); printf("long value: %ld\n",li ); return 0; } number: [mario@zrmt forum]$ hd number 00000000 01 01 00 01 00 00 00 01 |........| 00000008 quando executado: [mario@zrmt forum]$ ./cast 1 257 16777473 72057594054705409 O char vai interpretar o primeiro byte, o short os dois primeiros, o int os quatro e o long todos os oito. Mas tambem posso estar terrivelmente errado.
  11. Man eu acho que é exatamente assim, até mesmo se tu olhar o codigo de "crc32.c"... u_int32_t chksum_crc32 (unsigned char *block, unsigned int length){ register unsigned long crc; unsigned long i; crc = 0xFFFFFFFF; for (i = 0; i < length; i++) { // incremento // vvvvvv crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF]; } return (crc ^ 0xFFFFFFFF); } u_int32_t crc32(unsigned char *block, unsigned int length){ if(!initialized){ chksum_crc32gentab(); initialized = 1; } return chksum_crc32(block, length); } Já da pra perceber que o nome da variavel na "crc32" é "length"(suspeito...), além disso o "for" na "chksum_crc32" realmente "passa" length vezes, incrementando "block"(o address da funcao) cada vez que "passa". Mas assim, não sou especialista.
  12. Marioh

    Cursos

    Bom se tu sabe um pouco de C, o Frederico Pissarra tem três livros bem legais, e apesar de dizer que não quer ensinar, os livros são otimos para isso. Também tem o RE4B , que eu não sei se é bom, e o livro do Mercês.
  13. @Fernando Mercês Parece que o fflush pode funcionar dessa maneira só não é garantido, li em algum lugar que os kernels atuais suportam, mas não sei ao certo tô com o 5.5.13 e comigo não funciona. Já o __fpurge da stdio_ext.h funciona examento como esperado. Li também em algum lugar (acho que foi no reddit) que realmente nao faz sentido dar um "flush" no stdin, afinal pra onde ele vai ser flushado ? Lá na manpage do fflush ele fala que se a stream for de output ele força um write nos dados em buffer que ultimamente tem um destino.
  14. Aí @Fernando Mercês, posso tá errado mas fflush não tem comportamento definido quando usado no stdin, tem ?
  15. Se eu nao me engano tu tem que esvaziar os stdin. tenta: char clear; while((clear = getchar()) != '\n' && clear != EOF); depois do seu primeiro scan. espero que ajude.
  16. Marioh

    Dúvida em C

    Pois e percebi isso assim que postei #include <stdio.h> #include <stdlib.h> typedef struct { long int numero; char nome[100]; }addr; void main(){ addr teste = {0, "default"}; FILE *p; p = fopen("teste", "rb"); if(p == NULL){ printf("ERROO"); exit(1); } int i = fread( &teste, sizeof(addr), 1, p); printf("read: %lu\n", teste.numero); puts(teste.nome); printf("%zu\n", sizeof(long int) ); fclose(p); } espero que ajude.
  17. Marioh

    Dúvida em C

    Entao dei um "echo "70707070testando > teste" e o codigo fica assim: #include <stdio.h> #include <stdlib.h> typedef struct { int numero; char nome[100]; }addr; // coloquei um valorzinho default pra debugar addr teste = {0, " "}; int main(void){ FILE *p; p = fopen("teste", "r"); if(p == NULL){ printf("ERROO"); exit(1); } // parenteses opcionais fscanf(p,"%d%s" , &(teste.numero), &teste.nome); printf("%u\n", teste.numero); puts(teste.nome); fclose(p); return 0; } Espero que ajude
  18. Marioh

    Dúvida em C

    Tu pode tentar com o fscanf.
  19. creio que a logica do teu primeiro for esteja errada tbm pq ele nunca vai ser executado com valores menores que 11. Talvez o teu x deva ser 0 ? Alem disso tu esta lendo mais do que teu vetor e assim tu vai pegar lixo na memoria.
  20. No printf falta os colchetes no 'a' como a[ i ]
×
×
  • Create New...