Jump to content

Fabiano Furtado

Apoiadores
  • Content Count

    29
  • Joined

  • Last visited

Everything posted by Fabiano Furtado

  1. Texto excelente! Para complementá-lo, segue um video do Ben Eater, onde ele fala sobre o trabalho de Turing e Church, e questiona se o computador de 8 bits que ele contruiu com portas lógicas simples é realmente considerado um computador completo. Bem, sugiro assistirem a esta Playlist fantástica! São mais de 40 videos. Comecei assistindo um e não consegui parar! 😆 Valeu!
  2. Segue o programa e o binário. /* * GCC 8.3.0: gcc -Wall -s -O2 helloworld.c -o helloworld */ #include<stdio.h> int main(void) { puts("Hello World!"); return 0; } helloworld
  3. Fiz o teste com o seu PEDA, copiando o peda.py para o diretório do meu peda. Não deu muito certo. O resultado foi esse: $ gdb ./helloworld GNU gdb (GDB) 8.3 Copyright (C) 2019 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ./helloworld... (No debugging symbols found in ./helloworld) gdb-peda$ start No unwaited-for children left. Display various information of current execution context Usage: context [reg,code,stack,all] [code/stack length] gdb-peda$ O que estou fazendo de errado? Valeu.
  4. Fernando... encontrei uma maneira de se fazer isso em https://reverseengineering.stackexchange.com/questions/19598/find-base-address-and-memory-size-of-program-debugged-in-gdb Combinando essa informação do Entry Point do cabeçalho e os comandos starti, info inferior e shell pmap -x <PID>, dá pra se chegar na _start ou main(). Valeu!
  5. Oi Fernando... vou testar sim, mas tem que ser amanhã. Legal essa iniciativa! Vou lhe dar um retorno em breve. Bom... testei esse comando "info files" que você mencionou no video e deu certo, mas deu errado! 😞 "Stripando" o binário com o strip, funciona, mas com o sstrip, não. O sstrip é um utilitário que vem no pacote elfkickers (http://www.muppetlabs.com/~breadbox/software/elfkickers.html). Enfim... parece que ele retira mais coisas do binário e o "info files" não consegue identificar o entry point. Usei o "readelf -a" para comparar e analisar os dois binários e não há nehhuma informação sobre os Section Headers no arquivo gerado pelo sstrip. Só para efeito comparativo, com o strip, o meu binário ficou com 6160 bytes. Com o sstrip ficou com 4144! Neste caso, há algum outro comando que possa ser usado no GDB? Valeu!
  6. Fernando, obrigado pelo video! Não conhecia essa "info files". Com certeza ajudará MUITO!! Valeu!!!
  7. Pessoal, preciso de uma ajuda com o GDB depurando arquivos binários stripped. Fiz um "Hello World!" básico em C, compilei ele com "gcc -Wall -z noseparate-code hw64.c -o hw64" e logo em seguida executei um sstrip em cima do binário. O parâmetro "-z noseparate-code" foi usado pra deixar o binário menor (leia o man deste parâmetro). Em tempo, o gcc compilou o binário com PIE habilitado, ou seja, a cada execução o SO aloca o programa em um endereço de memória diferente. Eu consegui fazer a depuração no GDB, mas precisei usar o Ghidra para descobrir os offsets do binário, uma vez que o objdump com o binário sstrip não mostra nada. Para isso, executei o GDB (estou usando a versão 8.3 com o peda 1.1): * starti --> ele executa a primeira instrução, no caso, uma instrução da lib ld-linux * info proc mappings --> para saber qual endereço de memória o programa foi alocado devido ao ASLR * breakpoint na main() --> depois de ter obtido o offset desta função com o Ghidra + informação do endereço de memória * continue --> fim da depuração Alguém conhece alguma técnica melhor que não precise do Ghidra (ou outro disassembly) para obtermos os offsets das funções? Desde já, agradeço.
  8. Tudo bem! Não precisa utilizar funções naked. Pode ser ofuscação utilizando outros métodos. Por exemplo, me lembro uma vez que você postou um artigo/comentário sobre substituição de uma insrtução call por outras equivalentes (push e jmp) para enganar o decompiler.... enfim... acho que você deve ter algum material bom sobre isso. Valeu!!!!
  9. Mais um link com dicas para deixar o seu binário menor: http://ptspts.blogspot.com/2013/12/how-to-make-smaller-c-and-c-binaries.html
  10. Segue o link do NASM: https://blog.stalkr.net/2014/10/tiny-elf-3264-with-nasm.html O programa ficou com 132 bytes com o NASM versão 2.14.02.
  11. Fernando.... blza? Vc tem mais exemplos de ofuscação? Eu achei bem interessante, apesar de ser "meio fraco". :)
  12. Pessoal... Olhem isso: https://www.cirosantilli.com/elf-hello-world/ http://timelessname.com/elfbin/ O pessoal está usando o NASM para gerar os bytes diretamente para o binário, sem usar o GCC. Bem interessante.
  13. Blza.... vou pesquisar sobre o assunto. Se sair algo, eu divulgo aqui. Obrigado!
  14. Pessoal, boa noite. Estava pensando em fazer um programa em C para inserir NOPs entre duas funções quaiquer da section .text de um binário ELF. Seria mais para fins de estudos mesmo, sem muito objetivo prático. Alguém já pesquisou sobre isso? Será que vale o esforço? Imagino que não seja algo muito fácil de se fazer, uma vez que temos várias referências de chamadas de funções dentro de um binário. Desde já, agradeço.
  15. Muito bom os artigos!!!! Realmente fica quase impossível adivinhar esses números diante de tantas possíveis combinações.
  16. Pessoal, desenvolvi recentemente 2 programas em C para gerar e filtrar números/combinações numéricas das loterias Dupla Sena e Lotofácil (eles podem ser adaptados facilmente para outros tipos de concursos, por exemplo). Gostaria de um feedback de vocês pois não sei se fiz da melhor forma possível. Achei a leitura do arquivo texto contendo as combinações um pouco lenta. Enfim... todas as críticas são bem-vindas pois tenho certeza que poderia ter feito ele de outra maneira mais otimizada. https://github.com/fabianofurtado/random-lottery-numbers Há, basicamente, duas formas de vocês o utilizarem: 1) Através de um arquivo texto contendo as combinações (pode ser gerada no random.org) 2) Através do parâmetro -n onde o sistema utilizará as funções srand() e rand() da libc. Valeu!
  17. cpuodzius, agora entendi a complexidade... vou dar uma lida no artigo indicado. Agradeço pelo retorno.
  18. Pessoal, estou estudando alguns tópicos do livro "Reversing: Secrets of Reverse Engineering" do Eldad Eilam, ano 2005, mais espeficificamente o capítulo "10- Antireversing Techniques". Neste capítulo há muito conteúdo, mas a dúvida é sobre o "Garbage Byte", técnica onde se coloca bytes em posições estratégias do binário para dificultar o disassembly, combinado com os métodos que os disassemblers utilizam para fazer o reversing de forma correta. O livro apresenta duas técnicas chamadas de Linear Sweep e Recursive Traversal. Segundo o autor, este exemplo do livro... _asm { mov eax, 2 cmp eax, 3 je Junk mov eax, After jmp eax Junk: _emit 0xf After: mov eax, [SomeVariable] push eax call AFunction } ... confunde os disassemblers, independentemente da técnica utilizada (Linear Sweep ou Recursive Traversal). "A razão pela qual esse truque funciona é bem trivial - porque o disassembler não tem idéia de que a sequencia mov eax, After, jmp eax é equivalente a jmp After...". Neste exemplo temos 2 "pegadinhas" para os disassemblers. A primeira é um jump condicional, que sempre será incondicional pois a comparação feita sempre será com constantes (2 e 3). A segunda é esse conjunto "mov eax, After, jmp eax", já citado anteriormente. Bem, implementar uma nova técnica de disassembler mais inteligente é muito complicado? Pelo menos uma técnica onde se consiga avaliar os saltos baseados em constantes, como no exemplo acima. Acredito que seja complexo pois este livro é de 2005 e até hoje os disassemblers não a implementaram. Alguém já teve alguma experiência com isso? Saberia me apontar a dificuldade em se implementar tal técnica? Em tempo, sugiro a leitura e estudo deste livro. Estou achando excelente o seu conteúdo. Desde já, agradeço.
  19. Oi Fernando... primeiramente, obrigado pelo retorno. Acho que ainda não tenho essa capacidade para fazer tal análise, ainda mais de dentro da ld-linux. 😞 Quem sabe um video sobre o assunto no seu canal do YouTube? O máximo que consegui foi tirar algumas informações do dump que foi gravado: $ coredumpctl list Hint: You are currently not seeing messages from other users and the system. Users in groups 'adm', 'systemd-journal', 'wheel' can see all messages. Pass -q to turn off this notice. TIME PID UID GID SIG COREFILE EXE Wed 2018-11-14 15:56:57 -02 17737 1000 988 11 present /usr/lib/ld-2.28.so $ coredumpctl info 17737 Hint: You are currently not seeing messages from other users and the system. Users in groups 'adm', 'systemd-journal', 'wheel' can see all messages. Pass -q to turn off this notice. PID: 17737 (ld-linux-x86-64) UID: 1000 (fabianofurtado) GID: 988 (users) Signal: 11 (SEGV) Timestamp: Wed 2018-11-14 15:56:56 -02 (5min ago) Command Line: /lib64/ld-linux-x86-64.so.2 /tmp/hw64 Executable: /usr/lib/ld-2.28.so Control Group: /user.slice/user-1000.slice/session-6.scope Unit: session-6.scope Slice: user-1000.slice Session: 6 Owner UID: 1000 (fabianofurtado) Boot ID: ***** Machine ID: ***** Hostname: PC-107204 Storage: /var/lib/systemd/coredump/core.ld-linux-x86-64.1000.******.*****.lz4 Message: Process 17737 (ld-linux-x86-64) of user 1000 dumped core. Stack trace of thread 17737: #0 0x00007f293c068bc3 _dl_relocate_object (/usr/lib/ld-2.28.so) #1 0x00007f293c061397 dl_main (/usr/lib/ld-2.28.so) #2 0x00007f293c076090 _dl_sysdep_start (/usr/lib/ld-2.28.so) #3 0x00007f293c05f088 _dl_start (/usr/lib/ld-2.28.so) #4 0x00007f293c05e008 _start (/usr/lib/ld-2.28.so) Esse programa foi um "Hello World" feito em NASM.
  20. Fernando, tudo bem? Tenho uma dúvida em relação a esse procedimento de hook relacionada a segurança. Muito básica, diga-se. Para que esse LD_PRELOAD foi implementado na GLIBC se, ao meu ver, só há desvantagens em relação a segurança? Quais os benefícios de se ter implementado isso? Achei muito interessante esse recurso, mas a segurança fica comprometida com ele ativado. Outra... usei o ldd para ver as dependências e a maioria das aplicações Linux linkadas dinamicamente utiliza a ld-linux-x86-64.so.2 para funcionar/carregar o binário ELF. Lendo mais sobre o assunto (1), e também demonstrado por você no artigo ( $ LD_PRELOAD=$PWD/hook.so ./ld-linux-x86-64.so.2 ./ola ), é possível executar um binário sem o bit de execução habilitado. Não entendi o motivo disso. Fiz um teste com o ld-linux-x86-64.so.2 em um binário sem dependências (linkado estaticamente) e, independentemente do estado do bit de execução, o binário não roda. Tenho um Segmentation Fault. Eu só queria uma opinião mesmo sobre essas implementações pois acho que a segurança fica muito comprometida desta maneira. Desde já agradeço. Referências: * (1) https://superuser.com/questions/341439/can-i-execute-a-linux-binary-without-the-execute-permission-bit-being-set
  21. Artigo EXCELENTE! Sempre aprendo algo novo por aqui! Vou postar um comentário, pois estou com algumas dúvidas. Valeu!
  22. Pessoal... eu queria poder utilizar essa técnica com o ALSR ativado. Então, continuando a pesquisa sobre o assunto, descobri que precisaria do valor do EIP para fazer o "jump" para o endereço randomizado. Lendo sobre isso em https://stackoverflow.com/questions/8333413/why-cant-you-set-the-instruction-pointer-directly, descobri que não tem como ler diretamente ou escrever para o EIP usando os opcodes normais. Somente as instruções JMP, CALL ou RET é que podem alterar o EIP. Desta forma, criei uma função get_eip() para alterar o EIP para fazer o JMP incondicional. Segue o programa em C modificado: #include <stdio.h> void get_eip(void) { return; } int main(void) { int c = 0; c++; if ( c == 1 ) { get_eip(); // faz o JMP para 'end:' (goto end;) //goto end; // Comentei pois estou forcando o jump dentro da get_eip() } do { puts("Dentro do while"); goto end; } while (1); puts("antes do Fim"); end: puts("Fim"); return 0; } Depois de compilar com "gcc -Wall -m32 -O0 salto.c -o salto" (utilizando ALSR), o programa ficou assim: 0000118d <get_eip>: 118d: 55 push ebp 118e: 89 e5 mov ebp,esp 1190: e8 6f 00 00 00 call 1204 <__x86.get_pc_thunk.ax> 1195: 05 6b 2e 00 00 add eax,0x2e6b 119a: 90 nop 119b: 5d pop ebp 119c: c3 ret 0000119d <main>: 119d: 8d 4c 24 04 lea ecx,[esp+0x4] ..... 11c9: 75 05 jne 11d0 <main+0x33> 11cb: e8 bd ff ff ff call 118d <get_eip> 11d0: 83 ec 0c sub esp,0xc 11d3: 8d 83 08 e0 ff ff lea eax,[ebx-0x1ff8] ..... Após a alteração dos opcodes, a função get_eip() ficou assim: 0000118d <get_eip>: 118d: 58 pop eax ; Retira o endereco do IP da pilha e o copia em EAX 118e: 05 13 00 00 00 add eax,0x13 ; Soma o IP com 0x13 para fazer o salto de 19 instruções 1193: 50 push eax ; Joga o novo endereço do IP na pilha 1194: c3 ret ; Altera o EIP e altera o fluxo para a label "end" do programa em C Bom, resumindo, a bagaça funcionou. Entretanto, gostaria de saber se há alguma forma mais simples de se manipular o EIP e fazer essa operação sem o uso de call. Alguém mais experiente poderia ajudar nisso? Obrigado desde já.
  23. Rafael, descobri o que estava fazendo de errado, graças aos seus binários!!! Estava compilando com o PIE ativado! E como o PIE é para suportar randomização de espaço de endereço (ASLR) em arquivos executáveis, coloquei um "-no-pie" na linha de compilação do gcc (gcc -Wall -no-pie -m32 -O0 salto.c -o salto) e deu certo! Como o endereçamento é dinâmico, a probabilidade de dar um Segmentation Fault é altíssima! Desabilitando isso, resolve. Obrigado!
  24. Oi Rafael, primeiramente, obrigado pelo retorno. Você pode colocar os opcodes que você usou para as novas intruções? Repeti o processo e ainda estou com o "Segmentation Fault". Desde já, agradeço.
  25. Pessoal, bom dia. Estou estudando algumas técnicas de proteção de binários, me baseando no video do Fernando Mercês do Roadsec 2017 https://www.youtube.com/watch?v=cpU9U0sqzh4 Mais especificamente, em 27'29", o Fernando mostra como substituir algumas instruções por outras equivalentes, para dificultar a análise do binário. Fiz exatamente isso, mas o programa da um Segmentation Fault após a alteração, e eu não tenho idéia do que pode ser. Alguma ajuda? Segue o programa exemplo em C que fiz para alterar o JMP: #include <stdio.h> int main(void) { int c = 0; c++; if ( c == 1 ) { __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); goto end; } do { puts("Dentro do while"); goto end; } while (1); puts("antes do Fim"); end: puts("Fim"); return 0; } Compilei ele com: gcc -Wall -m32 -O0 salto.c -o salto Seguem as linhas originais: 11b5: 83 7d f4 01 cmp DWORD PTR [ebp-0xc],0x1 11b9: 75 06 jne 11c1 <main+0x34> 11bb: 90 nop 11bc: 90 nop 11bd: 90 nop 11be: 90 nop 11bf: eb 13 jmp 11d4 <main+0x47> 11c1: 83 ec 0c sub esp,0xc 11c4: 8d 83 08 e0 ff ff lea eax,[ebx-0x1ff8] 11ca: 50 push eax 11cb: e8 60 fe ff ff call 1030 <puts@plt> 11d0: 83 c4 10 add esp,0x10 11d3: 90 nop 11d4: 83 ec 0c sub esp,0xc 11d7: 8d 83 18 e0 ff ff lea eax,[ebx-0x1fe8] Seguem as linhas alteradas: 11b9: 75 06 jne 11c1 <main+0x34> 11bb: 68 d4 11 00 00 push 0x11d4 11c0: c3 ret 11c1: 83 ec 0c sub esp,0xc 11c4: 8d 83 08 e0 ff ff lea eax,[ebx-0x1ff8] 11ca: 50 push eax 11cb: e8 60 fe ff ff call 1030 <puts@plt> 11d0: 83 c4 10 add esp,0x10 11d3: 90 nop 11d4: 83 ec 0c sub esp,0xc 11d7: 8d 83 18 e0 ff ff lea eax,[ebx-0x1fe8] Alguma ajuda? Desde já, agradeço.
×
×
  • Create New...