{"id":280,"date":"2025-04-13T19:27:49","date_gmt":"2025-04-13T22:27:49","guid":{"rendered":"https:\/\/utfpr.curitiba.br\/vespas\/?p=280"},"modified":"2025-04-29T17:03:42","modified_gmt":"2025-04-29T20:03:42","slug":"htb-university-ctf-2024","status":"publish","type":"post","link":"https:\/\/utfpr.curitiba.br\/vespas\/htb-university-ctf-2024\/","title":{"rendered":"HTB University CTF 2024"},"content":{"rendered":"\n<p>Dias ap\u00f3s a concep\u00e7\u00e3o da equipe, n\u00f3s tivemos a oportunidade de representar a UTFPR na nossa primeira competi\u00e7\u00e3o de Capture the Flag ou CTF, o <strong>University CTF 2024: Binary Badlands<\/strong> da plataforma HackTheBox, que aconteceu entre os dias 13 e 15 de Dezembro. O evento contou com 49 flags, que s\u00e3o pequenos c\u00f3digos escondidos que voc\u00ea precisa encontrar ou conquistar para ganhar pontos na competi\u00e7\u00e3o, que foram distribu\u00eddas em desafios de diferentes frentes de seguran\u00e7a cibern\u00e9tica.<\/p>\n\n\n\n<p>Ap\u00f3s uma sequ\u00eancia de oficinas preparat\u00f3rias que fizemos para capacitar os membros da equipe para participar na competi\u00e7\u00e3o, obtivemos a classifica\u00e7\u00e3o 108 de um total de 1128 equipes participantes de universidade ao redor do mundo. Nosso resultado foi muito satisfat\u00f3rio considerando o pouco tempo que tivemos para preparar a equipe para a competi\u00e7\u00e3o, o que nos fez perceber o quanto o nosso projeto \u00e9 promissor.<\/p>\n\n\n\n<p>Um dos desafios conclu\u00eddos pela equipe na categoria de engenharia reversa foi o <strong>ColossalBreach<\/strong>, que consistia em dois arquivos: <code>brainstorm.ko<\/code> que era um kernel object file do Linux e um arquivo de texto simples chamado de <code>logs<\/code>. O desafio contava com 7 perguntas, e a resposta para cada uma delas era considerada uma flag:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Who is the module&#8217;s author?<\/li>\n\n\n\n<li>What is the name of the function used to register keyboard events?<\/li>\n\n\n\n<li>What is the name of the function that converts keycodes to strings?<\/li>\n\n\n\n<li>What file does the module create to store logs? Provide the full path<\/li>\n\n\n\n<li>What message does the module print when imported?<\/li>\n\n\n\n<li>What is the XOR key used to obfuscate the keys? (e.g. 0x01, 0x32)<\/li>\n\n\n\n<li>What is the password entered for &#8216;adam&#8217;?<\/li>\n<\/ol>\n\n\n\n<p>Para encontrar a maioria das respostas, fizemos a engenharia reversa do arquivo <code>brainstorm.ko<\/code> utilizando a ferramenta Ghidra.<\/p>\n\n\n\n<p>Para a primeira pergunta, que era o nome do autor do m\u00f3dulo, foi poss\u00edvel encontrar o nome na aba de strings do Ghidra ap\u00f3s fazer a an\u00e1lise do arquivo, mas tamb\u00e9m poderia ser encontrado utilizando o comando <code>strings<\/code> do Linux combinado com <code>grep<\/code> para encontrar um texto espec\u00edfico: <code>strings brainstorm.ko | grep \"author\"<\/code>.<\/p>\n\n\n\n<p><strong>Resposta:<\/strong> <code>0xEr3n<\/code>.<\/p>\n\n\n\n<p>Para a segunda pergunta, o nome da fun\u00e7\u00e3o usada para registrar eventos do teclado, pode ser utilizado um decompiler como o Ghidra, BinaryNinja ou uma ferramenta online como o <a href=\"https:\/\/dogbolt.org\">https:\/\/dogbolt.org<\/a> para fazer uma an\u00e1lise do c\u00f3digo. No output gerado, podemos encontrar a fun\u00e7\u00e3o <code>register_keyboard_notifier()<\/code>, que na verdade \u00e9 uma fun\u00e7\u00e3o do pr\u00f3prio kernel.<\/p>\n\n\n\n<p><strong>Resposta:<\/strong> <code>register_keyboard_notifier<\/code>.<\/p>\n\n\n\n<p>Similarmente para a terceira pergunta, podemos encontrar uma fun\u00e7\u00e3o chamada <code>keycode_to_string()<\/code> no c\u00f3digo, que como o pr\u00f3prio nome j\u00e1 diz, converte <code>keycodes<\/code> para <code>strings<\/code>. Convenientemente a fun\u00e7\u00e3o foi nomeada exatamente como esper\u00e1vamos, mas poderia ser o caso de se ter que analisar a l\u00f3gica da fun\u00e7\u00e3o para entender o funcionamento caso o nome fosse condizente com a pergunta.<\/p>\n\n\n\n<p><strong>Resposta: <\/strong><code>keycode_to_string<\/code>.<\/p>\n\n\n\n<p>A quarta pergunta envolveu um pouco mais de pesquisa, e se tratava de determinar o arquivo criado para armazenar os logs da aplica\u00e7\u00e3o e o caminho completo (full path) de onde ele era salvo na m\u00e1quina. Para chegar na resposta, encontramos no c\u00f3digo gerado pelo Ghidra uma instru\u00e7\u00e3o <code>debugfs_create_dir(\"spyyy\",0)<\/code>, que cria um diret\u00f3rio chamado <code>spyyy<\/code>. Ao procurar na documenta\u00e7\u00e3o do kernel do Linux a fun\u00e7\u00e3o DebugFS, descobrimos seu diret\u00f3rio padr\u00e3o: <code>\/sys\/kernel\/debug<\/code>, tendo assim o caminho completro: <code>\/sys\/kernel\/debug\/spyyy<\/code>.<\/p>\n\n\n\n<p>Para descobrir o nome do arquivo de logs, observamos que logo ap\u00f3s a cria\u00e7\u00e3o do diret\u00f3rio havia uma instru\u00e7\u00e3o <code>debugfs_create_file(&amp;DAT_00100c6c,...)<\/code>, onde <code>&amp;DAT_00100c6c<\/code> \u00e9 um ponteiro referenciando uma regi\u00e3o da mem\u00f3ria. Ao navegar para esse endere\u00e7o pelo Ghidra, podemos ver os caracteres ocupando esse e os pr\u00f3ximos endere\u00e7os formando a palavra <code>keys<\/code>.<\/p>\n\n\n\n<p><strong>Resposta:<\/strong> <code>\/sys\/kernel\/debug\/spyyy\/keys<\/code><\/p>\n\n\n\n<p>A resposta da quinta pergunta estava convenientemente localizada nos pr\u00f3ximos endere\u00e7os de mem\u00f3ria logo ap\u00f3s a palavra <code>keys<\/code> localizada anteriormente, que era a mensagem imprimida quando o m\u00f3dulo era importado: <code>w00tw00t<\/code>.<\/p>\n\n\n\n<p><strong>Resposta:<\/strong> <code>w00tw00t<\/code>.<\/p>\n\n\n\n<p>Para a sexta pergunta, que era qual a XOR key utilizada para ofuscar as chaves, fizemos uma busca pelo caractere &#8216;<code>^<\/code>&#8216; que simboliza a opera\u00e7\u00e3o XOR sendo feita no c\u00f3digo, e encontramos a seguinte instru\u00e7\u00e3o: <code>*pbVar2 = *pbVar2 ^ 0x19;<\/code> nos dizendo que a chave utilizada foi o valor <code>0x19<\/code>.<\/p>\n\n\n\n<p><strong>Resposta:<\/strong> <code>0x19<\/code>.<\/p>\n\n\n\n<p>A pergunta final era o a senha utilizada pelo usu\u00e1rio &#8216;adam&#8217;, e isso nos levou de volta ao outro arquivo apresentado no desafio, o arquivo <code>logs<\/code>. No arquivo, podemos ver uma s\u00e9rie de caracteres encriptados, que, podemos concluir pela pergunta anterior, que foram ofuscados utilizando a opera\u00e7\u00e3o XOR com a chave <code>0x19<\/code>. Existem diversas formas de reverter essa opera\u00e7\u00e3o, como criar um script em Python para desfazer a opera\u00e7\u00e3o, mas nesse caso utilizamos a ferramenta <a href=\"https:\/\/gchq.github.io\/CyberChef\/\" data-type=\"link\" data-id=\"https:\/\/gchq.github.io\/CyberChef\/\">CyberChef<\/a>, que nos d\u00e1 diversas op\u00e7\u00f5es de opera\u00e7\u00f5es de criptografia. Ao inserir o texto encriptado e a &#8216;receita&#8217; XOR do CyberChef e a chave <code>0x19<\/code>, podemos observar no log decifrado a senha inserida pelo usu\u00e1rio: &#8220;supers3cur3passw0rd&#8221;.<\/p>\n\n\n\n<p><strong>Resposta:<\/strong> <code>supers3cur3passw0rd<\/code>.<\/p>\n\n\n\n<p>Com isso conclu\u00edmos o desafio encontrando as 7 flags!<\/p>\n\n\n\n<p>Esse foi apenas um dos 32 desafios conclu\u00eddos pela equipe, mas que foi interessante por ser o primeiro contato de alguns membros com a categoria de engenharia reversa, o que despertou a vontade de se aprofundar no tema e aprender cada vez mais!<\/p>\n\n\n\n<p>Ao final do evento, os times das universidades mais bem classificadas receberam pr\u00eamios e todos os alunos integrantes das equipes receberam um certificado de participa\u00e7\u00e3o.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"726\" src=\"https:\/\/utfpr-ct-static-content.s3.amazonaws.com\/utfpr.curitiba.br\/wp-content\/uploads\/sites\/194\/2025\/04\/2025-04-11-202942-1024x726.jpeg\" alt=\"\" class=\"wp-image-657\" srcset=\"https:\/\/utfpr-ct-static-content.s3.amazonaws.com\/utfpr.curitiba.br\/wp-content\/uploads\/sites\/194\/2025\/04\/2025-04-11-202942-1024x726.jpeg 1024w, https:\/\/utfpr-ct-static-content.s3.amazonaws.com\/utfpr.curitiba.br\/wp-content\/uploads\/sites\/194\/2025\/04\/2025-04-11-202942-300x213.jpeg 300w, https:\/\/utfpr-ct-static-content.s3.amazonaws.com\/utfpr.curitiba.br\/wp-content\/uploads\/sites\/194\/2025\/04\/2025-04-11-202942-768x545.jpeg 768w, https:\/\/utfpr-ct-static-content.s3.amazonaws.com\/utfpr.curitiba.br\/wp-content\/uploads\/sites\/194\/2025\/04\/2025-04-11-202942.jpeg 1117w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Autor: Raphael Felix<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dias ap\u00f3s a concep\u00e7\u00e3o da equipe, n\u00f3s tivemos a oportunidade de representar a UTFPR na nossa primeira competi\u00e7\u00e3o de Capture the Flag ou CTF, o University CTF 2024: Binary Badlands da plataforma HackTheBox, que aconteceu entre os dias 13 e 15 de Dezembro. O evento contou com 49 flags, que s\u00e3o pequenos c\u00f3digos escondidos que [&hellip;]<\/p>\n","protected":false},"author":344,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[5,7,9,8,6],"class_list":["post-280","post","type-post","status-publish","format-standard","hentry","category-writeups","tag-ctf","tag-reversing","tag-utfpr","tag-vespas","tag-writeup"],"_links":{"self":[{"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/posts\/280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/users\/344"}],"replies":[{"embeddable":true,"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/comments?post=280"}],"version-history":[{"count":6,"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/posts\/280\/revisions"}],"predecessor-version":[{"id":661,"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/posts\/280\/revisions\/661"}],"wp:attachment":[{"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/media?parent=280"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/categories?post=280"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/utfpr.curitiba.br\/vespas\/wp-json\/wp\/v2\/tags?post=280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}