Ir para conteúdo

Fernando Mercês

Administradores
  • Postagens

    1.507
  • Registro em

  • Última visita

  • Dias Ganhos

    160

Posts postados por Fernando Mercês

  1. Opa, bem vindo @Crystoppher!

    Em algum momento da vida, o x64dbg passou a criar um símbolo exportado (na aba Símbolos/Symbols) chamado OptionalHeader.AddressOfEntryPoint. O nome deste símbolo vem do fato de o endereço do entrypoint ser um campo do cabeçalho chamado Optional Header. No disassembly, se você estiver diante de um endereço de um símbolo, o x64dbg coloca o nome do símbolo do lado. 😉

    Abraço.

    • Curtir 1
  2. Legais as perguntas! 🙂

    Em 17/10/2023 em 21:39, Nitczi disse:

    Na linha onde está "sar rax,cl" vi que isso é uma operação de bit shifting para a direita, pesquisei em alguns sites para ver como ficaria essa operação e o resultado é sempre 5, mas rodando o programa o resultado é 1, por que?

    O nome é deslocamento aritimético para a direita. Tem o deslocamento lógico também, que é feito pela instrução SHL. 😉

    O que essa instrução faz é, tomando o número em binário, "empurrar" todos os bits para a direita e aí o bit que "sobra" à esquerda é preenchido com zero ou um (caso ele já seja 1). Por exemplo:

    0011 SAR 1 = 0001
    1100 SAR 1 = 1110

    O código faz 0x1122334455667788 SAR 0x3c (60) na primeira iteração do loop. Para entender, você teria que converter 0x1122334455667788 para binário e fazer a operação de deslocamento aritimético para a direita sessenta vezes, entende? Então vamos lá:

    0x1122334455667788 em binário é: 0001 0001 0010 0010 0011 0011 0100 0100 0101 0101 0110 0110 0111 0111 1000 1000 (observe a parte em negrito, que será deslocada para a direita).

    Deslocando somente uma vez para a direita, teremos:

    0000 1000 1001 0001 0001 1001 1010 0010 0010 1010 1011 0011 0011 1011 1100 0100

    O zero foi colocado à esquerda porque o bit original era zero.

    Agora você teria que fazer o processo mais 59 vezes para chegar no resultado 1. 🙂

    Fiz um programa em Python aqui para simular, trabalhando com o número como se fosse uma string. Espero que não confunda mais. 🤣

    rax = '0001000100100010001100110100010001010101011001100111011110001000'
    
    print(f'rax = {rax}')
    
    for i in range(1, 61):
        if rax[0] == '0':
            rax = '0' + rax[:-1]
        else:
            rax = '1' + rax[:-1]
    
        print(f'rax SAR {i:02d} = {rax}')

    A saída é:

    rax = 0001000100100010001100110100010001010101011001100111011110001000
    rax SAR 01 = 0000100010010001000110011010001000101010101100110011101111000100
    rax SAR 02 = 0000010001001000100011001101000100010101010110011001110111100010
    rax SAR 03 = 0000001000100100010001100110100010001010101011001100111011110001
    rax SAR 04 = 0000000100010010001000110011010001000101010101100110011101111000
    rax SAR 05 = 0000000010001001000100011001101000100010101010110011001110111100
    rax SAR 06 = 0000000001000100100010001100110100010001010101011001100111011110
    rax SAR 07 = 0000000000100010010001000110011010001000101010101100110011101111
    rax SAR 08 = 0000000000010001001000100011001101000100010101010110011001110111
    rax SAR 09 = 0000000000001000100100010001100110100010001010101011001100111011
    rax SAR 10 = 0000000000000100010010001000110011010001000101010101100110011101
    rax SAR 11 = 0000000000000010001001000100011001101000100010101010110011001110
    rax SAR 12 = 0000000000000001000100100010001100110100010001010101011001100111
    rax SAR 13 = 0000000000000000100010010001000110011010001000101010101100110011
    rax SAR 14 = 0000000000000000010001001000100011001101000100010101010110011001
    rax SAR 15 = 0000000000000000001000100100010001100110100010001010101011001100
    rax SAR 16 = 0000000000000000000100010010001000110011010001000101010101100110
    rax SAR 17 = 0000000000000000000010001001000100011001101000100010101010110011
    rax SAR 18 = 0000000000000000000001000100100010001100110100010001010101011001
    rax SAR 19 = 0000000000000000000000100010010001000110011010001000101010101100
    rax SAR 20 = 0000000000000000000000010001001000100011001101000100010101010110
    rax SAR 21 = 0000000000000000000000001000100100010001100110100010001010101011
    rax SAR 22 = 0000000000000000000000000100010010001000110011010001000101010101
    rax SAR 23 = 0000000000000000000000000010001001000100011001101000100010101010
    rax SAR 24 = 0000000000000000000000000001000100100010001100110100010001010101
    rax SAR 25 = 0000000000000000000000000000100010010001000110011010001000101010
    rax SAR 26 = 0000000000000000000000000000010001001000100011001101000100010101
    rax SAR 27 = 0000000000000000000000000000001000100100010001100110100010001010
    rax SAR 28 = 0000000000000000000000000000000100010010001000110011010001000101
    rax SAR 29 = 0000000000000000000000000000000010001001000100011001101000100010
    rax SAR 30 = 0000000000000000000000000000000001000100100010001100110100010001
    rax SAR 31 = 0000000000000000000000000000000000100010010001000110011010001000
    rax SAR 32 = 0000000000000000000000000000000000010001001000100011001101000100
    rax SAR 33 = 0000000000000000000000000000000000001000100100010001100110100010
    rax SAR 34 = 0000000000000000000000000000000000000100010010001000110011010001
    rax SAR 35 = 0000000000000000000000000000000000000010001001000100011001101000
    rax SAR 36 = 0000000000000000000000000000000000000001000100100010001100110100
    rax SAR 37 = 0000000000000000000000000000000000000000100010010001000110011010
    rax SAR 38 = 0000000000000000000000000000000000000000010001001000100011001101
    rax SAR 39 = 0000000000000000000000000000000000000000001000100100010001100110
    rax SAR 40 = 0000000000000000000000000000000000000000000100010010001000110011
    rax SAR 41 = 0000000000000000000000000000000000000000000010001001000100011001
    rax SAR 42 = 0000000000000000000000000000000000000000000001000100100010001100
    rax SAR 43 = 0000000000000000000000000000000000000000000000100010010001000110
    rax SAR 44 = 0000000000000000000000000000000000000000000000010001001000100011
    rax SAR 45 = 0000000000000000000000000000000000000000000000001000100100010001
    rax SAR 46 = 0000000000000000000000000000000000000000000000000100010010001000
    rax SAR 47 = 0000000000000000000000000000000000000000000000000010001001000100
    rax SAR 48 = 0000000000000000000000000000000000000000000000000001000100100010
    rax SAR 49 = 0000000000000000000000000000000000000000000000000000100010010001
    rax SAR 50 = 0000000000000000000000000000000000000000000000000000010001001000
    rax SAR 51 = 0000000000000000000000000000000000000000000000000000001000100100
    rax SAR 52 = 0000000000000000000000000000000000000000000000000000000100010010
    rax SAR 53 = 0000000000000000000000000000000000000000000000000000000010001001
    rax SAR 54 = 0000000000000000000000000000000000000000000000000000000001000100
    rax SAR 55 = 0000000000000000000000000000000000000000000000000000000000100010
    rax SAR 56 = 0000000000000000000000000000000000000000000000000000000000010001
    rax SAR 57 = 0000000000000000000000000000000000000000000000000000000000001000
    rax SAR 58 = 0000000000000000000000000000000000000000000000000000000000000100
    rax SAR 59 = 0000000000000000000000000000000000000000000000000000000000000010
    rax SAR 60 = 0000000000000000000000000000000000000000000000000000000000000001

    Com isso você prova que 0x1122334455667788 SAR 60 é igual a 1. Mas na próxima iteração do loop, RAX sofrerá uma operação SAR com 56, que já não é 1, e por aí vai... Ou seja, não é que é sempre 1. 😉

    O objetivo deste programa é você imprimir na tela cada dígito hexa do registrador RAX, não importa o que você coloque lá. Testa com 0xf0f0caf0f0ca2023 por exemplo. 😉

    Abraço!

    • Agradecer 1
  3. De nada. 🙂

    Em 26/09/2023 em 09:36, Gabriel Guedes disse:

    Botao direito em um arquiv >> Enviar para / Abrir com >> Toolkit, é feito como? Pelo instalador? Com alguma entrada no Registro?

    Dá pra fazer por registro, mas eu tentei e vi que tem limite de aninhamento das opções. Acabei usando um software chamado sendto+. O Inno Setup pode escrever as chaves de registro se você escolher fazer via registro. No caso do retoolkit, eu instruo o script do Inno Setup para instalar (copiar) o sendto+ como um programa normal e criar os atalhos.

    Em 26/09/2023 em 09:36, Gabriel Guedes disse:

    E sim! Pode ter certeza que tambem vou adorar compartilhar!

    😍

    • Curtir 1
  4. Oi @Gabriel Guedes! Que legal sua decisão de estudar programação. Acho essencial para qualquer área da computação. 🙂

    Muito interessante o projeto de criar um instalador. Existem vários softwares que criam instaladores (Inno Setup, Nullsoft Scriptable Install System (NSIS), Setup Factory, etc), mas fazer o seu próprio é com certeza um projeto muito interessante!

    Vou tentar ajudar com as dúvidas:

    Em 26/09/2023 em 08:02, Gabriel Guedes disse:

    Quais bibliotecas / features ou tópicos eu devo me preocupar?

    Quase nenhuma. Normalmente instalar significa copiar arquivos para determinados diretórios, criar atalhos e escrever em chaves de registro. Tudo isso é feito com funções da biblioteca padrão em linguagens como C# e C++.

    Em 26/09/2023 em 08:02, Gabriel Guedes disse:

    Vi que o retoolkit usa o Inno Setup para criar o instalador, o trabalho dele é instalar os programas que fazer parte do kit apenas?

    Sim. O Inno Setup suporta uma linguagem própria de scripting e cria um instalador baseado no que está nesses scripts. O código-fonte do retoolkit consiste destes scripts.

    Em 26/09/2023 em 08:02, Gabriel Guedes disse:

    Como ele faz isso sem ter o .exe de cada programa ali?

    Eu não fiz upload dos arquivos dos programas para o GitHub porque não é uma boa prática colocar arquivos que não são de texto em repositórios git, mas eu os tenho na minha máquina, no diretório d:\ret, que é de onde o script pega os arquivos do programa. Perceba que isso tá especificado aqui. 😉

    Em 26/09/2023 em 08:02, Gabriel Guedes disse:

    Quais as vantagens de fazer em C# e quais as vantagens de fazer em C++?

    Acredito que você vá aprender mais sobre um ou sobre o outro. Acredito que C# seja um pouco mais fácil e você terá que se preocupar menos com a linguagem. Por que não faz primeiro com um e depois com o outro? Assim você estuda ambas. 🙂

    Em 26/09/2023 em 08:02, Gabriel Guedes disse:

    Existe algum programa semelhante que eu posso tomar como referencia além do Retoolkit?

    De cabeça não sei, mas você pode pesquisar por instaladores feitos nas duas linguagens.

    Adoraríamos ver o progresso do teu instalador aqui! 🙂

    Um abraço e boa sorte!

    • Curtir 1
  5. Oi @Samuel Araujo. Essa contagem faz sentido e é exatamente o motivo de o registrador r8 ser o r8. 🙂 Em arm por exemplo, ela é utilizada.

    No entanto, em amd64 os nomes originais foram mantidos acredito que porque preservam a ideia de sua função e também facilita pra quem já sabia i386. Por exemplo, rcx é o contador e por aí vai. Ninguém (?) usa a nomenclatura de r0 a r7 em amd64 mas o nasm a suporta sim: basta usar as macros definidas no pacote altreg no início do seu código. Veja:

    bits 64
    
    %use altreg
    
    SYS_WRITE equ 1
    STDOUT    equ 1
    SYS_EXIT  equ 60
    
    section .rodata
    
    msg:
     db `Registradores alternativos!\n`
     msg_len equ $ - msg
    
    section .text
    
    global _start
    _start:
     mov r0, SYS_WRITE
     mov r7, STDOUT
     lea r6, [msg]
     mov r2, msg_len
     syscall
    
     mov r0, SYS_EXIT
     xor r7, r7
     syscall

    Usar o pacote altreg é como definir os novos nomes você mesmo. Algo como %define r0 rax, embora o nasm use %idefine no pacote altreg, que faz a definição ficar insensível ao caso, permitindo R0, r0, RAX, rax, rAX, etc. Mais detalhes no arquivo macros/altreg.mac.

    Isso é só nome e só faz sentido no código-fonte. A instrução gerada no compilado é a mesma, quer você use r0, quer você use rax. O fonte vai ficar confuso já que ninguém (?) tá acostumado com isso em amd64. Além disso, tem que decorar a ordem. Perceba que o segundo registrador é rcx, não o rbx. A ordem é A, C, D, B. Depois vem o SP, BP, SI e DI. Lembrar disso "numericamente" representa uma dificuldade adicional, mas é possível claro.

    Abraço.

    • Curtir 1
  6. Oi @Ana Francisca,

    Você tá usando o NASM né? Ele suporta "Character Strings", ou seja, você escreve no fonte como string e ele compila como char (número). Ou seja, '3' vai gerar o número 0x33, que é o código do texto '3' na tabela ASCII. Dá uma olhada para entender mais:

    Se quiser o número 3 mesmo, então é só remover as aspas simples. O mesmo se aplica para os demais números.

    PS.: Em C isso também funciona com um caractere só. Por exemplo, char c = 'A' vai por o valor 0x41 na variável c.

    Valeu.

    • Curtir 2
  7. Oi Ana!

    Parabéns pela decisão em estudar Assembly. 🙂

    No teu código falta especificar o destino nas instruções MOV. Por exemplo: mov, 4 tá pedindo para mover/copiar o valor 4, mas para onde? Falta especificar um destino, entende? O que você precisa aí é saber em qual registrador você quer colocar tais valores. O nome do registrador vai antes da vírgula.

    Você pode ler mais sobre o assunto no nosso livro, por exemplo, ou em centenas de outros livros e artigos na internet.

    Outra coisa: em Assembly, você não "muda" o conteúdo de um label assim:

    mov nome, dword 'Jon' ; Mudar o nome Ana para Jon Linhares

    Para atingir o que você quer, o jeito mais simples é especificar, na seção .data, dois labels, nome1 e nome2, e aí usá-los um em cada bloco de código que imprime um nome.

    Por fim, a syscall que sai do programa é a SYS_EXIT. Ela recebe um argumento (você pode conferir aqui ou dando um man 2 exit). Sendo assim, você precisa fazer:

    mov ebx, 0
    mov eax, 1
    int 0x80

    Isso é equivalente à uma chamada exit(0), entende? E sair com o código de retorno zero é o padrão para dizer para o SO que "deu tudo certo". 😉

    Valeu!

    • Curtir 1
  8. Em 04/08/2023 em 07:43, jhow disse:

    Nao chegou nessa parte nao , ela da erro aonde eu mostrei...

    Então é mais um indício de que o software está ok e o problema é com a máquina mesmo. É cedo para afirmar, mas é um indício. 🙂

    Em 04/08/2023 em 07:43, jhow disse:

    Sao 2 ram de 4MB, eu fiz o comando mem /c e deu invalid keyword.

    Já experimentou remover os dois pentes de memória e limpar seus contatos com borracha? Ao ligar o PC, é legal ver no POST (aqueles testes que rolam quando o computador liga) se a memória está sendo reconhecida em sua totalidade (8MB no seu caso).

    Em 04/08/2023 em 07:43, jhow disse:

    Tentei rodar no celular e deu erro da FOTO 

    É um emulador de MS-DOS pra celular?

    Abraço!

  9. Eu dei uma olhada aqui e tudo parece bastante interessante. Não tenho o dispositivo com o qual este programa conversa, mas num emulador aqui ele pelo menos subiu:

    image_2023-08-04_000159778.png

    Aí chega a aparecer esta tela?

    Eu tô achando que o problema é o seguinte: a memória RAM está se esgotando e o programa não consegue nem memória para alocar uma string de erro "Out of memory" nessa função:

    void sub_42AEC0()
    {
      char var_4[4]; // [esp+20h] [ebp-4h] BYREF
    
      __InitExceptBlock();
      string::string((string *)var_4, aOutOfMemory);
      xalloc::xalloc((xalloc *)&__xalloc, (const string *)var_4, 0);
      string::~string((TStringRef **)var_4, 2);
    }

    No caso acima, var_4 é null se o operador new falhar. Veja v5 abaixo:

    string *__cdecl string::string(string *this, char *s)
    {
      size_t v2; // eax
      TStringRef *v3; // eax
      TStringRef *v5; // [esp+28h] [ebp-4h]
    
      __InitExceptBlock();
      v5 = (TStringRef *)operator new(0x12u);
      if ( v5 )
      {
        if ( s )
          v2 = strlen(s);
        else
          v2 = 0;
        TStringRef::TStringRef(v5, s, v2, 0, 0, 0);
        --*(_DWORD *)_DestructorCountPtr;
        v3 = v5;
      }
      else
      {
        v3 = 0;
      }
      *(_DWORD *)this = v3;
      ++*(_DWORD *)_DestructorCountPtr;
      return this;
    }

    Com var_4 sendo NULL, o fluxo entra em xalloc(NULL, 0) e dentro dela tem mais duas chamadas, onde uma chega no mov eax, [eax] problemático em 0x0042C253.

    Combinando então o seguinte:

    1. Você não alterou nada no sistema.
    2. O sistema rodou no meu emulador.
    3. Minha suspeita de ser um erro de alocação de memória.

    Meu palpite é que um pente de memória deste computador tenha queimado ou esteja com algum mau contato e ele está com metade da memória que ele deveria ter. Não sei. Você pode tentar ver quanto de memória tem livre com o comando mem /c e dizer aqui pra gente (postar uma foto da saída). Ou tentar desligar, limpar os pentes de memória e ligar novamente o PC.

    Só ideias por enquanto...

  10. Opa, deixa eu te pedir mais umas coisas:

    1. Uma foto do conteúdo do AUTOEXEC.BAT que mostre tudo (tá cortando um pedaço na que você mandou).
    2. Uma foto do conteúdo do INIT.BAT. É só comandar type c:\progs\sr632\v3.10\obj\init.bat
    3. Uma foto da saída do comando dir c:\
    4. Uma cópia da pasta inteira (eu sei que você tá buscando os disquetes já, mas só pra não esquecer).

    Abraço!

  11. Em 02/08/2023 em 10:37, jhow disse:

    Vou ver se consigo um disquete pra copiar a pasta , pq a cpu e muito antigo so tem entrada pra disquete,nao possui usb , e so tem o sistema Ms-Dos , a maquina e uma rebobinadeira.

    Boa!

    Em 02/08/2023 em 10:37, jhow disse:

    O que sera que pode ter causado esse erro?

    Ainda não sei. Enquanto você não acha os disquetes, consegue tirar uma foto do conteúdo do AUTOEXEC.BAT e CONFIG.SYS? Os comandos são:

    cd \
    type autoexec.bat
    type config.sys

    Seria legal também ter a versão do DOS e uma listagem desse diretório OBJ aí:

    ver
    dir c:\progs\sr632\v3.10\obj

    Valeu!

  12. Olá!

    O programa que você executou tentou acessar um endereço de memória inválido e por isso o SO matou o processo. No caso, ele dá um dump dos opcodes das instruções me 0x42C24B e diz que o errou ocorreu na instrução em 0x42C253. Então dá pra inferir o seguinte:

    # rasm2 -ax86 -d e84cabffff8b450c8b008903
    call 0xffffab51
    mov eax, dword [ebp + 0xc]
    mov eax, dword [eax]
    mov dword [ebx], eax

    Colocando os endereços, ficaria:

    42C24B    call 0xffffab51
    42C250    mov eax, dword [ebp + 0xc]
    42C253    mov eax, dword [eax]
    42C255    mov dword [ebx], eax

    Então o erro seria na instrução mov eax, dword [eax]. Como no momento que essa instrução roda EAX é 0 (tem um dump dos valores dos registradores na imagem), o programa tenta acessar o endereço de memória 0, o que bate com o erro final (The instruction referenced illegal address 00000000).

    A instrução anterior copia um valor para EAX a partir de EBP + C, que parece ser o segundo argumento da função dona dessa instrução. Não dá pra saber se é a main() do programa, mas você pode tentar passar um argumento pra ver se o erro muda:

    C:\PROGS\SR632\V3.10\OBJ>NEW.EXE 1 2

    Se precisar de mais ajuda, acho que vai ter que copiar a pasta PROGS, compactá-la e enviar aqui pra gente. Assim alguém pode dar uma olhada num disassembler e tentar te ajudar com o erro.

    Abraço!

  13. Oi Ana, bem vinda à Mente Binária. 🙂

    O nasm.us parece estar fora mesmo. No entanto, vejo algumas opções:

    • Se você usa Linux, pode instalar pelo gerenciador de pacotes. Ex.: apt install nasm.
    • Se você usa Windows, pode baixar do Fossies.
    • Se usa macOS, acho pode instalar com o brew.sh: brew install nasm.
    • Você pode estudar Assembly com o fasm alternativamente.

    Espero que ajude. Bons estudos aí!

×
×
  • Criar Novo...