Ir para conteúdo
  • Cadastre-se

Todas Atividades

Atualizada automaticamente     

  1. Hoje
  2. Ah, sobre o modo de operação ECB, o principal problema não é revelar dicas sobre a chave e sim dicas sobre o cifrotexto. Uma mensagem de "Bom dia!" enviada toda manhã, por exemplo, sempre resultará em um mesmo cifrotexto, dando dica para um atacante sobre o que aquele cifrotexto significa. Chamamos isso de falta de segurança semântica. Isso também afeta a segurança da transmissão de outras mídias que não texto. Um exemplo clássico é essa imagem do pinguim cifrada com ECB em comparação com a utilização de um modo de operação adequado.
  3. Sobre segurança: Ao transformar/expandir uma chave ou um password utilizando uma função de hash é importante ter em mente que se essa entrada original for menor que a chave do AES a segurança será reduzida ao tamanho dessa entrada. Assim, se você tem um password de 2 bytes, a segurança do seu AES está sendo reduzida de 128 bits (caso do AES-128) para 16 bits. No caso contrário, se a entrada for maior que 128 bits, a segurança também será reduzida a 128 bits (limitado pela segurança da cifra de bloco). No caso de estar utilizando um password como entrada, também é importante adicionar um Salt à entrada dessa transformação para evitar ataques que utilizam rainbow tables. E, se possível, utilizar uma função de password hash, como o argon2 ou lyra2, que são computacionalmente mais custosas/lentas e tornam os ataques se busca por colisão mais caros ou demorados.
  4. Muito bom, parabéns! Seguem apenas umas dicas sobre os termos de acordo com o que observo na literatura da área em língua portuguesa. Cifra normalmente é utilizado para designar o algoritmo de cifração. Exemplo: o AES é uma cifra de bloco. A saída de um algoritmo de cifração comumente é chamado de cifrotexto ou texto cifrado, e o inverso é chamado de texto claro. Galois Fields são traduzidos comumente como corpos de Galois ou corpos finitos. Os esquemas que permitem cifrar mensagens maiores que um bloco são chamados de modo de operação de cifra de bloco, ou simplesmente modo de operação.
  5. Ontem
  6. Eis um texto meu explicando o AES. Espero que gostem: https://bitismyth.wordpress.com/2017/05/19/wanna-laugh-ou-criptografia-no-refugio-dos-elfos/
  7. Em linguagens com tipagem, como é o caso de C, existem inteiros sinalizados (possuem valores negativos) e não sinalizados (apenas valores positivos). É intuitivo, para o estudante, pensar que valores negativos como sendo aqueles que tem um sinal '-' na frente do número, no entanto, não é assim que as coisas são feitas pelo processador. Não há como colocar um '-' na frente de um valores binários, nos circuitos do processador ou do computador. Acredito que eu já tenha digo, por aqui ou em meu blog, que valores inteiros sinalizados são meras representações e que, na realidade, eles não tenham sinal algum. Ou seja, a maneira como são interpretados é que dá sinal ao valor, na hora de ser convertido de e para a base decimal... É também comum que essa representaçao use a técnica do "complemento 2", onde o bit mais significativo do valor indica ao programa que esse valor pode ser interpretado como sendo negativo. Mas, o que diabos significa "complemento 2"? Que "complemento" é esse? Daqui por diante farei de conta que nosso processador hipotético tenha registradores de apenas 4 bits só para não ficar escrevendo um montão de bits, mas os raciocínios aplicam-se a 8, 16, 32, 64 e a 128 bits facilmente. Comecemos com os inteiros não sinalizados... Com 4 bits, todos os valores possíveis são de 0b0000 até 0b1111, ou, em decimal, de 0 a 15. Não há qualquer mistério ai. As operações aritméticas funcionam perfeitamente bem, desde que não tenhamos condições de overflow (exemplo: 0b0000 - 0b0001 = 0b1111, ou 0 - 1 = 15?). Se quisermos trabalhar com esses valores como se existissem valores negativos, um macete é encarar o bit mais significativo (msb) como se fosse um indicador de sinal (como se fosse o '-'). Se o msb for 0 temos um valor positivo, na faixa de 0 a 7 (0b0000 até 0b0111), se o msb for 1, temos valores negativos (discussão sobre a faixa segue abaixo). Poderíamos simplesmente parar ai, ou seja, -1 poderia ser representado como 0b1_001 (msb='-' e 1), mas isso causa problemas nas operações aritméticas fundamentais... Como vimos, 0b0000 - 0b0001 = 0b1111, ou seja, nessa representação teríamos como resposta -7 (que poderia ser encarada como uma condição de overflow, mas não é, como veremos). Outra técnica é a inversão de todos os bits de um valor positivo para obter o negativo e usarmos apenas o bit 1 como sinalização. Com o mesmo exemplo, -1 seria ~0b0001 = 0b1110, ou seja, o "inverso" de 1 (operação NOT) seria -6, o que ainda está errado. Mas essa representação é usada em computadores antigos, com alguns ajustes. Por exemplo, sempre que toparmos com o msb=1 devemos inverter o valor para obter seu absoluto... assim, ~0b1110 volta a ser 1, interpretado como negativo, e estaria tudo certo. Mas temos um problema: E quanto ao valor 0b1111? Seu inverso, obviamente, é 0b0000, o que significaria que temos +0 e -0 e, usando aritmética binária elementar 0b0000 - 0b0001 = 0b1111, ou seja, nessa representação temos +0 - +1 = -0 (menos zero?). A solução para isso foi o uso do conceito de complementação da faixa dos positivos. Se temos 8 valores positivos de 0b0000 até 0b0111, na sequência ascendente, podemos copiar a sequência, mudando apenas o msb para 1 e colocando-a "antes" da faixa dos positivos (de 0b1000 até 0b1111). Assim: 0b1000, 0b1001, 0b1010, ..., 0b000, 0b0001, ... Assim, temos 8 valores negativos antes do zero, na sequência {-8, -7, -6, ... 0, +1, ..., 7}. Ou, de outra maneira, um valor sinalizado pode ser calculado de acordo com a seguinte equação: Eis o "complemento 2", trata-se apenas da "complementação" da faixa dos inteiros positivos (quando s=0), na sequência, ascendente que mostrei, pela mesma sequência, mas com s=1. Onde: s é o msb e P é a precisão, em bits, do valor (lembrando que "precisão" é a quantidade de bits que expressa o valor absoluto - isso vale tanto para inteiros quanto para ponto flutuante). No nosso caso, P=3 e s é o bit 3. Vejamos como fica -1: Se 0b1111 é -1, então, pela equação acima temos (-1*2³)+(4+2+1) = -8+7 = -1. Isso faz com que as operações aritméticas fiquem corretas, exceto no caso de overflows, e não temos mais dois zeros: 0b1000 = -8. Existe, é claro, uma aparente assimetria de valores. No lado negativo o menor valor é -8 e no lado positivo o maior é +7. Isso é inevitável, já que temos uma quantidade par de valores possíveis, dividindo toda a faixa em dois blocos de 8 valores, onde um deles é 0 (que ficará do lado positivo). O único problema aqui é que -8 será sempre -8, se interpretado com sinal. Não é difíil perceber, embora eu gastaria muitas palavras aqui para descrever, que a fórmula acima pode ser substituída, lógicamente, por uma simples operação NOT seguida de um incremento de uma unidade para realizar a transformação de um valor positivo para negativo e vice-versa, ou seja, a operação de negação (o '-' unário de C e a instrução NEG do x86) só fazem y=~x+1. E essa é outra interpretação do significado do "complemento 2": Se o "complemento 1" for definido como a simples inversão, ao somar 1 temos um "complemento 2". Quanto aos overflows, eles acontecem, como sempre, na passagem dos extremos da faixa. -8 - 1 resultará em +7, assim como 7+1 resultatá em -8. Resumindo: inteiros sinalizados são uma representação, o seu processador sempre lida com valores sem sinal, mas mantém flags interpretando os valores com e sem sinal (CF para não sinalizados e SF e OF para sinalizados - e ZF para ambos -- em outros processadores, como ARM, por exemplo, os flags são nomeados, respectivamente, C, N, V e Z, de carry, "negativo", "oVerflow" e Zero). Agora dá para entender porque, em C, ao fazer,: unsigned int x = -1; Obtemos 0xffffffff?
  8. Resolvi fazer de outra forma, mas ainda assim valeu pela ajuda 😄
  9. Esse CrackMe merece um vídeo no canal hem!
  10. O melhor curso que já vi sobre o assunto, Fernando você e nota dez.
  11. Última semana
  12. Visitante

    Curso de Engenharia Reversa Online (CERO)

    Ótimo curso, tenho aprendido muito.
  13. Tem esse aqui bem legal também com jogo de GBA: https://www.megabeets.net/reverse-engineering-a-gameboy-rom-with-radare2/
  14. Outro follow-up: A geração de código ineficiente foi aceita como bug a ser corrigido (até o momento) no bugzilla do GCC.
  15. Engenharia reversa em jogos não está nada distante da Engenharia Reversa utilizada em Análise de Malware, correção de bugs, etc, até porque os conceitos que ela envolve são os mesmo, não importa o local onde é aplicada. Falando em jogos, você conhece o Mega Drive? Sim, aquele console da Sega de 16 bits, lançado em 88 e com sucesso nos anos 90. Foi lançado em um blog uma espécie de CTF para o SEGA Genesis (nome popular para o Mega drive) que se resume à "apenas" um desafio: reverter o jogo criado pelo autor e quebrá-lo utilizando um emulador. O autor disponibilizará o código fonte daqui um tempo, mas até lá você pode mandar um e-mail e/ou twitter com sua resolução!! Se pararmos para pensar este desafio parte de uma abordagem ofensiva, mas será que além de burlar há uma maneira de defender este ou outro jogo? 🤖
  16. Um follow-up no que concerne esse bug: Não é um bug! Recebi uma explicação convincente do Bugzilla do GCC, onde me foi dito que a segunda chamada é feita apenas para ajustar o errno (errno = EDOM, quando x < 0). Mas, de qualquer modo, o código é ineficiente (comentário meu)... Em essência, o GCC está fazendo o que deveria mesmo fazer. Só mais um aviso: Não é necessário o uso de assembly inline para obter uma única instrução SQRTSS, SQRTSD ou FSQRT. Basta adicionar a opção -ffast-math (que não é habilitada com -O2 ou -O3 -- mas é habilitada com a opção -Ofast)...
  17. Entendo... mas acho que as sentenças acima, com algumas pequenas alterações para caberem no texto, explica melhor do que dizer que um computador binário não é binário... 🙂
  18. Concordo plenamente. De qualquer forma, foi uma excelente descoberta de sua parte.
  19. 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 achando que código de máquina é hexadecimal porque abriu um binário em um editor hexa e viu os bytes em hexadecimal... Sobre o resto, vou revisar. Muito obrigado.
  20. Recentemente divulguei uma descoberta minha, que, acho, ninguém prestou atenção antes, sobre a geração esquisita de código do GCC em relação à função built in sqrt()... Anunciei isso em outros foruns e tentei reporta para o bugzilla do GCC (não consegui!). Eis algumas reações: Nunca disse que não segue, mas que o GCC está criando código inútil. Ao apontar isso o sujeito usa aquele ar de profundo conhecedor do padrão (e o total desconhecimento de Assembly) para me dizer, num forum sobre 😄 Além disso, nosso "profundo conhecedor" não sabe de coisa alguma dos bugs que ainda existem em compiladores C/C++ (tanto o GCC quanto o CLANG, VC++ e Intel C++, pra citar alguns)... A característica de alguém que busca minúcias para desqualificar os argumentos de outra pessoa e/ou mudar de assunto completamente para o mesmo fim é, na minha opinião, coisa de idiota...
  21. Algumas críticas, se é que você quer vê-las: Essa ideia de que "código de máquina não é binário" é bizarra, em minha opinião... A linguagem de programação é ASSEMBLY, não "código de máquina"... Há uma correspondência direta, ok, mas não são a mesma coisa... Acredito que para o novato (se é que os textos se destinam a eles) a coisa está num ritmo muito rápido... Por exemplo, na parte 2 você cita "flags", mas não os conceitua... []s Fred
  22. 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 comentar aqui no post. Código de máquina x86 — Parte 0 | Introdução Código de máquina x86 — Parte 1 | Conhecendo Código de máquina x86 — Parte 2 | Opcode Código de máquina x86 — Parte 3 | Prefixos
  23. O nome, agora, é contraditório (ARM=Advanced Risc Machine). O conjunto de instruções é tudo, menos restrito: https://is.gd/D2YIXu
  24. Um detalhe: O código do CLANG não só é mais elegante, quanto mais rápido (se ambos chamarem sqrtf()). Saltos condicionais para frente são assumidos, pelo algoritmo do branch predictor, do processador, como não tomados. Como a função builtin sqrt() geralmente será chamada com valores válidos, o processador não perde tempo corrigindo o salto, que, na maioria das vezes, não será feito. Mas, como eu disse, isso ai é um exagero dos compiladores... Um simples "SQRTSS XMM0,XMM0" resolve todo o problema... Anyway... por favor, notem que não estou dizendo que clang tende a gerar sempre código melhor que o GCC. Pelos meus testes ele costuma criar código próximo da performance do gerado pelo GCC, mas, neste caso, ele ganhou a parada (embora pudesse ser melhor!).
  25. Testei, agorinha, com o GCC 8.2 e o bug ainda está lá... Testei com o CLANG 6 e o bug não está lá. Ele gera até um código mais elegante: f: xorps xmm1,xmm1 ucomiss xmm0,xmm1 jb .lessthan0 sqrtss xmm0,xmm0 ret .lessthan0: jmp sqrtf Mas, essa chamada a sqrtf() é inútil, já que sqrtss retorna os mesmos valores para x < 0 e até valores inválidos como NAN e INFINITY.
  26. https://ibb.co/HqFbxDq
  27. Confirmado! Isso é um BUG do GCC, pelo menos até a versão 7.3 (do Debian/Ubuntu, pelo menos) para o x86 e ARM AArch64 e versão 6.3 para ARM AArch32... Embora a versão 7.3 do MinGW-64 (do linux) não tenha esse BUG... Não sei se foi resolvida na versão 8. Felizmente é um bug inofensivo, já que o resultado será o da instrução SQRTSS (ou SQRTSD, se for double) e a chamda à função da libm sqrtf() (ou sqrt()) será feita, mas ignorada... Se for lidar com raiz quadrada no x86 e usa o GCC, prefira a função inline em asm, como mostrei acima. ou modifique-a para não ignorar o returno de sqrtf() se x < 0...
  1. Mais Resultados
×
×
  • Criar Novo...