Ir para conteúdo
  • Cadastre-se
  • Estude binários de Windows com o novo pev

       (0 análises)

    Fernando Mercês

    Desde 2013 que estamos trabalhando duro numa nova versão do pev, nosso toolkit para análise de binários PE (Portable Executable), o formato utilizado pelos executáveis (EXE, DLL, OCX, etc) do Windows.

    O pev é um projeto em que me sinto muito feliz de fazer parte e o principal motivo é que existe algo de muito forte e especial nele: colaboração.  Quase 30 pessoas contribuíram com o projeto de alguma forma (código, testes, empacotamento, etc) e hoje ele está presente nos repositórios das principais distribuições Linux, inclusive as focadas em segurança de alguma forma.

    Outro ponto importante é que ele começou como um projeto de faculdade lá em 2010, junto com outros alunos. Como a faculdade nem laboratório de pesquisa tinha, fizemos o nosso próprio grupo, batizado de Coding 40°, em homenagem ao calor da nossa cidade.

    O projeto atraiu muitos colaboradores, incluindo um que já commitou mais que eu no repositório e redefiniu, de forma muito profissional, toda a infraestrutura por trás do pev e da libpe. Foi o Jardel Weyrich. Sério, dá pra detectar que um projeto teve sucesso quando aparece alguém que já contribuiu com mais código para ele do que você!:)

    Por último, mas não menos importante: o pev é livre. E na boa, até agradeço as centenas de programadores que fizeram analisadores de PE proprietários, porque me motivaram a iniciar o pev. Era preciso um analisador de binários PE de código aberto, que permitisse estudantes e curiosos entender como um PE é parseado, que campos são importantes, por que a análise estática é tão poderosa, etc. Hoje, mesmo com todos os bugs que ainda hão de surgir (fora os que já surgiram e ainda não conseguimos corrigir!).

    Quero agradecer, de forma permanente, a todos que se envolvem ou se envolveram de alguma forma com o pev: usando, avisando-nos sobre bugs, contribuindo com código, ideias, testes, tudo importa! Obrigado, de coração.

    Emoções à parte, vamos partir para a análise de binários e falar das novidades do pev 0.80, lançado hoje!

    Acontece que um binário PE pode esconder muitas informações importantes antes mesmo de ser executado. Por exemplo, com a ferramenta readpe, do pev, você vai descobrir que um executável PE é dividido em cabeçalhos e seções e eles armazenam várias informações interessantes, por exemplo:

    $ readpe arquivo.exe
    DOS Header
        Magic number:                    0x5a4d (MZ)
        Bytes in last page:              144
        Pages in file:                   3
        Relocations:                     0
        Size of header in paragraphs:    4
        Minimum extra paragraphs:        0
        Maximum extra paragraphs:        65535
        Initial (relative) SS value:     0
        Initial SP value:                0xb8
        Initial IP value:                0
        Initial (relative) CS value:     0
        Address of relocation table:     0x40
        Overlay number:                  0
        OEM identifier:                  0
        OEM information:                 0
        PE header offset:                0x80
    COFF/File header
        Machine:                         0x14c IMAGE_FILE_MACHINE_I386
        Number of sections:              3
        Date/time stamp:                 1425562907 (Thu, 05 Mar 2015 13:41:47 UTC)
        Symbol Table offset:             0
        Number of symbols:               0
        Size of optional header:         0xe0
        Characteristics:                 0x102
        Characteristics names
                                             IMAGE_FILE_EXECUTABLE_IMAGE
                                             IMAGE_FILE_32BIT_MACHINE
    Optional/Image header
        Magic number:                    0x10b (PE32)
        Linker major version:            11
        Linker minor version:            0
        Size of .text section:           0x2a800
        Size of .data section:           0x3400
        Size of .bss section:            0
        Entrypoint:                      0x2c78e
        Address of .text section:        0x2000
        Address of .data section:        0x2e000
        ImageBase:                       0x400000
        Alignment of sections:           0x2000
        Alignment factor:                0x200
        Major version of required OS:    4
        Minor version of required OS:    0
        Major version of image:          0
        Minor version of image:          0
        Major version of subsystem:      4
        Minor version of subsystem:      0
        Size of image:                   0x34000
        Size of headers:                 0x200
        Checksum:                        0
        Subsystem required:              0x2 (IMAGE_SUBSYSTEM_WINDOWS_GUI)
        DLL characteristics:             0x8540
        DLL characteristics names
                                             IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
                                             IMAGE_DLLCHARACTERISTICS_NX_COMPAT
                                             IMAGE_DLLCHARACTERISTICS_NO_SEH
                                             IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
        Size of stack to reserve:        0x100000
        Size of stack to commit:         0x1000
        Size of heap space to reserve:   0x100000
        Size of heap space to commit:    0x1000
    Data directories
        Directory
            IMAGE_DIRECTORY_ENTRY_IMPORT:    0x2c738 (83 bytes)
        Directory
            IMAGE_DIRECTORY_ENTRY_RESOURCE:  0x2e000 (12728 bytes)
        Directory
            IMAGE_DIRECTORY_ENTRY_BASERELOC: 0x32000 (12 bytes)
        Directory
            IMAGE_DIRECTORY_ENTRY_IAT:       0x2000 (8 bytes)
        Directory
            IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:    0x2008 (72 bytes)
    Imported functions
        Library
            Name:                            mscoree.dll
            Functions
                Function
                    Name:                            _CorExeMain
    export directory not found
    Sections
        Section
            Name:                            .text
            Virtual Address:                 0x2000
            Physical Address:                0x2a794
            Size:                            0x2a800 (174080 bytes)
            Pointer To Data:                 0x200
            Relocations:                     0
            Characteristics:                 0x60000020
            Characteristic Names
                                                 IMAGE_SCN_CNT_CODE
                                                 IMAGE_SCN_MEM_EXECUTE
                                                 IMAGE_SCN_MEM_READ
        Section
            Name:                            .rsrc
            Virtual Address:                 0x2e000
            Physical Address:                0x31b8
            Size:                            0x3200 (12800 bytes)
            Pointer To Data:                 0x2aa00
            Relocations:                     0
            Characteristics:                 0x40000040
            Characteristic Names
                                                 IMAGE_SCN_CNT_INITIALIZED_DATA
                                                 IMAGE_SCN_MEM_READ
        Section
            Name:                            .reloc
            Virtual Address:                 0x32000
            Physical Address:                0xc
            Size:                            0x200 (512 bytes)
            Pointer To Data:                 0x2dc00
            Relocations:                     0
            Characteristics:                 0x42000040
            Characteristic Names
                                                 IMAGE_SCN_CNT_INITIALIZED_DATA
                                                 IMAGE_SCN_MEM_DISCARDABLE
                                                 IMAGE_SCN_MEM_READ

    Só olhando para este cabeçalho, já dá pra dizer muita coisa sobre esse binário. Por exemplo, é possível inferir que ele foi compilado em 5 de março de 2015, é um executável de janelas (GUI – Graphical User Interface) e na Import Table dele tem apenas uma entrada, uma função chamada _CorExeMain importada da biblioteca mscoree.dll. Isso já dá a dica que esse é binário foi compilado em .NET. Como eu sei disso? É que eu já vi vários binários em .NET e todos eles importam somente essa função. Não se preocupe, com o tempo você também pega os macetes!;)

    Claro que, para estudar os binários de forma eficiente é legal ler também outros tutoriais sobre o assunto. O que mais gosto em Português é O formato PE, da Vovó Vicky, isso mesmo, uma simpática senhora, médica, do Sul do país que adora arquivos PE. ❤️

    Voltando ao nosso binário, vamos dar uma olhada nas strings presentes nele com o pestr:

    $ pestr -so arquivo.exe
    0x2d81e .rsrc FileDescription
    0x2d840 .rsrc Gynx
    0x2d852 .rsrc FileVersion
    0x2d86c .rsrc 1.0.0.0
    0x2d882 .rsrc InternalName
    0x2d89c .rsrc Gynx.exe
    0x2d8b6 .rsrc LegalCopyright
    0x2d8d4 .rsrc Copyright
    0x2d8ea .rsrc   2015
    0x2d8fe .rsrc OriginalFilename

    A lista de strings completa é bem maior, mas eu cortei só para mostrar algumas.

    Primeira pergunta que pode surgir aqui é: por que fizemos um programa pestr se já existe o programa strings? Bem, você pode notar pela saída que dizemos muito mais que a string (texto) em si. Sabemos em que seção ela está e o offset (posição) no arquivo. Além disso, o pestr imprime strings ASCII e Unicode.

    No meio das strings tem outra informação de data, que reforça o ano da data de compilação. Tem também o nome original do arquivo (quando o programador compilou). Se você pesquisar no Google pelo nome do arquivo, já vai encontrar muita coisa!

    Continuando nossa análise, vamos ver com o pescan se tem algo estranho neste arquivo:

    $ pescan -v ~/dotnet
    file entropy:                    5.252392 (normal)
    fpu anti-disassembly:            no
    imagebase:                       normal - 0x400000
    entrypoint:                      normal - va: 0x2c78e - raw: 0x2a98e
    DOS stub:                        normal
    TLS directory:                   not found
    timestamp:                       normal - Thu, 05 Mar 2015 13:41:47 UTC
    section count:                   3
    sections
        section
            .text:                           normal
        section
            .rsrc:                           normal
        section
            .reloc:                          small length

    A baixa entropia sugere que o binário não está comprimido (packed) e tudo parece estar normal. Isso significa que o binário não está protegido, não que seu código não seja malicioso.;)

    Agora, já entrando nos novos recursos, que tal saber os hashes deste arquivo? Buscando por eles no Google também é possível encontrar algumas informações. Ao invés de calcular um por um, utilizando vários programas, o pev conta com o pehash, que faz tudo pra você:

    $ pehash -a arquivo.exe
    file
        filepath:                        /home/user/arquivo.exe
        md5:                             1f4c40ff46297bdc5a595cd574e0db64
        sha1:                            2bc6fa6558988d628dd4b95d0741405685c1c232
        sha256:                          b823a04f49463e410c9f823baade182eb283ba073b40c6d8cc443a570a9a1df6
        ssdeep:                          3072:yLYmWbfXGKJy7DFR9KwHS+MASjB5jL0S9Q0VwuUcu:AYmWbfX3y7DFR9KwHS+MAS/js0VhU
        imphash:                         f34d5f2d4577ed6d9ceec516c1f5a744
    headers
        header
            header_name:                     IMAGE_DOS_HEADER
            md5:                             919f1c12cf0d1cd93d7f1077f13ac374
            sha1:                            3d43712e5606b4640b85f5f0e25e9db8ed552074
            sha256:                          c46a3fc444808f3b86a7e757e5202d16f8ea9bf1c6aff2cabc593e7d0f2c9ad2
            ssdeep:                          3:WlWUqt/vllnln:idqP
        header
            header_name:                     IMAGE_COFF_HEADER
            md5:                             15174f39bbe557d104f169053af5c7a2
            sha1:                            21f9311fa5e1a7c8724c657db39ef2fbb1b896ce
            sha256:                          7430166bd1b2d5c400f2f5fb60c90393b50388b97e877aa7cf0c3057a413a85f
            ssdeep:                          3:HHJl/fkn:HHJlkn
        header
            header_name:                     IMAGE_OPTIONAL_HEADER
            md5:                             3b079fa2a88b6901db907bc47dee2d67
            sha1:                            21c1c517743170c94d1ade608ff7d2746fd7e3ea
            sha256:                          0fec7657e9361e8262af5872bf3784a7647b6978f3d0e35a419d2f410c8654a0
            ssdeep:                          3:6FZ//llAlFlllXNB//llrllel/dglPt1l9tllH:pfGwlN
    sections
        section
            section_name:                    .text
            md5:                             973d11759194c14071aa6963de8f55c7
            sha1:                            1934e0085c8776e3243bf658e95b8943d4f91bc9
            sha256:                          e68349bfcb04b20c11973ce27770570ebb22c8c7750133d073f15f7ec9eeda38
            ssdeep:                          3072:XLYmWbfXGKJy7DFR9KwHS+MASjB5jL0S9Q0VwuUc:bYmWbfX3y7DFR9KwHS+MAS/js0VhU
        section
            section_name:                    .rsrc
            md5:                             9d498bee08b1cf075d8aca022f1e16e9
            sha1:                            f938a8c23185b023bb5dd12082013c2a628bc0d3
            sha256:                          eb7454309df90fea2d01c887b0040e8237353919efc06a7081a7abb15091283a
            ssdeep:                          24:3A5t/ug9GXBEiViKZWIDDOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO:weg90VWIDZ6Kp+l4BhDqFWSfbNtm
        section
            section_name:                    .reloc
            md5:                             37ab911460a0b274ffa9f4e388ec933b
            sha1:                            7c9eac3b843c9a7ab8ef08aac5c14e4c51b2c703
            sha256:                          fb50df3b064d126999295b35f1a151f8fbe7e3593e306a9255a534999843f5b2
            ssdeep:                          3:LlQl:S

    Achou que teria os hashes do arquivo somente? Pois é, o pev surpreende mesmo! O pehash calcula MD5, SHA1, SHA-256 e ssdeep (uma técnica de fuzzy hash que vale a pena pesquisar sobre!) para cada cabeçalho e seção. Além disso, a partir das funções importadas do binário o pehash calcula o imphash, que já expliquei no artigo Entendendo o imphash.

    Tanto o imphash quanto o ssdeep podem ser utilizados, de maneiras diferentes, para saber se um arquivo é parecido com outro, se são variantes do mesmo código-fonte, mas neste caso o imphash não ajuda por ser um binário .NET (todos eles importam aquela mesma função única que comentei acima).

    Também é possível, com o peres (criação do Marcelo Fleury),  extrair os recursos e checar, por exemplo, o manifesto em XML dos arquivo:

    $ peres -x arquivo.exe
    Save On:                         resources/icons/2.ico
    Save On:                         resources/icons/3.ico
    Save On:                         resources/icons/4.ico
    Save On:                         resources/icons/5.ico
    Save On:                         resources/icons/6.ico
    Save On:                         resources/icons/7.ico
    Save On:                         resources/icons/8.ico
    Save On:                         resources/groupicons/32512.ico
    Save On:                         resources/versions/1.rc
    Save On:                         resources/manifests/1.xml
    
    $ cat resources/manifests/1.xml
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
          <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
            <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
          </requestedPrivileges>
        </security>
      </trustInfo>
    </assembly>

    O ícone utilizado também é extraído (groupicons) mas ele é quebrado em várias imagens (icons) e precisam ser reconstruídos se você precisar do ícone original do arquivo. De qualquer forma, você pode calcular o hash deles e comparar com os dos ícones de outros arquivos, se for essa a intenção.;)

    Uma outra novidade é o programa cpload, para analisar arquivos .cpl (Control Panel Applets). Ele é presente somente na versão do pev para Windows, pois serve para analisar binários dinamicamente. Este formato é um pouco diferente do EXE convencional (na verdade um CPL é uma “DLL que executa com dois cliques”). Na época o formato desses arquivos era muito pouco conhecido e até escrevi um artigo para a Wikipédia em Português sobre. Com o cpload, é possível enviar para a função presente no arquivo .cpl todas as mensagens que ela deve reconhecer. Assim o analista pode ver qual delas dispara o código. No exemplo abaixo, a mensagem CPL_DBLCLK (clique duplo) foi enviada para um .cpl presente no Windows chamado joy.cpl. Veja que o programa executa e mostra uma janela:

    cpload-dblclk.png.dfb36d4c9774706bb34bb51e508fa6fa.png

    Adicionalmente, se você fizer isso no contexto de um debugger, passando os argumentos como na imagem abaixo:

    cpload-olly-arguments.png.bca94ef0b9f9f98024681d5596aeaa2f.png

    O cpload força um software breakpoint antes do carregamento do arquivo .cpl pela função LoadLibrary() e antes da entrada na CPLApplet(), que é a função principal de um arquivo .cpl, o que permite ao analista enxergar o trecho exato de código dele, sem precisar debugar processos do sistema como o rundll32.exe.

    cpload-olly-bp.png.7b9a1b51fa499534a2a27d1416bfde17.png

    E ainda sobre o pev, os plugins de formato de saída estão dando um show (ideia do Jan Seidl e portada para plugins pelo Jardel). Olha só como fica a saída se você pedir ao pedis, nosso disassembler, para disassemblar o entrypoint  de um binário PE em JSON:

    $ pedis --format json --entrypoint PUTTY.EXE
    {
        "54eb0": "6a 60                           push 0x60",
        "54eb2": "68 70 7b 47 00                  push 0x477b70",
        "54eb7": "e8 08 21 00 00                  call 0x456fc4",
        "54ebc": "bf 94 00 00 00                  mov edi, 0x94",
        "54ec1": "8b c7                           mov eax, edi",
        "54ec3": "e8 b8 fa ff ff                  call 0x454980",
        "54ec8": "89 65 e8                        mov [ebp-0x18], esp",
        "54ecb": "8b f4                           mov esi, esp",
        "54ecd": "89 3e                           mov [esi], edi",
        "54ecf": "56                              push esi",
        "54ed0": "ff 15 e0 d2 45 00               call dword [0x45d2e0]",
        "54ed6": "8b 4e 10                        mov ecx, [esi+0x10]",
        "54ed9": "89 0d 48 e1 47 00               mov [0x47e148], ecx",
        "54edf": "8b 46 04                        mov eax, [esi+0x4]",
        "54ee2": "a3 54 e1 47 00                  mov [0x47e154], eax",
        "54ee7": "8b 56 08                        mov edx, [esi+0x8]",
        "54eea": "89 15 58 e1 47 00               mov [0x47e158], edx",
        "54ef0": "8b 76 0c                        mov esi, [esi+0xc]",
        "54ef3": "81 e6 ff 7f 00 00               and esi, 0x7fff",
        "54ef9": "89 35 4c e1 47 00               mov [0x47e14c], esi",
        "54eff": "83 f9 02                        cmp ecx, 0x2",
        "54f02": "74 0c                           jz 0x454f10",
        "54f04": "81 ce 00 80 00 00               or esi, 0x8000",
        "54f0a": "89 35 4c e1 47 00               mov [0x47e14c], esi",
        "54f10": "c1 e0 08                        shl eax, 0x8",
        "54f13": "03 c2                           add eax, edx",
        "54f15": "a3 50 e1 47 00                  mov [0x47e150], eax",
        "54f1a": "33 f6                           xor esi, esi",
        "54f1c": "56                              push esi",
        "54f1d": "8b 3d d8 d2 45 00               mov edi, [0x45d2d8]",
        "54f23": "ff d7                           call edi0x454f25",
        "54f25": "66 81 38 4d 5a                  cmp word [eax], 0x5a4d",
        "54f2a": "75 1f                           jnz 0x454f4b",
        "54f2c": "8b 48 3c                        mov ecx, [eax+0x3c]",
        "54f2f": "03 c8                           add ecx, eax",
        "54f31": "81 39 50 45 00 00               cmp dword [ecx], 0x4550",
        "54f37": "75 12                           jnz 0x454f4b",
        "54f39": "0f b7 41 18                     movzx eax, word [ecx+0x18]",
        "54f3d": "3d 0b 01 00 00                  cmp eax, 0x10b",
        "54f42": "74 1f                           jz 0x454f63",
        "54f44": "3d 0b 02 00 00                  cmp eax, 0x20b",
        "54f49": "74 05                           jz 0x454f50",
        "54f4b": "89 75 e4                        mov [ebp-0x1c], esi",
        "54f4e": "eb 27                           jmp 0x454f77",
        "54f50": "83 b9 84 00 00 00 0e            cmp dword [ecx+0x84], 0xe",
        "54f57": "76 f2                           jbe 0x45504b",
        "54f59": "33 c0                           xor eax, eax",
        "54f5b": "39 b1 f8 00 00 00               cmp [ecx+0xf8], esi",
        "54f61": "eb 0e                           jmp 0x454f71",
        "54f63": "83 79 74 0e                     cmp dword [ecx+0x74], 0xe",
        "54f67": "76 e2                           jbe 0x45504b",
        "54f69": "33 c0                           xor eax, eax",
        "54f6b": "39 b1 e8 00 00 00               cmp [ecx+0xe8], esi",
        "54f71": "0f 95 c0                        setnz al",
        "54f74": "89 45 e4                        mov [ebp-0x1c], eax",
        "54f77": "56                              push esi",
        "54f78": "e8 b4 28 00 00                  call 0x457831",
        "54f7d": "59                              pop ecx",
        "54f7e": "85 c0                           test eax, eax",
        "54f80": "75 21                           jnz 0x454fa3",
        "54f82": "83 3d 94 e1 47 00 01            cmp dword [0x47e194], 0x1",
        "54f89": "75 05                           jnz 0x454f90",
        "54f8b": "e8 56 44 00 00                  call 0x4593e6",
        "54f90": "6a 1c                           push 0x1c",
        "54f92": "e8 d8 42 00 00                  call 0x45926f",
        "54f97": "68 ff 00 00 00                  push 0xff",
        "54f9c": "e8 be fb ff ff                  call 0x454b5f",
        "54fa1": "59                              pop ecx",
        "54fa2": "59                              pop ecx",
        "54fa3": "e8 65 47 00 00                  call 0x45970d",
        "54fa8": "89 75 fc                        mov [ebp-0x4], esi",
        "54fab": "e8 e9 25 00 00                  call 0x457599",
        "54fb0": "85 c0                           test eax, eax",
        "54fb2": "7d 08                           jge 0x454fbc",
        "54fb4": "6a 1b                           push 0x1b",
        "54fb6": "e8 d0 fe ff ff                  call 0x454e8b",
        "54fbb": "59                              pop ecx",
        "54fbc": "ff 15 a8 d1 45 00               call dword [0x45d1a8]",
        "54fc2": "a3 00 e9 47 00                  mov [0x47e900], eax",
        "54fc7": "e8 af 4d 00 00                  call 0x459d7b",
        "54fcc": "a3 8c e1 47 00                  mov [0x47e18c], eax",
        "54fd1": "e8 03 4d 00 00                  call 0x459cd9",
        "54fd6": "85 c0                           test eax, eax",
        "54fd8": "7d 08                           jge 0x454fe2",
        "54fda": "6a 08                           push 0x8",
        "54fdc": "e8 aa fe ff ff                  call 0x454e8b",
        "54fe1": "59                              pop ecx",
        "54fe2": "e8 bf 4a 00 00                  call 0x459aa6",
        "54fe7": "85 c0                           test eax, eax",
        "54fe9": "7d 08                           jge 0x454ff3",
        "54feb": "6a 09                           push 0x9",
        "54fed": "e8 99 fe ff ff                  call 0x454e8b",
        "54ff2": "59                              pop ecx",
        "54ff3": "6a 01                           push 0x1",
        "54ff5": "e8 95 fb ff ff                  call 0x454b8f",
        "54ffa": "59                              pop ecx",
        "54ffb": "89 45 d8                        mov [ebp-0x28], eax",
        "54ffe": "3b c6                           cmp eax, esi",
        "55000": "74 07                           jz 0x455009",
        "55002": "50                              push eax",
        "55003": "e8 83 fe ff ff                  call 0x454e8b",
        "55008": "59                              pop ecx",
        "55009": "89 75 bc                        mov [ebp-0x44], esi",
        "5500c": "8d 45 90                        lea eax, [ebp-0x70]",
        "5500f": "50                              push eax",
        "55010": "ff 15 ac d1 45 00               call dword [0x45d1ac]",
        "55016": "e8 2e 4a 00 00                  call 0x459a49",
        "5501b": "89 45 e0                        mov [ebp-0x20], eax",
        "5501e": "f6 45 bc 01                     test byte [ebp-0x44], 0x1",
        "55022": "74 06                           jz 0x45502a",
        "55024": "0f b7 45 c0                     movzx eax, word [ebp-0x40]",
        "55028": "eb 03                           jmp 0x45502d",
        "5502a": "6a 0a                           push 0xa",
        "5502c": "58                              pop eax",
        "5502d": "50                              push eax",
        "5502e": "ff 75 e0                        push dword [ebp-0x20]",
        "55031": "56                              push esi",
        "55032": "56                              push esi",
        "55033": "ff d7                           call edi0x455035",
        "55035": "50                              push eax",
        "55036": "e8 93 3b ff ff                  call 0x448bce",
        "5503b": "8b f8                           mov edi, eax",
        "5503d": "89 7d d4                        mov [ebp-0x2c], edi",
        "55040": "39 75 e4                        cmp [ebp-0x1c], esi",
        "55043": "75 06                           jnz 0x45504b",
        "55045": "57                              push edi",
        "55046": "e8 6f fc ff ff                  call 0x454cba",
        "5504b": "e8 8c fc ff ff                  call 0x454cdc",
        "55050": "eb 2b                           jmp 0x45507d",
        "55052": "8b 45 ec                        mov eax, [ebp-0x14]",
        "55055": "8b 08                           mov ecx, [eax]",
        "55057": "8b 09                           mov ecx, [ecx]",
        "55059": "89 4d dc                        mov [ebp-0x24], ecx",
        "5505c": "50                              push eax",
        "5505d": "51                              push ecx",
        "5505e": "e8 75 48 00 00                  call 0x4598d8",
        "55063": "59                              pop ecx",
        "55064": "59                              pop ecx",
        "55065": "c3                              ret"

    Os formatos de saída suportados por todos os programas do toolkit incluem JSON, XML, CSV e o padrão, texto. Assim o pev se faz útil para quem quer automatizar o processo de análise estática de binários PE, para salvar em um banco de dados para consulta posterior, por exemplo.

    A documentação para a versão 0.80 está pronta e recomendo fortemente que você a leia se quiser aproveitar o máximo do toolkit. O changelog completo também está disponível. Despeço-me com a certeza de que fizemos um bom trabalho e de que o software livre é viável, funciona e é, principalmente, algo prazeroso de se manter, que pode ajudar pessoas e empresas a atingirem seus objetivos, sem custo.:)

    Confere lá: https://github.com/merces/pev



    Feedback do Usuário

    Crie uma conta ou faça o login para deixar um comentário

    Você precisa ser membro para fazer uma análise

    Criar uma conta

    Crie uma nova conta em nossa comunidade. É fácil!

    Crie uma nova conta

    Entrar

    Já tem uma conta? Faça o login.

    Entrar Agora

    Não há análises para mostrar


  • Conteúdo Similar

    • Por Fabiano Furtado
      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.
    • Por Fernando Mercês
      Saudações, leitores do Mente Binária! Hoje me deu vontade de falar sobre uma tarefa que eventualmente preciso fazer na empresa onde trabalho, que é a de verificar as diferenças entre arquivos executáveis, normalmente de Windows, também conhecidos por executáveis PE.
      Há vários usos ao comparar binários. É possível avaliar o que mudou na versão atual de um software em relação à anterior, descobrir o que muda em cada sample diferente de uma mesma família de malware, etc. Esses dias mesmo me foi pedido que verificasse a diferença entre 6 arquivos maliciosos, que compartilho abaixo como fiz.
      Reconhecimento básico
      Os arquivos que recebi tinham seu hash SHA-256 como nome. A primeira coisa que fiz foi checar seu tipo (usando comandos do macOS, mas o Linux tem comandos similares):
      $ file * fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04: PE32 executable (GUI) Intel 80386, for MS Windows fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9: PE32 executable (GUI) Intel 80386, for MS Windows fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05: PE32 executable (GUI) Intel 80386, for MS Windows ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd: PE32 executable (GUI) Intel 80386, for MS Windows ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640: PE32 executable (GUI) Intel 80386, for MS Windows ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e: PE32 executable (GUI) Intel 80386, for MS Windows Só para garantir, também chequei o SHA-256 deles e realmente bateu com o nome, o que era esperado:
      $ shasum -a256 * fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9 fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9 fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05 fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05 ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640 ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640 ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e PS.: No Linux o comando seria sha256sum ao invés de shasum -a256.
      O próximo passo foi checar o tamanho deles:
      $ wc -c * 396973 fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 396973 fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9 396973 fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05 396973 ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd 396973 ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640 396973 ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e 2381838 total Aqui apresentou-se um caso atípico: os binários possuem exatamente o mesmo tamanho! Já pensei que havia grandes chances de as diferenças entre eles serem mínimas: provavelmente algo usado pelo autor do malware só para "mudar o hash" na tentativa de evitar que os antivírus detectem os arquivos idênticos, por exemplo. Essa tentativa é na verdade frustrada visto que, ao contrário do que muitos pensam, os antivírus não detectam malware por hash normalmente, já que isso seria muito custoso do ponto de vista do desempenho (seria preciso ler todos os bytes do arquivo!) e também seria muito fácil tornar um novo arquivo indetectável - bastaria alterar um único byte para um hash final completamente diferente.
      Comparação de estrutura
      Se estivéssemos tratando arquivos de texto, poderia simplesmente usar o comando diff, mas o assunto aqui é PE, então algo interessante de verificar é sua estrutura, que consiste basicamente em cabeçalhos, localizados antes das seções. Se você não sabe do que estou falando, recomendo os seguintes recursos:
      Posts do @Leandro Fróes sobre o formato PE e suas referências. Capítulo sobre PE do livro Fundamentos de Engenharia Reversa. Aulas 5 e 6 do CERO, nosso Curso de Engenharia Reversa Online em vídeo. Digitar "PE executable" no Google ler o que curtir. Depois dessa imersão no mundo dos executáveis PE, não tenho dúvidas de que você vai se apaixonar por eles também! 😍
      Voltando à comparação, o que eu quero dizer com estrutura? Bem, os valores dos campos dos cabeçalhos. Por exemplo, para ver o cabeçalho COFF de um arquivo PE, usei o readpe, parte do kit de ferramentas pev:
      $ readpe -h coff fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 COFF/File header Machine: 0x14c IMAGE_FILE_MACHINE_I386 Number of sections: 5 Date/time stamp: 1401620468 (Sun, 01 Jun 2014 11:01:08 UTC) Symbol Table offset: 0 Number of symbols: 0 Size of optional header: 0xe0 Characteristics: 0x102 Characteristics names IMAGE_FILE_EXECUTABLE_IMAGE IMAGE_FILE_32BIT_MACHINE Mas não, não usei o pev por saudosismo! A ideia de ter uma saída em texto da estrutura desses binários é depois usar o comando diff para compará-las. A primeira coisa que precisei então foi gerar um .txt contendo toda a estrutura, e não só o cabeçalho COFF, para cada um dos arquivos. Uma repetição em bash dá conta do recado:
      $ ls -1 readpe_output_* readpe_output_fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04.txt readpe_output_fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9.txt readpe_output_fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05.txt readpe_output_ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd.txt readpe_output_ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640.txt readpe_output_ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e.txt Eu usei o readpe sem nenhuma opção, assim ele imprime todos os cabeçalhos, incluindo os de seções. Só pra começar fiz um diff do primeiro para o segundo e não houve qualquer saída, ou seja, a estrutura dos arquivos eram idênticas! E eram mesmo:
      $ wc -c readpe_output_* 21627 readpe_output_fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04.txt 21627 readpe_output_fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9.txt 21627 readpe_output_fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05.txt 21627 readpe_output_ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd.txt 21627 readpe_output_ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640.txt 21627 readpe_output_ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e.txt 129762 total $ md5 !$ md5 readpe_output_* MD5 (readpe_output_fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e.txt) = 05b36b89b1165b3d619bee16f8a1d7f7
      Os hashes MD5 da saída em texto da estrutura de todos os arquivos batem. Eles são mesmo iguais estruturalmente!
      Passado o choque, percebi que teria que comparar o conteúdo das seções (código, dados, talvez resources, etc). Aí fui obrigado a inicializar minha VM do Janelas mesmo...
      Comparação do conteúdo das seções
      Existem alguns softwares que trabalham com PE e possuem funções de comparação de dois executáveis. Eu costumava usar o Cold Fusion (um antigo gerador de patch) pra isso, mas ele tem alguns bugs que me impediram. Achei a mesma função no Stud_PE, mas ele localiza arquivos por extensão na janela de comparação, então renomeei o primeiro e o segundo arquivo que tinha para a.exe e b.exe respectivamente.
      Ao abrir o a.exe no Stud_PE, usei o botão "File Compare", selecionei o método "Binary", setei o "Starting from" pra "Raw" e cliquei em "Compare":

      Se você não entendeu por que fiz isso, volte uma casa ou leia os tutorias de PE que indiquei. Ou pergunte que eu falo. 😍
      Bem, entre esses dois caras então havia 9 bytes que o diferenciavam e eu já tinha os offsets a partir do início do arquivo. Agora é descobrir em que seção eles estavam no PE, o que são, o que comem e como eles vivem. 😎
      Descobrindo como as diferenças são usadas
      Abri o executável no x64dbg (na verdade no x32dbg, já que este binário é de 32-bits) mas percebi que o entrypoint estava no endereço 013706AA. Como o ImageBase deste binário é 00400000, percebi que o ASLR estava habilitado e, antes de continuar , desabilitei-o com o DIE, como mostro neste vídeo rápido no canal Papo Binário:
      Antes de reabrir o binário no x32dbg, convém lembrar que eu tinha um offset e precisava convertê-lo para endereço virtual (VA). Isso é feito com o que alguns analisadores de PE chamam de FLC (File Location Calculator). O DIE tem, o Stud_PE tem e o pev também tem, com a ferramenta ofs2rva:
      $ ofs2rva 0x4c451 a.exe 0x4dc51 Mas pra não você não me acusar de saudosismo de novo, vou mostrar no Stud_PE 😄

      Percebe que o Stud_PE já diz que este byte pertence à seção .rdata, o que à esta altura você já sabe, caso tenha feito o trabalho de casa de estudo do PE, que é provavelmente uma seção de dados somente-leitura, então há grandes chances de nossa sequência diferentona pertencer à uma string constante, por exemplo. Fui ver no debugger como é que tava a festa. Abri o a.exe lá e dei um Ctrl+G no Dump pra ir pro endereço 44DC51:

      De fato tinha uma string lá: zuk0KRrGrP, mas ela na verdade começava em 44DC44 e pra saber quando ela era usada no malware, coloquei um breakpoint de hardware no acesso ao byte, que é o primeiro da string e cheguei à conclusão de que, como o nome sugere, é realmente uma string de identificação da campanha do malware, sempre no mesmo offset (calculei de novo usando FLC).  Agora foi só ver a dos outros e novamente recorri à uma ferramenta do pev (💚), a pestr:
      $ for i in *; do echo $i; pestr -so $i | grep 0x4c444; echo; done fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 0x4c444 .rdata identifierStrzuk0KRrGrP fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9 0x4c444 .rdata identifierStrAR0U4hr1wW fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05 0x4c444 .rdata identifierStrswEYVkFWeg ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd 0x4c444 .rdata identifierStrKXaUzlBDIj ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640 0x4c444 .rdata identifierStrv91TJ5c3Lr ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e 0x4c444 .rdata identifierStrOzJnvFQy2U Bom, daí o céu é o limite. Dá pra criar assinatura, criar um script pra extrair esse ID da campanha, enfim, missão cumprida.

      FAQ
      1. Por que você não utilizou só um comparador de arquivos qualquer, que compara os bytes em hexadecimal?
      Eu queria saber exatamente onde estavam as diferenças entre os arquivos, se na estrutura ou não. Em caso negativo, é código? Se sim, que código? Que faz o que? São dados? Usados onde? Em qual seção? Um editor hexadecimal ignorantão não me daria isso. Além disso, se os arquivos fossem diferente estruturalmente, ou em tamanho, eu queria saber antes, pra não perder tempo analisando diferenças de bytes hexa que eu não sei o que é.
      2. Existem softwares para comparar binários PE muito mais poderosos, como o BinDiff. Por que caralhas você não o usou?
      O BinDiff é pra comparar código. Minha diferença estava nos dados. Além disso, o BinDiff e seus amigos traduzem o Assembly original do binário para uma linguagem intermediária própria e comparam lógica, não instruções. É bem fodão, mas não me atendia neste caso, afinal eu já sabia que os binários eram idênticos em funcionalidade. Só queria saber onde estava a diferença exata.
      3. Percebi pela screenshot do Stud_PE que ele também compara a estrutura dos arquivos PE, então todo aquele processo com o readpe foi à toa?
      Sim, foi só pra Inglês ver. Não, brincadeira! O Stud_PE compara os cabeçalhos COFF, Optional e os diretórios de dados somente. O readpe imprime todos os cabeçalhos, incluindo todas as seções mais os imports. É outro nível, moleque! 😏

      4. E quanto à executáveis ELF?
      O título não fala somente de PE propositalmente, já que a mesma técnica pode ser usada para arquivos ELF, só mudando os programas (readelf, etc).
      Por hora é só. Se você deixar sua análise abaixo ou quiser fazer um comentário/pergunta, ficarei muito grato. Considera apoiar a gente também vai. 💚
    • Por Fernando Mercês
      Muitos jogos antigos apresentam problemas ao serem executados ou simplesmente instalados no Windows Vista. Isto acontece por conseqüência de diversos fatores, mas o principal é que quando o jogo (ou software) foi desenvolvido, o Windows Vista ainda não estava no mercado, o que impediu testes de serem realizados, entre outros aspectos.
      Este artigo mostra um exemplo de como utilizar a ER para estudar o executável do game e saber o que o impede de rodar no Vista.
      Você verá como uma simples alteração em 2 bytes de um arquivo PE pode salvar seu fim de semana.
      Ao tentar instalar o jogo Mortal Kombat 4 (PC) no Windows Vista Home Basic, obtivemos um erro fatal que dizia: “Start Menu Error”. A única opção era clicar no botão OK, que encerraria a execução do programa de instalação.
      Numa tentativa de contornar tal situção, copiamos o conteúdo do CD-ROM para um diretório no disco rígido e tentamos executar o game pelo seu executável direto, o MK4.EXE. Isso resultou no seguinte erro:

      É notável que o executável checa se a instalação do jogo foi feita e, como não foi feita, recebemos a mensagem acima. Ao clicar em OK, o processo é encerrado.
      Mas o que será que o jogo checa para saber se está instalado ou não? Para responder a essa pergunta precisaremos de um debugger de executáveis. Um aplicativo que mostra, em assembly, as rotinas executadas por arquivo PE. Usaremos o OllyDbg para tal função.
      Ao abrir o executável MK4.EXE no OllyDbg, vamos procurar pela string de texto contida na mensagem de erro da primeira imagem. Para isto, clique com o botão direito do mouse no primeiro quadrante e escolha “Search for > All referenced text strings”, como sugere a imagem abaixo:

      A próxima tela mostra uma lista contendo todas as strings de texto encontradas e entendidas no arquivo MK4.EXE. Nela, clicando novamente com o botão direito do mouse e escolhendo “Search text”, abrirá uma janela como a mostrada abaixo e então digitamos o texto “CD” (sem aspas) e marcamos a opção para diferenciar o caso, para filtrar a pesquisa.

      Isso foi feito para encontrarmos a string de texto que nos foi exibida no erro incial, lembra-se? O texto era “Mortal Kombat 4 is not installed. Run Setup from the CD”. Por isso buscamos a palavra “CD”, para achar essa string dentro do executável do jogo, o que nos leva para próximo da rotina onde esta mensagem é chamada.
      Vamos ver o resultado na imagem abaixo:

      O Olly nos mostra que no endereço 004AD2B1, o comando é PUSH 004F474C, que vai empurrar para a memória (stack) o nosso texto. Para localizarmos exatamente onde está este comando no programa, basta darmos um ENTER nesta linha e a tela abaixo é exibida.
       
      Entramos no bloco onde o texto do erro é exibido na tela. Vamos subir um pouco para ver o que vem antes.
      Na linha 004AD299 temos um CALL (como um GOTO) e, depois que a CALL temina e o programa volta para sua execução normal, temos um TEST EAX, EAX, que é um comando que verifica se o conteúdo de EAX é zero. Então podemos prever que a CALL altera o valor de EAX.
      Mais abaixo, temos um JNZ 004AD2D4. Esse JNZ significa Jump if Not Zero (Pule se não for zero), o que quer dizer que a execução do programa saltará para a linha 004AD2D4 se o conteúdo de EAX não for zero.
      Bom, se a execução não saltar e seguir abaixo, cairemos na mensagem de erro. Se saltar, a pularemos. Então seria interessante alterar essa parte do programa para que sempre salte para a linha 004AD2D4. Isso significa que independente do resultado do teste anterior (TEST EAX, EAX) o salto ocorrerá, sempre. Assim nunca cairemos na mensagem novamente e programa continuará sua execução normal.
      O comando que faz o papel de salto incondicional em assembly é o JMP (Jump). Então, vamos alterar o JNZ da linha 004AD2A0 para JMP (e manter o resto da linha). Para isso, basta selecionar a linha e apertar a barra de espaços, depois clicar em Assemble.

      Feito isso, o Olly marca nossa alteração em vermelho. Clicando com o botão direito do mouse sobre a alteração (ou próximo) e escolhendo “Copy > All modifications”, uma tela com as modificações abre e então basta clicar novamente com o botão direito e escolher “Save file”.

      Dei o nome de MK4-mod.EXE para facilitar o reconhecimento. Agora vamos ao teste. Ao executar este novo executável modificando, vemos o jogo rodando:

      É importante esclarecer que os passos descritos aqui não são genéricos e não servem para todos os softwares que não funcionam, em primeira instância, no Vista. O funcionamento depende de vários fatores e principalmente do nível de integração do software com o SO para o qual ele foi desenvoldido.
      O objetivo deste artigo foi demonstrar como a ER pode nos ajudar a resolver pequenos (e grandes, por quê não?) problemas do dia-a-dia na informática. Este é um dentre dezenas de exemplos de uso da ER para soluções que seriam um pouco difíceis sem ela.
    • Por nicolaslima321
      Caros,
      Utilizo o OpenSUSE Tumbleweed na minha máquina, minha distro não reconhece o comando "HD", eu tenho usado o "Hexdump" que eu imaginava que estaria fazendo a mesma coisa, tentando fazer os exemplos da aula 3 do curso CERO, o resultado ficou em ordem diferente (Print abaixo). Sabem se é possível adicionar o comando "HD", se fiz algo de errado ou se faltou alguma coisa?
      Agradeço desde já


       
       

    • Por Leandro Fróes
      Após ver sobre o comando find no nosso canal Papo Binário decidi estudar um pouco mais sobre o mesmo. Revisando estas anotações pensei que seria interessante compartilhá-las, tendo em vista que o find é um comando extremamente poderoso. Alguns dos parâmetros já foram abordados no vídeo, mas vou repassar alguns aqui, não custa nada, não é mesmo?!
      Este comando pode ser útil para diversas tarefas, dentre elas investigação, administração ou mesmo aprendizado sobre o sistema.
      Indo direto ao ponto, o find é um comando para procurar itens no filesystem (arquivos, links, diretórios, etc). O que o difere de outros programas que fazem isto é a quantidade de opções que a ferramenta possui e o fato de não depender da variável $PATH para encontrar um binário. O comando leva como principal parâmetro um path, ou seja, um caminho para procurar algo. Se não passarmos nada ele entenderá que o path é o diretório atual:
      find find /etc Se não especificarmos exatamente o que queremos buscar o find simplesmente nos mostra tudo o que achar pois ele varre o filesystem recursivamente na hora de procurar algo, mas não queremos isso tudo, até porque não seria muito útil. 🙄
      Vamos tentar entender alguns filtros interessantes... Imagine que você é um administrador e precisa verificar todos os arquivos que pertencem a um usuário em específico:
      find / -type f -user leandro O que fizemos aqui? Utilizamos 2 tipos de filtros, um deles foi o -user, que busca arquivos que pertencem apenas à aquele usuário. O -type filtra pelo tipo de item no filesystem e suporta os seguintes tipos:
      d -> diretório f -> arquivo regular l -> link simbólico s -> socket     Procurando por arquivos perdidos:   Imagine agora que seu sistema está uma bagunça e você não faz ideia onde está um arquivo em específico, pense que você tem no mínimo 8 subdiretórios lotados de arquivos e você não lembra onde está o que você está procurando, só lembra que existe a palavra "mentebinaria" no nome dele. Além disso, você também sabe que não está nos primeiros 2 subdiretórios. Podemos resolver com: find . -mindepth 2 -name "*mentebinaria*" -type f A primeira coisa que fizemos foi utilizar a opção -mindepth, que especifica quantos níveis na hierarquia o find deve olhar no mínimo (a opção -maxdepth especifica o máximo). A outra opção foi a -name, que procura por um nome completo ou parte dele como fizemos no exemplo utilizando o wildcard * (asterisco) para bater com qualquer string antes de depois da palavra "mentebinaria".   Executando comandos:
      Na minha opinião uma das opções mais interessantes do find é a -exec, que praticamente executa comandos em cima do que o find encontrar. Não entendeu? Vamos lá... supondo que queiramos ver qual o tipo de arquivo de todos os arquivo que encontrarmos em um diretório em específico com o comando file:
      find . -type f -exec file {} \; Temos muita coisa pra entender nesta linha. Primeiro, o -exec trabalha com o conceito de targets (as chaves {} ) e isto significa: coloque tudo o que o find devolver no local da chave. Para cada arquivo que o find achar ele rodará o comando file naquele arquivo. Incrível, não?
      Sim, mas com isto estaremos executanto o mesmo comandos múltiplas vezes, por exemplo:
      leandro@teste:~$ find . -type f | wc -l 295 Imagine rodar isto 295 vezes, muita coisa, não? Se notarmos no primeiro exemplo do -exec vemos que no fim da linha tem um ponto de vírgula e este indica o fim do -exec para o find (e não para o shell). Temos que usar a contra barra para escapar e o shell não pensar que é para ele.
      Ok, mas até agora não vimos como melhorar isto. Concordam que o comando file aceita mais de um parâmetro?
      file arq1 arq2 arq3 E se pudéssemos pegar tudo que o find achar e, ao invés de rodar um comando do -exec por vez passamos tudo um atrás do outro? É exatamente isto o que o + faz e para ele não precisamos escapar:
      find . -type f -exec file {} + Este exemplo é a mesma coisa do anterior, mas de forma mais automatizada. Vamos medir a velocidade dos dois comandos:
      root@teste:~# time find / -type l -exec file {} \; ... real 0m15,127s user 0m0,336s sys 0m1,640s root@teste:~# time find / -type l -exec file {} + ... real 0m1,119s user 0m0,212s sys 0m0,396s Bem mais rápido com o +, não acham? 😉
       
      Investigando o sistema:
      Seu servidor foi atacado, você não sabe exatamente o que aconteceu e como aconteceu, só sabe que nem tudo está funcionando do jeito que deveria. Uma coisa interessante à se fazer é tentar olhar para o que exatamente foi alterado desde o ataque. Imagine que isto ocorreu à 2 dias: find / -mtime -2 Aqui estamos dizendo que a partir da hora que rodarmos o comando olhar para tudo que foi modificado 48 horas atrás. Podemos também verificar se algo foi acessado com -atime.
      E se você não sabe exatamente quando foi o ataque? A única coisa que você sabe é que a última coisa que você fez foi adicionar novas funcionalidades à um script que você tem. Podemos procurar por tudo que foi modificado após este arquivo com a opção -newer:
      find /etc -newer <arquivo_velho> Mas como isto? O Linux guarda um tipo de informação chamada MAC no inode de cada arquivo, resumindo é simplesmente a data da última modificação, acesso e criação do arquivo ao qual aquele inode se refere. Apenas como curiosidade, o comando stat lê essas informações também. 😋
       
      Mais algumas informações:
      Ok, agora você não teve nenhum problema, só quer algumas informações sobre os arquivos que o find encontrar. A opção -size <n> pode ajudar a procurar por arquivos maiores (+) ou menores (-) que o especificado:
      find /var -size +20k Podemos trabalhar com os seguintes formatos:
      c -> bytes k -> KB 0 ou -empty -> vazio find . -empty Não está satisfeito? Ok, a opção -ls ti da muito mais informações (praticamente aplica um ls -lids em cima de tudo que o find achar)
      find . -user leandro -type d -ls  
      Facilitando o parsing:
      Achou as opções de informações fracas? De fato a saída fica bem poluída. E se você precisasse todo dia monitorar informações específicas sobre arquivos específicos e criasse um script para isso, como você faria para obter estas informações? O find ti ajuda nisso também!!! Se você está familiarizado com a linguagem C (se não está veja isto) a função printf do C pode imprimir uma saída formatada de acordo com o que você escolher (string, inteiro, inteiro sem sinal, etc).
      Assim como em C, a opção -printf possui uma série de diretivas para formatarmos a saída do find como quisermos, algumas delas são:
      %f -> nome do arquivo %p -> path completo %i -> inode %M -> permissões %n -> número de hard links find / -type f -atime -1 -printf '%p %i %M \n' O único detalhe aqui é que por padrão o -printf não coloca um caractere de nova linha, devemos adicionar como no exemplo. Com isto a saída fica bem mais interesante para um script ler, não acham?! Aqui está o exemplo de uma saída:
      file1 262295 -rw-r--r-- file2 262283 -rw-r--r-- file3 262296 -rw-r--r-- Estas foram algumas dicas sobre o comando find. Com certeza informações mais completas podem ser encontradas no manual do comando, este tutorial tem como objetivo simplesmente compartilhar minhas anotações sobre o que acho bem interessante e usual sobre o comando find.
      Qualquer dúvida, crítica ou sugestão, por favor, sinta-se à vontade para comentar e obrigado! 😄
×