Jump to content

anderson_leite

Supporter - Nibble
  • Posts

    29
  • Joined

  • Last visited

  • Days Won

    8

anderson_leite last won the day on August 21 2022

anderson_leite had the most liked content!

About anderson_leite

More about me

Recent Profile Visitors

3,960 profile views

anderson_leite's Achievements

26

Reputation

  1. Tudo normal, mas como está na descrição eu coloquei o RTTI para ajudar. Qualquer coisa entra la no discord, eu coloquei no canal Desafios e dai podemos bater um papo sobre alguma dúvida que não afete a resolução diretamente.
  2. Não tem nenhum packer ou software de terceiros envolvidos.
  3. Olá, trago mais um desafio interessante para Linux (logo logo atualizo com o binario para Windows também), onde você precisa montar a flag completa! Ao executar o binario ele vai te dar a metade da flag logo de cara, você deve ser capaz de entender como ele te mostrou essa flag inicialmente e também encontrar a outra metade! Está tudo liberado, você pode fazer patch, manipular o processo e etc... o importante aqui é entender como tudo funciona ? Algum tipo de proteção ? Não O Binário está stripped ? Sim, porém deixei o RTTI para facilitar Qual o formato ? ELF Regras: Coloque a tag de spoiler na sua resposta Algumas ferramentas que podem te ajudar a resolver: x64dbg IDA Free Radare2 Cutter GDB Ghidra Divirta-se! inception
  4. Olá, trago mais um desafio interessante para Linux e Windows onde você só precisa acertar o seu valor de entrada para receber sua flag, a ideia aqui é treinar sua habilidade de analise de codigo e debugging para encontrar uma entrada que cause colisão. Algum tipo de proteção ? Não O Binário está stripped ? Não Qual o formato ? ELF & PE Regras: Coloque a tag de spoiler na sua resposta Não será considerado uma solução valida se a mesma for baseada em patches Não será considerado resoluções baseadas em brute force Algumas ferramentas que podem te ajudar a resolver: x64dbg IDA Free Radare2 Cutter GDB Ghidra colide.exe colide
  5. Olá, mais um simples desafio para Linux e Windows onde você so precisa acertar o valor de entrada para receber seu parabéns ? Algum tipo de proteção ? Não O Binário está stripped ? Sim Qual o formato ? ELF & PE Regras: Colocar tag de spoiler para sua resposta Não será considerado uma solução valida se a mesma for baseada em patches Não será considerado resoluções baseadas em brute force Algumas ferramentas que podem te ajudar a resolver: x64dbg IDA free Radare2 Cutter GDB Ghidra Boa sorte ? weaksum weaksum.exe
  6. Olá, eis mais um simples desafio para Linux chamado revealme onde você precisa apenas precisa descobrir qual o comando este binário vai executar, porém para deixar o desafio mais interessante você deve realizar tudo usando apenas analise estática! ou seja, sem debugging! Algum tipo de proteção ? Não O Binário está stripped ? Sim Qual o formato ? ELF Algumas ferramentas open source que podem te ajudar a resolver são: Cutter Radare Ghidra IDA Free Este desafio será usado no curso CR2 no canal do Papo binário, então caso não consiga basta assistir as aulas ? Boa sorte e divirta-se! revealme
  7. Incrível artigo! Ansioso para as próximas publicações dessa serie.
  8. Parabéns pela solução, e desculpa pela demora no feedback ? Bom, vou deixar uma linha de raciocínio com a tag de spoiler:
  9. @paulosgfExcelente analise! O desafio é bem complicadinho mesmo mas a resolução é extremamente simples!, vou colocar minha dica na tag de spoilers Fico muito feliz que você esteja resolvendo.
  10. Olá, decidi começar a publicar alguns desafios de engenharia reversa, criptografia e análise de malware nessa seção do forum! Para iniciar, eis um crackme para Linux chamado "Call me" onde você só precisa encontrar a chave correta e receber a sua mensagem de resolução ? Algumas considerações: Coloque sua resolução com a tag de spoiler, para não mostrar para todos como resolveu Resoluções por brute-force no input são validas, porém é sempre mais elegante entender o que está acontecendo por trás Dica: Caso sua "chave" esteja errada, você recebera um segmentation fault Algum tipo de proteção ? Não O Binário está stripped ? Sim Qual o formato ? ELF Algumas ferramentas open source que podem te ajudar a resolver são: Cutter Radare gdb Boa sorte ? callme
  11. Esse valor na URL parece mais um UUID, isso é muito usado para gerar um identificador único, então isso pode ser tanto gerado por arquivo quanto por url para download.
  12. Excelente desafio, parabéns pelo packer! por mais simples que seja rende um bom aprendizado. Segue minha resolução abaixo, se as imagens ficarem pequenas pode clicar que expande. Também, meu feedback sobre o packer abaixo:
  13. Olá @Brandao, Se for uma imagem que está dentro do PE, provavelmente ela vai estar na seção de recursos então você pode usar o Resource Hacker para extrair ou trocar por outra.
  14. Parabéns pelo projeto! Excelente contribuição, sempre achei que o AG já tinha uma lib junto com ele.
  15. Já faz um bom tempo (quase 1 ano!) desde o último artigo da série de desenvolvimento de debuggers. Este é o último artigo da série e iremos finalmente criar nosso primeiro prototipo de debugger. A ideia aqui, é compilar tudo que foi ensinado nos artigos anteriores sobre Sinais, Forks e ptrace . Com isso, criaremos um simples tracer em C que irá receber um endereço como argumento e colocar um breakpoint no mesmo. Diagrama Antes vamos definir um pouco o escopo do nosso software: O nosso tracer irá criar um fork e nesse fork será feita a chamada para a execv, que por sua vez irá trocar a imagem do atual processo (seu conteúdo) pela de outro processo, fazendo com que de fato vire outro processo. Já o nosso debugger, dentro de um loop, irá se comunicar via sinais com o processo filho. Breakpoints Existem dois tipos de breakpoints: software breakpoints e hardware breakpoints. Ambos servem para interromper a execução do nosso software em determinada instrução. Para que isso seja possível é necessário que a execução do processo seja interrompida na nossa CPU. Interrupções Quando ocorre algum evento no computador que precisa de um tratamento imediato, a CPU invoca uma interrupção. Cada evento desse contém uma ação especifica que nosso kernel irá lidar de alguma maneira e a estrutura responsável por salvar os valores e significados das mesmas é a Interrupt Descriptor Table. A imagem acima representa visualmente uma implementação desse vetor, onde cada posição (offset) contém uma struct associada e nela os valores necessários para lidar com isso. Você pode ter uma explicação mais detalhada aqui. Mas por que eu estou falando de tudo isso? Porque breakpoints nada mais são do que uma interrupção em um dado endereço que faz com que o processador pare a execução do seu programa. O valor que interrompe a CPU para um breakpoint é o 0x03. Vamos testar isto nesse pequeno bloco de código: main() { int x = 4; // Iniciando qualquer coisa __asm__( "int $0x03" ); } A macro __asm__ permite que seja colocado o código direto em assembly, nesse caso, foi colocado o mnémonico INT, que cuida das interrupções com o valor 3 (offset comentado acima na IDT). Se você compilar e executar esse programa: ~ ./code zsh: trace trap (core dumped) ./code Nesse momento o trabalho de fazer o handle dessa interrupção é do nosso software. O que fizemos aqui foi implementar um software breakpoint. Agora vamos executar esse programa no gdb e não por breakpoint algum (dentro do gdb) e só executar: (gdb) r Starting program: /home/zlad/code Program received signal SIGTRAP, Trace/breakpoint trap. 0x000055555555515f in main () (gdb) disas Dump of assembler code for function main: 0x0000555555555139 <+0>: push %rbp 0x000055555555513a <+1>: mov %rsp,%rbp 0x000055555555513d <+4>: sub $0x10,%rsp 0x0000555555555141 <+8>: movl $0x2,-0x4(%rbp) 0x0000555555555148 <+15>: mov -0x4(%rbp),%eax 0x000055555555514b <+18>: mov %eax,%esi 0x000055555555514d <+20>: lea 0xeb0(%rip),%rdi 0x0000555555555154 <+27>: mov $0x0,%eax 0x0000555555555159 <+32>: callq 0x555555555030 <printf@plt> 0x000055555555515e <+37>: int3 => 0x000055555555515f <+38>: mov $0x0,%eax 0x0000555555555164 <+43>: leaveq 0x0000555555555165 <+44>: retq End of assembler dump. (gdb) Veja que a nossa interrupção foi capturada pelo GDB, pois ele detectou um breakpoint trap e é exatamente isso que iremos fazer. Nosso tracer será capaz de detectar quando irá ocorrer um SIGTRAP, ou seja, um sinal que deve ser tratado por nosso sistema operacional. Finalmente implementando Vamos finalmente começar o nosso pequeno tracer, que será capaz colocar breakpoints, executar instrução por instrução e imprimir os registradores na tela! Para inserir a interrupção de breakpoint (int 3) não precisamos de muito, pois já existe um mnemónico para isso que é o int3 e que tem como valor 0xCC. Para inserir breakpoints precisamos de um endereço (que vá ser executado) e uma maneira de escrever nesse local na memória virtual do nosso processo. Já vimos anteriormente o ptracer e nele sabemos que temos alguns enums que podem ser passados como seu primeiro argumento. São eles o PEEK_DATA e o POKE_DATA, que servem para buscar algo na memória de um processo e escrever algo na memória de um processo, respectivamente. Segue a função que vamos usar para adicionar breakpoints no nosso tracer: uint64_t add_breakpoint(pid_t pid, uint64_t address) { uint64_t break_opcode = 0xCC; uint64_t code_at = ptrace(PTRACE_PEEKDATA, pid, address, NULL); uint64_t breakpoint_code = (code_at & ~0xFF) | break_opcode; ptrace(PTRACE_POKEDATA, pid, address, breakpoint_code); return code_at; } Respire fundo e vamos em partes, a ideia aqui é a seguinte: Dado o pid do nosso processo filho e um endereço de memória, vamos buscar o código que estava naquele local (code_at), salvar esse código (não só queremos adicionar um novo opcode, mas podemos futuramente querer executá-lo) e então vamos adicionar nossa instrução nos bytes menos significativos, ou seja, vamos executar ela primeiro. Usamos aqui uma variável de 64 bits por conta da arquitetura do meu sistema. Se você quiser tornar isto portável, é possível criar uma variável genérica baseada na arquitetura: #ifdef __i386__ #define myvar uint32_t #else #define myvar uint64_t #endif Isso é opcional, mas caso você queira criar algo mais genérico, esse é o caminho. A operação bitwise que fizemos aqui também pode ser “nebulosa” para alguns, mas segue o equivalente de maneira mais “verbosa” e em python: >>> hex(0xdeadbeef & ~0xFF) # Mascarando byte menos significativo '0xdeadbe00' >>> hex(0xdeadbeef & ~0xFF | 0xCC) # Mascarando byte e adicionado opcode int3(0xCC) '0xdeadbecc' O que é feito aqui é uma jogada lógica. Vamos quebrar isso em passos: Fazemos um AND com algo negado (0xFFFFFF00); Fazemos um OR com o resultado que irá "preencher" o espaço vazio, visto que um valor OR 0 será sempre o valor com conteúdo; No final mascaramos o último byte e colocamos nosso opcode; O nosso loop precisa executar enquanto nosso processo filho estiver sendo debugado. Em termos de estrutura de códigos vamos usar um laço que irá receber uma flag para sua execução: while (!WIFEXITED(status)) { // Our code } Caso você esteja perdido nessa função WIFEXITED, vale a pena dar uma olhada no artigo desta série sobre Forks. Agora é puramente uma questão de jogar com sinais e estruturar nosso código da maneira mais coesa possível, resumindo, pura programação ? Após nosso breakpoint ser definido em memória precisamos fazer o handling disso. Para isso usamos a função WSTOPSIG, que irá receber o status do nosso processo (que é atribuído na função wait) e irá nos dizer qual tipo de interrupção ocorreu: while (!WIFEXITED(status)) { wait(&status); signal = WSTPOPSIG(status); switch(signal) { case SIGTRAP: puts("We just hit a breakpoint!\n"); display_process_info(pid); break; } } No momento que uma sigtrap for enviada para a gente podemos considerar que caímos no nosso breakpoint. Nesse momento, nosso processo filho está block (pois sofreu uma interrupção), esperando algum tipo de ação para continuar. A função display_process_info(pid) irá mostrar o atual estado dos nossos registrados, usando o enum PTRACE_GETREGS que recebe a struct regs (também já visto no artigo passado): void display_process_info(pid_t pid) { struct user_regs_struct regs; ptrace(PTRACE_GETREGS, pid, NULL, &regs); printf("Child %d Registers:\n", pid); printf("R15: 0x%x\n", regs.r15); printf("R14: 0x%x\n", regs.r14); printf("R12: 0x%x\n", regs.r12); printf("R11: 0x%x\n", regs.r11); printf("R10: 0x%x\n", regs.r10); printf("RBP: 0x%x\n", regs.rbp); printf("RAX: 0x%x\n", regs.rax); printf("RCX: 0x%x\n", regs.rcx); printf("RDX: 0x%x\n", regs.rdx); printf("RSI: 0x%x\n", regs.rsi); printf("RDI: 0x%x\n", regs.rdi); printf("RIP: 0x%x\n", regs.rip); printf("CS: 0x%x\n", regs.cs); printf("EFGLAS: 0x%x\n", regs.eflags); } O código do nosso loop final fica da seguinte forma: while (!WIFEXITED(status)) { signal = WSTOPSIG(status); switch(signal) { case SIGTRAP: puts("We just hit a breakpoint!\n"); break; } printf("> "); fgets(input, 100, stdin); if (!strcmp(input, "infor\n")) { display_process_info(pid); } else if (!strcmp(input, "continue\n")) { ptrace(PTRACE_CONT, pid, NULL, NULL); wait(&status); } } printf("Child %d finished...\n", pid); return 0; } Não iremos focar em implementação pela parte da interação do úsuario pois não é o foco dessa série de artigos. Tentei ser o mais “verboso” possível no quesito UX ?. No projeto original usei a lib linenoise para criar uma shell interativa, mas isso fica para sua imaginação. Vamos executar: ~/.../mentebinaria/artigos >>> ./tracer hello 0x401122 #<== Endereco da main [130] Forking... Adding breakpoint on 0x401122 We just hit a breakpoint! > infor Child 705594 Registers: R15: 0x0 R14: 0x0 R12: 0x401050 R11: 0x2 R10: 0x7 RBP: 0x0 RAX: 0x401122 RCX: 0x225d7578 RDX: 0x19a402c8 RSI: 0x19a402b8 RDI: 0x1 RIP: 0x401123 CS: 0x33 EFGLAS: 0x246 We just hit a breakpoint! > continue Hello world Child 705594 finished... A ideia aqui não é criar tudo para você. A partir de agora, com o conhecimento básico dessa série de artigos, é possível criar o seu próprio debugger ou ferramenta semelhante. Deixo aqui o meu projeto, sdebugger, que foi fruto do meu estudo sobre este tema. Todo conhecimento base que eu passei aqui foi o necessário para criar este projetinho. Agradeço a toda turma do Mente Binária pelo apoio e desculpa à todos pela demora para finalizar essa série de artigos. Tenho várias ideias para artigos futuros, então vamos nos ver em breve! Links úteis: ELF Interruptions Breakpoints Interrupt Descriptor Table Qualquer problema/erro por favor me chame ?
×
×
  • Create New...