Jump to content

Felipe.Silva

Membros
  • Content Count

    68
  • Joined

  • Last visited

Everything posted by Felipe.Silva

  1. A heap é uma estrutura especial de memória usada pelo processo. O que tem de especial nela é o fato de seu tamanho ser variável, já que sua memória pode ser alocada ou desalocada dinamicamente pelo processo. Isso pode ser feito usando syscalls do sistema operacional e o mesmo é responsável por alocar mais páginas de memória para a seção caso seja necessário. No Linux o segmento de dados pode ser aumentado ou diminuído usando a syscall brk, e é esse espaço de memória que os programas normalmente usam para a heap. Em C nós normalmente não usamos a heap diretamente e, ao invés disso, usamos
  2. O próprio Wine tem um debugger (winedbg) que você pode utilizar para depurar um .exe, dá para usar ele como gdb's server com a opção --gdb, caso você saiba usar o gdb... Porém o que o edb (e outros debuggers) faz é depurar processos e não arquivos executáveis. Se você pode iniciar um processo para o .exe então você pode depurá-lo. O passo-a-passo fica: Execute o .exe com o Wine. Abra o edb com privilégios root, menu "File" clique em "Attach". Procure pelo processo, dá para pesquisar pelo nome ou pelo PID. É necessário executar o edb como root porque é necessário privilégio
  3. Na programação orientada a objetos existe o conceito de encapsulamento, que resumidamente é o conceito de não alterar uma variável diretamente mas sim usando uma função. Isso faz com que a variável fique "encapsulada" dentro do objeto e permite que qualquer lógica seja aplicada na alteração daquela variável. E é exatamente o que você quer fazer... Toda vez que as variáveis A e B são alteradas existe uma certa lógica ocorrendo com elas, não é? Então eu sugeriria você colocar tudo dentro de uma struct e implementar funções para modificar os valores de A e B. Tipo assim: struct var {
  4. opcode = (ir & 0xf000)>>12; Quando você fez isso daqui, você pegou os 4 bits mais significativos de ir. Para pegar só 1 é a mesma coisa, só vai mudar o número de bits setados no valor com que está sendo feito o AND. if ( ac & (1 << 15) ) pc = address; // Negativo! ac é menor que zero if ( ac && !(ac & (1 << 15)) ) pc = address; // ac é diferente de zero e positivo.
  5. Acontece que ac é unsigned short int, por isso a comparação do if do C não interpreta como um número sinalizado. Mas aí é só você fazer um casting para um número sinalizado que o código já vai estar correto. Exemplo: if((short int)ac < 0) pc = address; Mas se por algum motivo você quiser fazer a verificação manualmente, bastaria você pegar o bit mais significativo (MSB) do número e ver se ele está ligado ou não. Se estiver, significa que o número é negativo... Mas como eu disse, isso não é necessário.
  6. Você não está atualizando o registrador "pc" corretamente. Remova as linhas "pc = pc + 1;" e, ao invés disso, atualize o pc imediatamente após carregar a instrução da memória. Tu pode fazer assim: ir = Mem[pc++]; O pc precisa ser atualizado sempre que uma instrução for executada. Como você só estava atualizando em algumas instruções, o loop ficava rodando indefinidamente porque pc estava sempre apontando para a mesma instrução. Sobre saber se as instruções fazem o que era esperado... Para isso eu sugiro que você compile o código no seu PC, execute e veja se o resultado foi o espe
  7. Injeção de código é uma técnica que consiste em adicionar instruções extras em um executável. Essas instruções podem ser adicionadas em vários lugares do programa, inclusive executar antes do entry point original. O uso mais comum para injeção de código é para fins maliciosos, onde um shellcode poderia ser inserido no executável e dar acesso remoto para um atacante. Mas um exemplo de uso "justo" para essa técnica é para fins de patching no executável quando você quer que algo seja alterado em tempo de execução no binário. Se você já tentou injetar código em um executável manualmente
  8. Opa, não apenas é possível como é o hobby de muita gente kkk. O primeiro passo para fazer a engenharia reversa em um firmware é justamente fazer o dump (você usou o termo certo) do código do firmware, isto é chamado de extração de firmware. Sobre ter bloqueios, sim muitas vezes pode ter. Mas existem técnicas para tentar burlar alguns bloqueios. Eu não manjo do assunto mas vou te passar referências de quem manja: Embedded Hacking: Extração de Firmware usando SPI H2HC University 2018 - Internet of Sh!t - Hacking de Dispositivos Embarcados - Maycon Vitali Os dois conteúdos é do
  9. Texto ocupa muito espaço visual, mas não tanto espaço em memória. Por exemplo, um artigo de 65536 caracteres é grande "pakas" para se ler, mas só ocupa 64 KiB. (considerando somente caracteres ASCII) O que é muita coisa para um embarcado com 32 KiB, mas para uma requisição HTTP com um servidor não é lá grande coisa a ponto de causar uma negação de serviço. Por exemplo no PHP, o tamanho máximo para upload de um arquivo é por padrão 2 MiB. Uma imagem em full HD pode alcançar fácil 4~5 MiB. Agora respondendo as perguntas: Depende da infraestrutura do site e como ele foi programado. Um s
  10. Tenho uma ferramenta em Bash no meu GitHub chamada 'new' que pode ser útil para gerar executáveis assim, sem precisar de modificar "na mão". No repositório tu pode olhar a pasta "templates" que um deles é o bin-elf64. A sequência de comandos ficaria assim: $ nasm tst.asm -o tst.bin $ new bin-elf64 file=tst.bin out=tst $ chmod +x tst $ ./tst Um "Hello World!" fica com 171 bytes. Mas um detalhe: Menor não necessariamente significa melhor. Isso aí é só de brincadeira, o executável não vai ficar mais eficiente porque você "capou" ele. Mas como passa-tempo é válido.
  11. A questão é que usando um registrador de 64 bits, a instrução divide o valor contido em RDX:RAX pelo valor passado como operando. Considere que RDX são os 8 bytes mais significativos do valor, e RAX seriam os 8 bytes menos significativos. Simplesmente zerar RDX traria um resultado incorreto se o número em RAX fosse negativo, o certo seria fazer um sign-extend e a instrução CQO faz isso para você: mov rax, 2345 cqo ; RDX:RAX = sign_extend(RAX) idiv rbx
  12. Colega, pelo que pesquisei aqui isto é uma instrução intrísseca do compilador do Visual Studio (Microsoft). Tem muita coisa em C que não é padronização da linguagem mas sim de alguma implementação específica, esta é uma delas. https://docs.microsoft.com/pt-br/cpp/intrinsics/sidt?view=vs-2019 Se você usa o GCC, e suponho que sim, você pode usar Inline Assembly para isso. (outros compiladores também suportam Inline Assembly, mas com sintaxe diferente) Vou deixar um exemplo: #include <stdio.h> #include <inttypes.h> typedef struct idtr_s { void *base; uint16
  13. $ gcc jonth.c -o test.c -E Eu usei -E do GCC para ver o conteúdo expandido. Depois procurei pelo texto "main(" no arquivo de saída e encontrei. Aproveitando das diretivas de linha que o GCC insere, eu vi que o conteúdo estava expandindo no arquivo /usr/include/X11/Xlib.c na linha 3889. Nesta linha contém a seguinte declaração: extern XIM XIMOfIC( XIC /* ic */ ); O `#define` da linha 5 seta o macro de nome XIMOfIC. Perto do final desse macro nós temos um macro "O" ali. Veja em negrito: Acontece que aonde tem esse "O" é expandido o conteúdo do macro B. Pelo visto um
  14. Não, eles não fazem a mesma coisa. O código em Assembly é para 32-bit e faz uma chamada para a syscall write do kernel Linux. Já o código em C é compilado para 64-bit e faz uma chamada para a função printf() da libc. Os código são diferentes porque são diferentes. Além disso C é uma linguagem de alto nível, então é de se esperar que haja mais código no executável do que o programador consegue enxergar. C ainda é minimalista, mas experimenta ler o código de outras linguagens de alto nível para ver a diferença absurda. Ah, e só porque o resultado é o mesmo não quer dizer que esteja fa
  15. Concordo plenamente. De qualquer forma, foi uma excelente descoberta de sua parte.
  16. Sim, eu quero vê-las e agradeço as críticas. Sobre o binário, é que eu vejo muitas pessoas que não são capazes de separar o conceito do sistema numérico binário do próprio código de máquina em si. Por exemplo, já vi gente vendo um número em binário de uma letra ASCII e falando que era "o código de máquina da letra A". Outros já vi afirmando que binário é uma criptografia. Por isso eu tentei deixar claro que código de máquina é uma coisa, e o sistema numérico binário é outra. Embora o código de máquina seja fisicamente em sistema binário. E o mesmo vale para hexadecimal, já vi pessoas ach
  17. Galera, estou escrevendo uma série de artigos no Medium explicando o básico do código de máquina da arquitetura x86. (desconsiderando o modo de 64-bits e outras tecnologias que eu não estudei) Essa informação pode ser útil para entender melhor o Assembly da arquitetura e também se alguém, por algum motivo aleatório, quiser desenvolver um assembler, disassembler, emulador ou qualquer outra ferramenta que exija esse conhecimento. No final de cada artigo tem um link para a próxima parte, mas mesmo assim irei deixar todas as partes indexadas aqui. Quando eu escrever novas partes irei come
  18. Fui o único que votou no projeto Bumerangue. ☹️
  19. Sim, falhas do tipo continuam sendo encontradas. E sempre serão, não acredito que um dia haverá um sistema 100% seguro.
  20. Não sou lá um especialista no assunto, mas enquanto não aparece uma pessoa mais qualificada você vai ter que se contentar com o que eu sei. rsrsrs :P Antes de mais nada esse método é para atacar redes WPA2-PSK, que é um dos métodos de autenticação que uma rede WPA2 suporta. Geralmente esse método de autenticação mais simples é usado em residências. Empresas usam o outro método porque é mais seguro. (não sei como o outro método funciona, nem pergunte.) O "método tradicional" para quebrar uma senha de uma rede WPA2 segue três passos simples: 1) Monitorar o tráfego no canal em que se
  21. Hehehe, comigo foi o contrário. Eu já sabia Assembly quando comecei a aprender C, aí eu compilava código em C e lia em Assembly para entender melhor o funcionamento do executável gerado. O próprio GCC oferece opção para apenas compilar o código, sem montar nem linkar ele. Dessa forma é possível ler o Assembly. Só usar: $ gcc programa.c -o programa.asm -S # Com sintaxe da Intel $ gcc programa.c -o programa.asm -S -masm=intel Fica a dica para quem quiser dar uma olhada. É interessante também usar o objdump para ver o programa depois de linkado. Opção -d do objdum
  22. @Leandro Fróes. Posso ter interpretado errado o texto dele, mas eu acho que não era ASLR. Ele disse que quando clicou "RUN" ele foi para o endereço 401000. Eu não sei o motivo e nem sei do que se trata, mas quando eu abro um executável no EDB ele também executa um código antes do entry point. Fica na região de memória do ld-2.26.so então eu imagino que seja alguma inicialização do S.O. Deve ser o mesmo caso no Windows. Mas como eu já disse eu não sei direito do que se trata. Inclusive eu queria perguntar aqui sobre isso e me esqueci.
  23. Olha eu vou te dar a "dica", mas você não vai gostar. 1) Você tem experiência com desenvolvimento de drivers? Se não, começa estudando isso. 2) Depois que ter pelo menos alguns meses de experiência com desenvolvimento de drivers, começa a estudar engenharia reversa. O curso CERO do Papo Binário é um bom começo... Eu imagino que ele já esteja completo quando você terminar de estudar sobre drivers. 3) Após o CERO aprenda Assembly. Mas cuidado para não aprender Assembly da arquitetura errada, existem várias linguagens Assembly... 4) Sabe redes? Se não, estude. Se sim, estude mais ai
×
×
  • Create New...