Jump to content
  • Sign in to follow this  

    Análise do malware IMG2005M.exe

       (0 reviews)

    Fernando Mercês

    Mês passado eu postei no blog uma análise básica de um malware brasileiro que recebi por e-mail. Algumas pessoas se ofereceram para continuar a análise mas não o fizeram, por motivos diversos. Eu tomei vergonha e achei uma máquina virtual com o XP e alguns programas velhos que ajudariam na análise. Este artigo é o meu relato sobre esse malware.

    No post do blog cheguei a identificar que o malware tinha UPX [1], então neste artigo vamos partir da remoção do packer:

    $ wc -c IMG2005M.exe
    58880 IMG2005M.exe
    
    $ upx -dqq IMG2005M.exe
    102400 <- 58880 57.50% win32/pe IMG2005M.exe
    
    $ wc -c IMG2005M.exe
    102400 IMG2005M.exe

    Ainda no Linux, fui atrás do entry point do binário com o pev [2]:

    $ pev -o IMG2005M.exe | grep -iA3 entry
    Entry point: 0x1758
    Address of CODE section: 0x1000
    Address of DATA section: 0x10000
    Imagebase: 0x400000

    Soma-se o EP à ImageBase e tem-se o offset do EP: 0x401758.

    Daqui pra frente resta muito pouco a se fazer com ferramentas nativas do Linux já que o binário é de Windows e o pev ainda não disassembla.

    Em seguida eu abri uma VM com Windows XP para ver a cara do inimigo:

    icone.png.6d9db8db87dfb8e1af13bae8e2dd780c.png

    Brincalhão esse coder hein? Detalhe para o ícone de fotos no EXE – usuário leigo cai fácil.

    Depois usei o RDG Packer Detector [3] para tentar descobrir o compilador utilizado no arquivo, se há alguma criptografia conhecida envolvida, hashes etc:

    rdg.png.20aaa7fddf8d4ad3465166c51d47d4b8.png

    O RDG detectou que é um binário compilado em Visual Basic 6.0, em código nativo. Pelo visto era só o UPX mesmo pois o RDG não detectou mais nada. No entanto, são suposições…

    Usando o OllyDbg [4], abri o malandro, e sempre a primeira coisa que vem em minha mente binária é buscar pelas strings hardcoded no executável. As strings dentro de um executável podem dizer *muito* sobre ele. Vale sempre a pena “passar o olho” nelas. No Olly é bem simples buscá-las: basta clicar com o botão direito e ir em “Search for -> All referenced strings”.

    Várias strings foram encontradas (referenced-strings.txt). Destaco algumas:

    UNICODE “*AC:Documents and SettingsMasterDesktopProfessor PardalSummer_TRSSummer_TRS.vbp”
    ASCII “GetLocaleInfoA”
    ASCII “GetUserDefaultLCID”
    UNICODE “6655475C45405C58521B606F53535577515F505640625441”
    UNICODE “625F5B06076B7A465047524C58585F6B4A46415059”
    UNICODE “695B5E545F470707584D1D4C5C46”

    A primeira string, bem, acho que dispensa comentários né? 

    Em seguida duas funções da API do Windows para identificação do idioma. Seria particularmente interessante um malware brasileiro ter versões do Windows em português como alvo?

    As outras três eu escolhi aleatoriamente. Acontece que criadores de malware sabem que precisam proteger suas strings, do contrário, muita coisa ficaria exposta a qualquer curioso que souber utilizar o comando strings do *n?x ou funções como essa do OllyDbg. Como há várias strings similares a essas três no binário, aposto que são strings encriptadas pelo programador do malware. Você não? =P

    De volta à tela do disassembly (ALT+C), parado bem no EP:

    00401758 PUSH 00401850
    0040175D CALL <JMP.&MSVBVM60.#100> ;Jump to MSVBVM60.ThunRTMain

    O jeito como o compilador constrói o executável é importante. No caso do VB é desse jeito acima: coloca-se um endereço na pilha e chama uma função da biblioteca. Esse endereço PUSHado é o offset de uma estrutura que define todo o programa em VB.

    Olhando a estrutura em 0x401850 no dump, dá pra identificar o offset do ProjectStruct (vem após esse 0x409):

    00401850  56 42 35 21|F0 1F 56 42|36 45 53 2E|44 4C 4C 00|  VB5!ðVB6ES.DLL.
    00401860  00 00 00 00|2A 00 00 00|00 00 00 00|00 00 00 00|  ….*………..
    00401870  00 00 0A 00|0A 0C 00 00|09 04 00 00|D0 AE 40 00|  ………..Ю@.
    00401880  D8 1B 40 00|00 F8 30 00|00 FF FF FF|08 00 00 00|  Ø@..ø0..ÿÿÿ…

    Então fui para o endereço 0x40AED0 no disassembler (CTRL+G) e coloquei um breakpoint (F2) logo no início da função. Aí foi só seguir com o F8 até chegar numa call que parecia interessante pois era uma chamada de função interna em 0x40AF1C.

    0040AF16  MOV EAX, DWORD PTR SS:[LOCAL.5]
    0040AF19  PUSH EAX
    0040AF1A  MOV ECX, DWORD PTR DS:[EAX]
    0040AF1C  CALL DWORD PTR DS:[ECX+1C] (0x40B450)
    0040AF1F  TEST EAX, EAX
    0040AF21  FCLEX

    Ao entrar nessa call, caí em 0x40B450. Nessa função dá pra ver uma daquelas strings doidas sendo operada em 0x40B4B7. Foi ali mesmo que coloquei um breakpoint e mandei rodar (F9).

    0040B4B0  MOV DWORD PTR SS:[LOCAL.1], 3
    0040B4B7  MOV EDX, 00402664  ; UNICODE “6655475C45405C58521B606F53535577515F505640625441”
    0040B4BC  LEA ECX, [LOCAL.11]
    0040B4BF  CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCopy>]
    0040B4C5  LEA EAX, [LOCAL.11]
    0040B4C8  PUSH EAX
    0040B4C9  LEA ECX, [LOCAL.17]
    0040B4CC  PUSH ECX
    0040B4CD  CALL 0040AF60
    0040B4D2  PUSH 0
    0040B4D4  LEA EDX, [LOCAL.17]
    0040B4D7  PUSH EDX
    0040B4D8  LEA EAX, [LOCAL.12]
    0040B4DB  PUSH EAX
    0040B4DC  CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrVarVal>]
    0040B4E2  PUSH EAX
    0040B4E3  LEA ECX, [LOCAL.21]
    0040B4E6  PUSH ECX

    Fui seguindo com F8 e quando passei da chamada para __vbaStrVarVal em 0x40B4DC não é que a string se transformou?!

    O que era “6655475C45405C58521B606F53535577515F505640625441” virou “Scripting.SWbemObjectSet”, mas como? Os olhos aqui têm que estar afiados. Se liga:

    $ echo -n 6655475C45405C58521B606F53535577515F505640625441 | wc -c
    48
    
    $ echo -n Scripting.SWbemObjectSet | wc -c
    24

    A string encriptada tem o dobro do tamanho. Além disso, parecem ser bytes hexa já que todos os dígitos vão de 0 a F. Mas se você achou que o Professor Pardal simplesmente usou os bytes hexa de cada caracter da string original para encriptá-la, se enganou. É um pouquinho mais trabalhado. hehehe

    Repara que antes da string ser desencriptada, o fluxo de execução só passou por uma função local, uma call em 0x40B4CD para 0x40AF60. As outras são funções da MSVBVM60.DLL. Portanto pude supor que é nesta função que está a rotina de desencriptação, coloquei um breakpoint lá e comecei tudo de novo…

    Essa função que desencripta (0x40AF60) é relativamente grande. Vou resumir o que ela faz:

    O primeiro loop (de 0x40B08F a 0x40B123) cria a seguinte string fixa gigante que será usada mais à frente:

    “5655545655381688355541151683736525351505152535455336435363716816838424040414195431239696123125941259”

    Por que usar um loop para criar uma string fixa ao invés de declará-la hardcoded? Essa string é a chave para descriptografar todas as outras. O Professor Pardal não a deixaria tão solta. Se tiver curiosidade de descobrir como ela é gerada vai ser um ótimo treino, principalmente pra quem está começando. Qualquer coisa tô pelo Twitter.;)

    O segundo loop pega dois caracteres da string encriptada e os interpreta de uma vez como um byte hexadecimal (um número). Depois disso, XOReia (tem gente que fala mIgUxOO) este número com o equivalente númerico do caractere da string chave na mesma posição. Complicou? Vamos a um exemplo…

    String encriptada: 665547

    1. Pegam-se dois caracteres da string encriptada e os interpreta como um número hexa:
    “66” -> 0x66

    2. Pega-se o equivalente numérico de um caractere da string chave:
    “5” -> 0x35

    3. Faz-se o xor entre esses números
    0x66 ^ 0x35 = 0x53

    4. Converte o resultado para o equivalente em ASCII.
    $ printf “x53n”

    5. Volta para o passo 1 até que todos os caracteres da string encriptada tenham sido pegos, sempre dois a dois. O próximo cálculo será 0x55 ^ 0x36 e o outro, 0x47 ^ 0x35, certo?

    Pra você não se perder no disassembly, o xor fica em 0x40B309 – é uma chamada à função __vbaVarXor da MSVBVM60.DLL. Nem bitwise programa em VB faz, rapaiz!

    Escrevi um programa em C para fazer este trabalho sujo de desencriptar as strings (pardal_decrypt.c) :

    $ gcc -o pardal_decrypt pardal_decrypt.c
    
    $ ./pardal_decrypt 6655475C45405C58521B606F53535577515F505640625441
    Scripting.SWbemObjectSet

    Em 0x40B4E7, depois de desencriptar a primeira string, o malware chama a função rtcCreateObject2 da biblioteca. Conseguimos saber o nome dela graças à análise do OllyDbg. Dá pra imaginar o que essa função faz pelo nome e pela string que foi descriptografada antes dela.

    Não tenho intenção aqui de reescrever o código do malawre, então não vou me focar em como ele faz e sim o que ele faz. Logo, meus chutes de código não refletem necessariamente a realidade.

    Daqui pra frente seria bom acompanhar olhando o disassembly do malware (cuidado – não vá rodar o cara!)

    Na sequência, mais strings são desencriptadas: “Scripting.SWbemObjectSet” e “Scripting.SWbemObject”. Objetos destas classes também são criados. Em seguida mais duas strings: “Win32_OperatingSystem” e “winmgmts:{impersonationLevel=impersonate}”.

    Não é difícil deduzir que será feita uma query WMI. Em 0x40B672 há uma chamada para a rtcGetObject. É claro que ter alguma experiência com programação ajuda aqui. No caso de executáveis feitos em VB, ter programado em VBScript me ajuda.

    Entrando na call em 0x40B70D, cheguei na função 0x40E210, que pega o idioma da instalação do Windows. Ainda nesta função, em 0x40E38F, o malware verifica se a string “uguês (Brasil)” faz parte da string de retorno do idioma. É uma chamada à função InStr() do VB.

    De volta ao fluxo anterior, em 0x40B726 rola um “for each” que vai iterar através da coleção de objetos que a query “SELECT * FROM Win32_OperatingSystem”, montada algumas linhas antes, retorna. Nesse loop duas coisas são feitas: o atributo Caption do objeto retornado é guardado e o idioma é checado.

    Em 0x40B87F há uma call interna para 0x4019ED. Esta é um call bem legal de acompanhar de perto. Ela desencripta a string “TMP” e em 0x40BB58 chama a rtcEnvironBstr, que vai retornar o valor de uma variável de ambiente. No caso, o valor da variável de ambiente TMP que é o caminho completo do diretório temporário do usuário logado:

    C:> echo %TMP%
    C:DOCUME~1xpclientCONFIG~1Temp

    O malware desperta a curiosidade: o que ele quer no temp? Baixar algo? Gravar algo? Em 0x40BF57 o corno chama a rtcFileCopy e se copia para o diretório temporário do usuário. Em seguida testa se está no Windows Vista ou 7 para usar o runas, porque ele vai querer executar a sua cópia com privilégios administrativos.

    Em 0x40C101 ele manda executar sua cópia com uma chamada a rtcShell e morre. O trabalho sujo mesmo será feito pela cópia agora.

    Abri a cópia no debugger e vi que em 0x40C12A o malware verifica se seu caminho atual de execução é o diretório temporário. O problema é que pelo menos no Windows XP, essa checagem foi feita de maneira errada (pois é, bug no malware). O caminho atual pego vem no formato 8.3 do DOS. Veja:

    0040C12A  MOV EAX, DWORD PTR SS:[LOCAL.10] ; UNICODE “C:\DOCUME~1\xpclient\CONFIG~1\Temp\IMG2005M.exe”

    Quando essa string é comparada com o conteúdo da variável ambiente TMP, o resultado é falso e o malware tenta se copiar novamente para o temp, mas já existe um executável dele lá (que é ele mesmo) e não consegue se copiar. Aí entra em loop. =P

    Zerei, em tempo de execução, o valor de EAX, que é o registrador que armazena o retorno da __vbaStrCmp, para que o salto em 0x40C132 aconteça.;)

    Seguindo a análise, entrei numa call para 0x40C640 que busca o valor “EnableLUA” na chave “HKLMSOFTWAREMicrosoftWindowsCurrentVersionPoliciesSystem”. Caso não exista ou não seja zero, o malware seta para zero, desabilitando esta proteção do Windows.

    Mais a frente, em 0x40C939 ele exibe essa mensagem:

    msgbox.png.5ad2a82a47a43c63b275ed1e599df3ab.png

    Isso não é um erro causado pelo malware – é uma mensagem inofensiva, exibida de propósito. O texto é fixo e essas strings fazem parte das strings criptografadas. Elas estão em 0x40C8CF e 0x40C8EA.

    Agora o processo fica residente aguardando acesso à internet. Para isso ele tenta acessar a página do Google. Quando conseguir, vai para a última função do mal em 0x40C9D0. À esta altura do campeonato, basta olhar a função que você vai perceber todo este fluxo.;)

    Logo no início dela, um arquivo mkajs21mx.tmp é criado no diretório temp do usuário. Em seguida o malware faz uma conexão com um serivodr MS-SQL remoto, na URLia8eaatjyur0gqzaslrlqw2n8k.zlg.br na porta 9321. Nome de usuário, senha e nome do banco também são desencriptados pela mesmíssima rotina 0x40AF60. Após conectar, o malare faz a seguinte query SQL:

    SELECT TOP 1 * FROM Professor_Carregador ORDER BY Professor_Carregador_ID DESC

    O retorno dessa consulta tem ~70k e começa com 0x4d e 0x5a. O que é o que é? =D

    O malware salva o binário pego via SQL em %WINDIR%System32MakeObject.dll e depois registra essa DLL com o regsvr32.exe como um complemento do IE:

    complemento.png.35a43b5f9f9c9c57a0ff526b75e22006.png

    Aí vem outra query:

    INSERT INTO Professor_Informa(Professor_Informa_WithEvents,Professor_Informa_Control) VALUES(‘0’, ‘0’)

    Fiz um script em VBScript pra pegar alguns registros deste banco (pardal_sql.vbs) e descobri que há mais de 6000 registros já. Ou seja, um número próximo desse de computadores brasileiros foram infectados. Impressionante. Já em relação aos registros, não tem nada demais.

    Por fim, só pra não dizer que não perturbou, o malware tenta apagar o arquivo WAV que é o somzinho de inicialização do Windows, mas pelo menos no XP SP3 PT-BR ele errou o nome e tentou apagar o Início do Windows XP.wav quando o nome real é Inicialização do Windows XP.wav. Segundo bug. ¬¬

    E o que faz a MakeObject.dll? Eu dei uma pesquisada e achei alguns usuários reportando sintomas de envio automático de e-mail via Hotmail. Por coincidência ou não, todos tinham essa DLL em logs do HiJackThis. Mas no momento estou cansado de ver funções do VB na minha frente. Então quem quiser analisar, eu envio a DLL.

    Os usuários de Windows têm então mais duas coisas para se preocupar: a falta do somzinho de incialização e um MakeObjects como complemento no IE. Sem falar na DLL em si, que não sabemos o que faz ainda. Boa sorte! hehe

     

    Referências:


    [1] upx.sourceforge.net
    [2] https://github.com/merces/pev
    [3] rdgsoft.net
    [4] www.ollydbg.de

    Sign in to follow this  


    User Feedback

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest

  • Similar Content

    • By kassane
      Olá pessoal, tudo bem?
      Creio que a maioria já sabem sobre  software reverse engineering(SRE) publicado pelo NSA's Research Directorate.
      Pois já existe uma comunidade voltada para esta ferramenta específica com um crescimento massivo, inclusive até mesmos curiosos desconfiados.
      Fontes de informações disponíveis:
      Ghidra -Download Release Notes Installation Guide Issues Tracker Community Collection Cheat Sheet - PDF API Documentation Decompiler Documentation Online Courses Getting Started Scripts Wiki IDA PRO database to Ghidra Plugins:
      GDBGhidra Ghidra Firmware Utils Function Tracer x64dbg-ghidra ret-sync (It's a set of plugins that help to synchronize a debugging session (WinDbg/GDB/LLDB/OllyDbg/OllyDbg2/x64dbg) with IDA disassembler.) Dragon Dance Launch WinAFL Go tools - Ghidra Ghidra Decompiler pyscript IDA keybindings to Ghidra or IDA2Ghidra-kb  
    • By Candeer
      Olá, já faz um bom tempo desde do ultimo artigo sobre a construção de debuggers mas, sem mais delongas, vamos dar continuidade a esta série! 😀 
      Neste artigo iremos falar um pouco sobre uma chamada de sistema que é capaz de controlar quase todos os aspectos de um processo: a syscall PTRACE (process trace). Antes de continuarmos, vale ressaltar que todo o código utilizado neste artigo está disponível no repositório do Github.
      De acordo com o manual do Linux (man ptrace), a syscall ptrace é definida assim:
      "A syscall ptrace provê meios para que um processo (denominado "tracer") possa observar, controlar a execução de um outro processo (denominado "tracee"), examinar e modificar a memória e registradores do "tracee". É primariamente utilizado para a implementação de 'breakpoint debugging' e para rastreamento de syscalls".
      Em outras palavras, podemos utilizar a ptrace para controlar um outro processo sobre o qual termos permissões sobre!
      Por exemplo, execute:
      strace /bin/ls O comando "strace" acima, é utilizado para que se possa rastrear todas as syscalls que um programa realiza. Vale lembrar que toda a técnica utilizada para o rastreamento de syscalls envolve o conteúdo abordado nos artigos anteriores, então é de suma importância que você tenha lido (ou saiba) o primeiro artigo sobre Sinais e o segundo sobre Forks.
      Antes de começar a rastrear um dado comando, o strace precisa ter controle total sobre a execução do processo alvo, para isso é feito um fork do processo em questão e o mesmo é "traceado". Voltaremos neste assunto em breve.
      A wrapper da ptrace é definida em <sys/ptrace.h> e tem o seguinte protótipo:
      #include <sys/ptrace.h> long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data); Onde o primeiro argumento request é um enum onde cada valor define uma ação em cima do "tracee", tais como TRACEME, GETEREGS, SETREGS e etc. O segundo argumento, pid, é o PID (Process Identification) do processo que queremos "tracear", o terceiro argumento addr é um endereço para alguma interação que a ser realizada da memória do processo "traceado" e o quarto e último argumento data é algum tipo de dado passado para o processo.
      Agora que você ja conhece o formato desta syscall, vamos fazer um pequeno breakdown do comando "strace".
      Execute:
      strace strace /bin/ls 2>&1 | grep -A2 clone Por mais bizarro que o comando acima pareça, o que vamos fazer aqui é rastrear todas as syscalls que o strace faz usando o próprio strace! Como a saída padrão do strace não é o stdout (dê uma lida em standart streams, caso esteja confuso) então é primeiro redirecionar a saída de erro para a saída padrão, para que seja possível rodar o grep no que queremos.
      Estamos buscando aqui, alguma chamada a syscall clone, que é sempre chamada quando é feito um fork. A chamada à ptrace vem logo em seguida:
      clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f7c4aa8ea10) = 16203 ptrace(PTRACE_SEIZE, 16203, NULL, 0) = 0 Nesse caso, o strace cria um processo filho e em seguida usa o ptrace com o argumento SEIZE para iniciar o rastreamento (tracing) de um processo sem interrompê-lo, como analisaremos em seguida. Dessa maneira o strace é capaz de interceptar cada chamada de sistema feita pelo processo!
      Dê uma olhada no comando ltrace, que diferente do strace, rastreia todas as chamadas à bibliotecas (libraries trace) e tente fazer o mesmo que fizemos acima!
      Algumas ações notáveis que podemos fazer com a ptrace:
      PTRACE_PEEKTEXT, PTRACE_PEEKDATA Ler uma word em um dado endereço. PTRACE_POKETEXT, PTRACE_POKEDATA Copiar uma word para um determinado endereço (injete dados na memória). PTRACE_GETREGS Ler os registradores de um processo, que será guardado na struct user_regs_struct em <sys/user.h>. PTRACE_SETREGS Escrever nos registradores de um processo (também no formato da struct acima). Execute "man ptrace" para uma abordagem mais detalhadas de todos os valores disponíveis. 👍
       
      Implementando um simples tracer
      Agora que já temos uma base de forks e uma ideia de como o ptrace funciona, podemos unificar os dois e tenho certeza que o ptrace irá ficar mais claro. A partir de agora ele é fundamental para a implementação do nosso debugger.
      O primeiro passo é definir o escopo de como será feito o nosso "tracer": vamos rastrear um processo que já esta sendo executado ou vamos criar um novo? Para o nosso debugger, iremos apenas criar um fork e trocar sua imagem de execução para a do programa que queremos debugar, usando uma das funções da família exec.
      Primeiro vamos usar a função execl, que faz parte do leque de funções exec (man 3 exec) que trocam a imagem do nosso processo por outra, ou seja, o nosso programa é realmente trocado por outro em uma execução.
      A função execl é definida como:
      #include <unistd.h> int execl(const char *pathname, const char *arg, ... /* (char *) NULL */); Onde o primeiro argumento pathname é caminho completo do nosso executável alvo e os demais argumentos, que podem ser vários, são os argumentos para o programa que será executado.
      Para seguir um padrão, o primeiro argumento que geralmente colocamos é o caminho do programa em questão (lembrem que no array argv a posição 0 guarda o nome do programa em si), o resto dos argumentos são opcionais e seguem no modelo de lista de argumentos que são delimitados por um argumento NULL, que geralmente usamos para finalizar a lista.
      Agora considere o seguinte exemplo:
      #include <unistd.h> #include <stdio.h> int main(int argc, char* const* argv) { if (argc < 3) { printf("Usage: %s <command> <args>\n", argv[0]); return 1; } const char* command = argv[1]; char* const* args = &argv[1]; printf("First arg => %s\n", args[0]); execv(command, args); puts("Continua?\n"); return 0; } Compile com
      $ gcc -o exec exec.c $ ./exec /bin/ls -lah Este programa bem simples demonstra como a exec funciona.
      O que acabamos de criar aqui foi uma espécie de wrapper para qualquer comando: ele irá pegar o nome do comando e os seus respectivos argumentos e trocar sua execução atual pela a que você especificou.
      Note também a string "Continue?" que deveria ser impressa na tela. Esta nunca será impressa pois o nosso programa virou de fato, outro.
      Interessante, não? Usando um pouco de criatividade, podemos criar novos processos filhos combinando forks + exec, ou seja, criamos um fork do nosso processo e trocamos sua imagem por outra! Dessa maneira, por exemplo, temos total controle sobre o comando ls.
      Modificando um pouco o código acima e seguindo a ideia de forks, temos:
      #include <stdio.h> #include <sys/types.h> #include <sys/ptrace.h> #include <unistd.h> int main(int argc, char* const* argv) { if (argc < 3) { printf("Usage: %s <command> <args>\n", argv[0]); return 1; } const char* command = argv[1]; char* const* args = &argv[1]; pid_t child_pid = fork(); // Neste ponto, todas as variaveis sao copiadas para o nosso fork // o fork NAO recebe as mesmas variaveis, apenas uma cópia ;) if (!child_pid) { // Hora de transformar nosso fork em outro programa ptrace(PTRACE_TRACEME, NULL, NULL, NULL); execv(command, args); } char in; do { puts("Iniciar processo ? [y/n]: "); in = getchar(); } while (in != 'y'); ptrace(PTRACE_CONT, child_pid, NULL, NULL); return 0; } Compile
      $ gcc -o fork_exec fork_exec. $ ./fork_exec /bin/ls O programa acima realiza os primeiros passos do nosso tracer: é passado o caminho de um programa e os argumentos para o mesmo. Com isso criamos um fork e usamos o ptrace no própio fork com o argumento TRACEME. Este parâmetro indica que o este processo será "traced" pelo seu processo pai. Em seguida trocamos a nossa execução para o nosso programa alvo. Neste momento temos total controle sobre a execução, no exemplo acima, do comando ls.
      Quando um processo inicia sua execução com TRACEME + exec, o mesmo recebe um sinal de interrupção (SIGTRAP) até que o seu processo pai indique que ele deve continuar sua execução. Por isso, o nosso processo pai, que retém o PID do processo filho, usa o ptrace com o argumento CONT para que seja enviado o signal para dar continuidade de execução.
      E depois?
      Agora toda a comunicação entre os processos pai e o filho se dará via sinais e usaremos a syscall wait constantemente.
      Lembra que definimos acima algumas funções que podemos usar em conjunto com a ptrace? Para já irmos adiantando alguns artigos, vamos fazer um programa que mostra o estado dos registradores para um processo, passo a passo. Vamos usar dois parâmetros para a ptrace: GETREGS e STEP. Segue o código:
      #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/ptrace.h> #include <sys/user.h> #include <sys/wait.h> void display_regs(struct user_regs_struct* regs) {     printf("RIP: 0x%x\n", regs->rip);     printf("RBP: 0x%x\n", regs->rbp);     printf("RSP: 0x%x\n", regs->rsp); } int main(int argc, char* const* argv) {     if (argc < 2) {         fprintf(stderr, "Usage: %s <program_path>\n", argv[0]);         return 1;     }     const char* progName = argv[1];          pid_t child = fork();     if (!child) {         ptrace(PTRACE_TRACEME, NULL, NULL, NULL);         execl(progName, progName, NULL);     }          int status;     int options = 0;     int signal;     // Estrutura que mantem os registradores     struct user_regs_struct regs;     /// Capta primeiro sinal de parada do filho     waitpid(child, &status, 0);     signal = WSTOPSIG(status);     if (signal == SIGTRAP) {         printf("Processo alvo %s esperando pronto para iniciar\n\n", progName);     }          printf("Executando 10 instruções\n");     for (int i = 0; i < 10; ++i) {         printf("Passo: %d\n", i+1);         // Executa uma instrução         ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);         // Espera sinal do filho         waitpid(child, &status, 0);         // Copia o estado atual dos registradores         ptrace(PTRACE_GETREGS, child, NULL, &regs);         // Função local para imprimir os principais registradores         display_regs(&regs);         puts("\n\n");     }     puts("Continuando...\n");     /// Continua execução     ptrace(PTRACE_CONT, child, NULL, NULL);     waitpid(child, &status, 0);     printf("Filho saiu com %d\n", WIFEXITED(status));     return 0; }  
      Compile:
      $ gcc -o tracer tracer.c $ ./tracer /bin/ls O código acima, além de criar e rastrear o processo, executa as primeiras 10 instruções e copia os estados dos registradores em cada passo. Logo após, continua a execução do programa normalmente.
      A estrutura user_reg_struct, definida em <sys/user.h>, contém todos os registradores que estão disponíveis na sua arquitetura. O código foi escrito considerando um ambiente x86-64.
      Com o estudo da ptrace, fechamos toda a introdução para construirmos o nosso debugger de fato, que vamos começar a desenvolver no próximo artigo, incialmente com capacidade de por breakpoints, imprimir o atual estado dos registrados e executar instrução por instrução do processo.
      Qualquer dúvida ou correção sinta-se livre de por nos comentários!  😁
      Links úteis:
      Process control Process relationship Code injection with ptrace Sinais Fork Até a próxima!
    • By Paulo Fegueredo
      Olá pessoal,
      Estou iniciando meus estudos em Analise de Malware, usando o curso CERO do Fernando Mercês como guia inicial.
      Baixei diretamente do site do fabricante o software para analise de executáveis Detect It Easy, e antes de executá-lo, submeti o DIE ao virus total. Pelo menos 6 engines detectaram o artefato como dropers/trojan. 
      Alguém passou por essa experiencia com o DIE?  Chegaram a analisa-lo para confirmar se está limpo?
      Fiquei com receio de executá-lo.
    • By Fernando Mercês
      Dia 02/04/2019 (terça) tivemos o lançamento oficial do Visual Studio 2019, com o anúncio de inúmeras novidades envolvendo o desenvolvimento de soluções baseadas em tecnologias como Azure DevOps, .NET Core, ASP.NET Core, C# e PowerShell.

      Assim como aconteceu em outras ocasiões, a Microsoft novamente fará uma parceria com comunidades técnicas através da realização de eventos locais.

      O DevOps Professionals em conjunto com a FC Nuvem também participa desta iniciativa, com um EVENTO PRESENCIAL e GRATUITO 

      Programação prevista (grade sujeita a alterações):

      - Novos Recursos para Debugging no Visual Studio 2019 + Suporte a Docker no .NET Core 3.0 - Renato Groffe (Microsoft MVP)

      - Dicas e truques com Azure e Azure DevOps no Visual Studio 2019 - Vinicius Moura (Microsoft MVP)

      - Colaboração Contínua com o Visual Studio Live Share - Milton Câmara Gomes (Microsoft MVP)

      - Indo além de ambientes Windows com PowerShell Core, Linux e Visual Studio Code - Ewerton Jordão (.NET SP, SampaDevs)

      Acompanhe e apoie esta iniciativa, divulgando e indicando o Visual Studio 2019 Launch para amigos e colegas de trabalho!
      Mais informações: https://www.sympla.com.br/visual-studio-2019---lancamento---devops-professionals--fc-nuvem__525409
    • By Vira
      Bom dia Galera,
       
      Sou bem novo aqui no Fórum, procurei as regras mas não encontrei. Então usarei apenas do bom senso! 🙂
       
      Eu estou a mais ou menos dois meses cutucando um CTF do hack the box, minha experiência com reversing não é muito grande, mas estou procurando aprimora-la cada vez mais. Terminei semana passada o CERO que o Fernando ministrou no Papo Binário, consegui certos progressos mas ainda assim não consigo retornar a flag.
       
      Segue o enunciado do CTF:
      Find the secret flag and get the name of the creators of this challenge!
      o arquivo do CTF esta em anexo, mas tambem pode ser baixado em https://www.hackthebox.eu/home/challenges/Reversing na opção Find The Secret Flag
      Senha do arquivo ZIP: hackthebox
       
      Identifiquei alguns pontos sobre o desafio:
      As 4 primeiras strings ascii são parte do programa normal, e não são produtivas pra nada, pelo que eu vi, as duas ultimas dentro do data são stirngs encodadas:

      Mesmo sabendo das strings, não encontrei referencias dela em nenhuma parte do código.
      A unica referencia a string encodada é na função sub.printf_400a5b, e o fluxo do código tabém não cai na área dela por padrão

       
      Eu fiz todo os tipos de direcionamentos que aprendi, procurei fazer com que as entradas do que as funções necessitam fossem sempre válidas, mas sempre que entro nestas funções recebo um seg fault, ou uma saida aleatória que não é útil pra  nada.
      As funções que destaquei abaixo são as que não identifiquei como sendo chamadas de forma nennhuma na execução do binário.

       
      Alguém mais experiente poderia me auxiliar com este desafio? Honestamente estou a tanto tempo nele que nem estou mais preocupado com a pontuação em si, mas quero entender que pontos estou errando para melhorar minhas habilidades. tenho certeza que isso me ajudará a reverter strings ofuscadas em malwares!!
       
      Obrigado desde já!
       
       

      secret_flag.zip
×
×
  • Create New...