Jump to content

Fernando Mercês

Administrators
  • Posts

    1,646
  • Joined

  • Last visited

  • Days Won

    236

Posts posted by Fernando Mercês

  1. Nunca vi isso não... o que tive no Windows é problema com a sincronização da hora. Resolvi assim (como administrador no Prompt de Comando):

    tzutil /s "E. South America Standard Time"
    w32tm /config /manualpeerlist:pool.ntp.org,0x8 /syncfromflags:MANUAL
    net stop w32time
    net start w32time
    w32tm /resync /rediscover

    Não sei se vai ajudar no teu caso, mas pode servir para embasar uma busca pela solução.

    Abraço!

  2. Em 01/01/2025 em 10:18, Jorge Luiz Gouveia Sousa disse:

    Como faço o debug do código pelo GDB?

    gdb ./teste

    Aí começa. Dá uma busca por "gdb básico" no Google. Tem vários tutoriais e vídeos.

    Em tempo: removi seu post perguntando se tem alguém para ajudar. Não precisa postar isso tá? O post com a pergunta tá implica que você tá pedindo ajuda. 😉 

    Abraço.

  3. Opa, o include com nome do arquivo  é necessário sim. Mas depois disso você tem que utilizar a macro, ou seja, “chamá-la”. Em outras palavras, digitar o nome dela. 🙂

    O SEGFAULT é porque o programa não chamou a SYS_exit(), mas quando você usar as macros vai parar. 😉

    Abraço!

  4. 8 horas atrás, Jorge Luiz Gouveia Sousa disse:

    Vou usar jmp em vez de call! Depois passo para call!

    Beleza. Nesse caso, saiba que você vai precisar de uma instrução JMP no final do procedimento para voltar para onde estava. Algo assim:

    _start:
    	; código
    	jmp soma
    depois_da_soma:
    	; código
    soma:
    	; código
    	jmp depois_da_soma

    Do contrário o fluxo vai para a soma e não volta para onde deveria. Ao invés disso, vai continuar para a próxima instrução depois da última instrução do seu rótulo soma. O mesmo deve ser feito para os outros rótulos.

    Alternativamente, você pode por uma coisa depois da outra, sem saltos, só para começar (depois você implementa os saltos):

    _start:
    soma:
    	; código
    int_para_string:
    	; código
    imprimir:
    	; código
    final:
    	; código

    Agora vamos aos problemas nos seus rótulos:

    • Em int_para_string, você não vai usar nenhuma syscall, por isso não tem que ter aquele int 0x80 ali.
    • Em imprimir, você tá usando a syscall write (eax=4). Ela precisa de três parâmetros:
      • O file descriptor (fd) onde você quer escrever, em ebx (no caso como você quer imprimir na tela, ebx precisa ser 1).
      • O endereço do buffer para ser escrito, em ecx.
      • O tamanho do buffer a ser escrito, em edx.

    Ou seja, antes de chegar na int 0x80 dela, você precisa desses três parâmetros configurados.

    Logo, você precisa de uma terceira "variável" na seção .data para o resultado, ou pode sobrescrever a sua x ou y. No início do rótulo de imprimir você pode fazer:

    mov byte [resultado], al
    mov ebx, resultado
    

    A primeira instrução vai pegar o byte que está em AL (a parte baixa de AX, que é a parte baixa de EAX), que conterá o seu 0x36 (6 + '0') e copiar para o buffer resultado (como disse antes, se quiser usar o próprio x ou y, fique à vontade pois nesse momento você não precisará mais deles).

    A segunda vai pegar o endereço de resultado e por em ebx, que é o que a syscall write precisa.

    O tamanho do buffer será 1 também, pois você vai imprimir apenas um caractere. Então você precisa por 1 em edx antes de chegar na int 0x80 do imprimir, que vai chamar a write.

    Depois que isso funcionar a gente segue aumentando o programa com a lógica que você quer, o que acha? 🙂

    PS.: Tem um botão para postar código aqui no fórum. No editor, é o botão <>. Fica bem melhor de lermos se você utilizá-lo, e será mais fácil te ajudar. 😉 

    Abraço.

  5. Oi @Jorge Luiz Gouveia Sousa, beleza? Recomendo começar pela função de soma(), que é mais simples que a int_para_string().

    Outra coisa, você tá trabalhando em Intel 32-bits e há convenções de chamadas estabelecidas para esta arquitetura. Veja:

    Para complementar, leia aqui também: https://mentebinaria.gitbook.io/engenharia-reversa/assembly/funcoes-e-pilha

    No entanto, não vejo problema em você criar a sua própria convenção de chamadas para fins de estudo. No caso, o jeito que você escolheu para passar os argumentos para a função tá sendo via registradores (EAX e EBX no seu exemplo). Depois disso você vai precisar da instrução CALL e no fim da sua função, a instrução RET. Já que você começou assim (passando argumentos via registradores), pode seguir depois você muda para uma convenção mais convencional se quiser.

    Tenta aí e volta com o que conseguiu que a gente ajuda mais. 😉

    Abraço e bons estudos! Muito legal o desafio! 

  6. Olá!

    Recomendo remover suas informações de contato.. principalmente telefone e e-mail, para evitar receber spam. 😉

    Quanto ao problema, de fato o API monitor só monitora chamadas externas. Se as funções que lêem os parâmetros do INI estiverem em uma DLL, você pode adicioná-la no API Monitor para ele monitorar, mas se as funções estiverem no próprio EXE alvo, aí não dá com ele. Penso que você pode usar breakpoints de hardware no acesso aos dados. Localize-os no dump do x64dbg e aí põe breakpoint de leitura no primeiro byte da string traduzida que você quer. Isso vai fazer o debugger parar quando algum código ler tal string. Aí deve ficar mais fácil encontrar o código defeituoso, que não põe a string na tela por algum motivo.

    Abraço!

  7. Oi @mateus.mota,

    Apesar do infeliz ocorrido, o tópico é muito interessante, valeu por compartilhar com a gente!

    A comunidade gamer é bastante talentosa, então eu não descartaria ameaças mais avançadas (rootkits), movimentações laterais e coisas do tipo. Eu não sei nos Windows atuais se uma reinstalação de fato formata ou só zera as configurações e restaura arquivos a partir de alguma partição. Se o malware infectou tal partição, ele pode estar persistente ainda.

    Você tem outros dispositivos na sua rede? Desconfiando de movimentação lateral, poderia ser possível que o atacante infectou outro dispositivo mantém persistência lá? Roteadores, câmeras de segurança, etc, qualquer coisa que tenha uma shell na real. Eu resetaria tudo para as configurações de fábrica.

    Sobre as contas em si, além de mudar a senha, recomendo:

    • Verificar se o 2FA está habilitado. Se não, habilitar por app (não por SMS). É legal desabilitar e reabilitar também para mudar a chave.
    • Verificar as sessões ativas e desconectar todas elas (inclusive a sua).
    • Se você sincroniza dados de browser, apagar tudo (cookies, arquivos temporários, extensões, etc).

    Tem a possibilidade de você estar reinstalando o malware de algum lugar.. OneDrive, Dropbox, etc?

    Sobre AV, eu compraria um se fosse possível. Uma vez um vídeo sobre o assunto.

    Vamos falando aí. Tem muita gente boa aqui na comunidade que pode dar várias ideias legais!

    Abraço!

  8. Olá! Eu sou da opinião de que quanto mais base, melhor, mas a escolha, ao meu ver, precisa levar em consideração outros fatores como qualidade da instituição de ensino, preço, proximidade da sua residência, segurança do caminho, etc.

    Em geral, penso que Ciência da Computação é a opção que daria a maior base (quatro anos). Junto a este há o de Engenharia da Computação (foco maior em hardware) e Sistemas de Informação (foco maior em sistema). Se não me engano, todos são de quatro anos.

    Como segunda opção, vem os tecnólogos (um pouco menos de base, de dois a três anos) que compreendem ADS e Redes.

    Dá pra perceber que não existe uma resposta que funciona como uma bala de prata né? Um bom curso de ADS é provavelmente melhor que um curso de CC meia-bomba. Assim como um curso de Redes perto pode ser melhor pra você que um curso de SI do outro lado da cidade (não queremos perrengue né?). O importante é estudar bastante e na melhor instituição possível dentro das suas possibilidades geográficas e financeiras, penso.

    Para pentest e forense, se eu tivesse que escolher um entre ADS e Redes do mesmo nível, ficaria com o primeiro. Posso estar enganado, mas os cursos de Redes focam em profissionais de administração de redes?

    Adoraria ler outras opiniões. 🙂

    Grande abraço!

  9. Olá!

    Em 23/09/2024 em 14:00, Cristian Liotto disse:

    Tentei debugar utilizando o rundll32 e passando ela como argumento, mas o processo simplesmente morre, tentei diretamente pelo x64dbg mas também não vai

    Se o código malicioso dela tá na DllMain(), você precisa parar lá. Tem duas alternativas simples: por um breakpoint na LoadLibrary() ao debugar o rundll32.exe (passando sua DLL como argumento) ou setando o EIP na mão para a DllMain() ao abrir a DLL direto no x64dbg.

    Também acho importante ver como o processo chama a DLL. Aï você pode imitar e fazer igual para ver o comportamento malicioso. 🙂 

    Vê se a aula 21 do AMO te ajuda. 😉

    Abraço e boa sorte!

  10. Oi @Jorge Luiz_,

    Construções como if, else, for, while, etc são de alto nível. Em Assembly, elas são implementadas utilizando saltos (em x86, são as instruções começando com "J", de "jump"). Por exemplo, analise o código abaixo:

    cmp eax, 0
    jne exit
    ; código se EAX é zero
    
    exit:
    ;  resto do código

    No exemplo, há uma comparação de EAX com zero. Se não for zero, o programa vai saltar (JNE - Jump If Not Equals) para o rótulo (labelexit. Mas se EAX for zero, o código logo abaixo do salto (JNE) será executado (e depois o que está sob o rótulo exit também).

    O que acontece é que alguns compiladores de Assembly possuem macroinstruções que facilitam este trabalho e funcionam de forma similar às instruções de alto nível. Por exemplo, no fasm você pode fazer:

    .if eax = 0
        ; código se EAX é zero
    .endif
    
    ; resto do código

    Mas no binário compilado, você verá os saltos de qualquer maneira, pois estas são instruções "reais" que o processador entende (enquanto .if só o compilador Assembly entende). Além disso, os rótulos somem pois os destinos da maioria dos saltos são deslocamentos (X bytes para frente ou para trás), o que na prática vira endereços de memória. Veja:

    fasm_if.png

    Dá uma olhada: http://flatassembler.net/docs.php?article=win32#2.2

    Abraço!

    • Agradecer 1
  11. A explicação é complicada (para os meus parâmetros hehe), mas vou tentar. 🙂

    1. *argv[] na main() já é um ponteiro para um array de chars. Mas é uma variável, e tem um endereço de memória (supomos, 0x200).
    2. Para a sum(), ao fazer &argv você passa o endereço de argv, ou seja, 0x200.
    3. Na sum() você recebe esse endereço como um ponteiro para ponteiro para um array de chars: **args[]. O que está certo.
    4. Na sum(), args contém um único elemento (o ponteiro para um array chars e não o array de chars em si).
    5. Com *args[i], sabendo que a precedência de [] é maior que a de *, então vamos analisar o loop:
      1. args[0] é o primeiro (e único) elemento de args. *args[0] o acessa.
      2. args[1] falha, pois args só contém um elemento. Segfault aqui.
    6. Agora, com (*args)[i]:
      1. (*args) é resolvido primeiro em todas as iterações do loop. O resultado é um ponteiro para um array de chars.
      2. (*args)[0] funciona, assim como (*args)[1], (*args)[2], até argc-1.

    Um desenho certamente explicaria melhor, ou talvez com o uso do GDB. Se não entender, avisa aí que eu tento de outra forma. Ou talvez outra pessoa explique melhor. 🙂

    Em tempo, você complicou mais do que precisa. O que eu faria é:
     

    sum(int n, char *args[]) {
    	// código
    	strtol(args[i], ...);
    }
    
    main(int argc, char *argv[]) {
    	// código
    	sum(argc, argv);
    }

    Dessa forma você passa o argv, que já é um ponteiro para um array de char (C strings, neste caso) para sum() e ela acessa por args, que é do mesmo tipo.

    Outras ideias, só por curiosidade:

    Economizando a variável i ao somar do último para o primeiro elemento (ou seja, na ordem reversa):

    int sum(int n, char *args[])
    {
       int result = 0;
       n--;
    
       while (n > 0) {
          result += strtol(args[n], NULL, 10);
          n--;
       }
    
      return result;
    }

    Economizando o uso de argc, já que o último elemento de argv é sempre nulo - ou seja, argv[argc] == NULL:

    int sum(char *args[])
    {
       int result = 0;
    
       while (*args) {
          result += strtol(*args, NULL, 10);
          args++;
       }
    
      return result;
    }

    Ou uma versão menorzinha, aproveitando que ++ é um operador de pós-incremento (primeiro o valor é lido e depois é incrementado):

    int sum(char *args[])
    {
       int result = 0;
    
       while (*args)
          result += strtol(*args++, NULL, 10);
    
      return result;
    }

    Mas aí já entram mais conceitos.. por exemplo *args é o mesmo que fazer *args != NULL. E args++ é aritmética de ponteiros. Não é "mais um" e sim "mais X bytes", onde X é o tamanho do tipo.

    Versão "olha mãe, sem as mãos":

    int sum(char *args[]) {
       return *args ? strtol(*args, NULL, 10) + sum(args + 1) : 0;
    }

    Aqui já entra recursividade (pode esgotar a pilha) e o ternário.

    Fiz essas coisas só para despertar a curiosidade mesmo e provar que C é a linguagem na qual o universo foi escrito. 😄 

    Abraço.

    • Agradecer 1
  12. Não existe um suporte nativo, mas tem gambiarras possíveis:

    ; Opção 1 - Simplesmente um ponto-e-vírgula no início de cada linha (mas essa você já sabe)
    ; linha1
    ; linha2
    ; linha3
    
    ; Opção 2 - Começa com ponto-e-vírtugla e protege o caractere de fim de linha com a contra-barra
    ; linha1\
    linha2\
    linha3
    
    Opção 3 - Testar se uma macro inexistente existe
    %ifdef COMENTARIO ; pode ser qualquer coisa, contanto que não exista - ou seja, não esteja definida
    linha1
    linha2
    linha3
    %endif
      
    Opção 4 - Avaliar uma expressão numérica que retorne falso sempre
    %if 0
    linha1
    linha2
    linha3
    %endif

    Abraço.

  13. Acho que se você postar o código - e o programa alvo se puder, ajuda mais. 🙂

    Pensando aqui que pode ser alguma proteção no programa alvo, para evitar isso, mas pode não ser também. hehe

    Abraço.

  14. Opa,

    Em 04/07/2024 em 13:14, Guilherme23 disse:

    vai informar pelo Youtube também ?

    Sim, por todos os nossos canais. 🙂

    Em 04/07/2024 em 13:14, Guilherme23 disse:

    Será necessário algum conhecimento prévio?

    Sim, os requisitos estão no fim do texto aqui.

    Abraço!

  15. Oi @Guilherme23, tudo em paz e contigo?

    Estamos planejando uma turma do curso A Arte da Engenharia Reversa (pago, online e ao vivo). Em relação aos cursos gratuitos, não lançaremos outros sobre estes tópicos este ano. Segue um resumo do que temos sobre ER e 😄

    Sobre C, temos:

    Há ainda um livro muito legal de dicas de C e Assembly que o autor nos permitiu disponibilizar para download aqui. Chama-se Dicas - C e Assembly para arquitetura x86-64.

    Por hora, isto é tudo. 🙂

    Grande abraço e bons estudos. Qualquer outra dúvida é só falar.

    Abraço!

  16. Em 05/06/2024 em 14:37, rsievering@hotmail.com disse:

    Existe algum certificado que eu possa emitir.???

    Opa, tudo bem? Obrigado por terminar o curso! No momento não emitidos certificados para os cursos livres pois não temos nenhuma maneira automatizada de fazê-lo.

    Um abraço!

  17. Olá!

    Se alguém tiver tempo, pode ser que consiga te ajudar sim, mas se você quiser aprender e fazer você mesmo, ou se unir com alguém da comunidade e fazer junto, recomendo que comece pelos nossos treinamentos gratuitos aqui. Dependendo do quanto você já conhece, pode ser interessante fazer o de C primeiro e depois o CERO. Aí você pode estudar também pelo livro Fundamentos de Engenharia Reversa e o de Assembly, ambos gratuitos. Tá tudo no menu Ensino aqui mesmo no nosso site. 🙂

    Abraço,

    Fernando

×
×
  • Create New...