Jump to content

unc4nny

Membros
  • Content Count

    8
  • Joined

  • Last visited

Everything posted by unc4nny

  1. Oi. Se eu nao me engano eh por regra da linguagem. Primeiro eh bom notar que um ponteiro NAO eh um array, e um array NAO eh um ponteiro. Se nao estou enganado, {1, 2, 3} nao eh exatamente um array de inteiros, mas sim uma lista de inicializadores. Isso pode ser usado para inicializar um array de inteiros, mas nao um ponteiro, por exemplo: int a[] = {1, 2, 3}; Por baixo dos panos, isso esta na verdade: Reservando um espaco de sizeof(int) * 3 na stack Colocando cada valor em a[0]...a[2] indivudualmente. Por ex: a[0]=1; a[1]=2... Para voce fazer algo semelhante ao que vc quer fazer, vc pode usar compound literals. int *a = (int []){1,2,3}; Neste trexo vc esta criando uma lista anonima de inteiros, e depois designando um ponteiro para a primeira posicao dessa lista, atravez do array decay. Acho que usei alguns termos mais avancados nessa explicacao, mas o que eu estou tentando dizer eh: Isso nao eh possivel pois eh regra da linguagem! Espero ter ajudado!
  2. Entao, tentei fazer o exercicio que o Fernando deixou pra gente na aula 0 do AMO. Acabou que eu nao cheguei exatamente em um resultado, mas eu acho que cheguei perto. Entao aqui vai minha 'nao-solucao' (O sistema que eu uso eh Manjaro Linux, soh por via das duvidas): A primeira coisa que eu fiz, foi voltar pra VM e abrir o arquivo com o pestudio mais uma vez, soh pra dar mais uma olhada na tabela de strings que o pestudio formou. Nela eu achei algumas coisas interessantes: Uma sequencia de caracteres que representa os caracteres da base64 (A-Z, a-z, 0-9, + e /) e duas "stringonas". Uma delas eh aquela que ele mostrou no video, de tamando 1128, e outra de tamanho 368. Alem de strings em russo e alguns sites. Okay, fiquem com essa informacao da string de caracteres em base64 em mente, vai ser importante (talvez) la pra frente. Mas como o desafio era entender a stringona, eu foquei nisso. A primeira coisa que eu tentei fazer foi decodificar a string: Esse foi o resultado. Nao ajudou muita coisa entao eu tentei ver que tipo de arquivo ele eh: Okay, aparentemente eh uma stream de bytes, dumpando esse arquivo eu obtive: Isso tambem nao ajudou em nada. Entao eu peguei a outra "stringona" e fiz a mesma coisa, pulando pra parte do dump, ela ficou desse jeito: Tambem nao ajudou em muita coisa, mas nessa a gnt ve uma sequencia de caracter conhecida: 'RSA1', um criptosystem bem conhecido. Mas o objetivo eh a outra stringona. Entao ele tem duas strings (que eu saiba) codificadas em base64, e uma outra string com caracteres de base64, me parece razoavel pensar que ele vai decriptar essas strings dentro do programa, usando uma implementacao de decriptador caseira. Com essas informacoes e suposicoes, eu pulei pro ghidra pra tentar ver onde essas strings sao usadas: Procurei strings com no minimo tamanho 63, para ver se encontrava onde os caracteres base64 sao usados, que provavelmente seria o decoder dele: Infelizmente, ghidra nao conseguiu achar a string dos caracteres base64, mas achou as outras 2 stringonas. Entao, peguei a maior e fui ver onde ela era usada: Vemos que o ghidra identificou que a string eh utilizada em 6 ocasioes diferentes, vamos ver entao. Todas as 6 vezes sao na mesma funcao, apelidade pelo ghidra de FUN_004013F2. Essa eh uma das vezes que ele usa ela: Ele pega o tamanho da string, faz um calculo maluco que eu nao entendi o motivo com ele, cujo resultado deu 846. Pega o HANDLE para a heap do processo. Que chamou a funcao, que no caso eu imagino que seja o proprio ransomware. Aloca um bloco de tamanho 846 na heap do processo. A seguir, ele de novo faz o calculo do tamanho da stringona, mas usa ele com outro proposito: Ele chama a funcao que o ghidra apelidou de FUN_0040133e, passando como primeiro argumento a stringona, e como segundo o tamanho da string, entrando na funcao: Esse eh o resultado do decompiler do ghira. Nao entendi muita coisa dessa funcao, pra ser sincero, quando tem muita manipulacao de bit na funcao eu geralmente soh ignoro kkkkk. Mas algumas coisas nessa funcao chamaram minha atencao. Primeiro que eu ja estava esperando que essa stringona fosse chamada em uma funcao desse estilo. Pois como ja foi dito, eu esperava que ele decodificasse ela dentro do codigo. Entao eu fui na internet procurar por algumas implementacoes de um decoder base64: Nao vou falar que eh 100% igual, mas existem semelhancas muito grandes. Entao eu continuei a explorar com a suposicao que aquele era o decoder dele. Mas soh tem um problema, ele nao usa nenhum tipo de retorno, e o ghidra nao especifica se ele esta usando de fato um literal de string ou um endereco de memoria. Entao eu parti pra analisar as instrucoes e ver o que elas me dizem Antes de passar pras instrucoes, notem que depois que ele chama o 'decoder' ele faz faz mais uma vez aquele calculo doido com o tamanho da stringona e chama uma funcao da API do windows, CryptDecrypt: Eu poderia ver o que eh este DAT_0040F968. Mas isso vai alem do escopo do exercicio. Eu ate tentei, mas assim como esse exercicio, eu cheguei numa resposta mais ou menos hehehe Aqui esta a sequencia de instrucoes ate o CryptDecrypt: Aqui, percebi que realmente, aparentemente ele nao utiliza o resultado da funcao que eu estava chamando de decoder, e que ate agora ainda acredito que seja, pois ela eh usada mais uma vez em um contexto similar, no que eu acredito que seja a outra stringona, mas isso vai alem do escopo do exercicio. Voltando para CryptDecrypt, os argumentos passado para ela sao: Segundo a API do windows, essa funcao decripta dados que foram previamente encriptados usando a funcao CryptEncrypt, que inclusive eh o contexto que eu me referi onde a outra stringona eh usada, com a funcao que eu acredito que seja o decoder. Essa eh a assinatura da funcao, entao, fazendo a cross-reference com a assinatura e com os parametros que foram passados pra chamar a funcao, da esquerda pra direita: DAT_0040F968 = hKey (Um HANDLE para a chave que sera usada para decriptacao, esse HANDLE foi gerado pela funcao CryptImportKey, pelo que eu pude perceber a outra stringona tambem sera usada nessa funcao. Acredito que a outra stringona na verdade seja usada para encriptar, e essa para decriptar.) 0 = hHash (Um HANDLE para um objeto hash, o valor eh zero entao provavelmente eh um ponteiro nulo) 1 = Final (Um valor booleano que indica se esta eh a ultima secao de blocos a ser decriptada, o valor eh 1 entao ela eh a ultima ou a unica) 0 = dwFlags (Nao ha flags, entao nao precisamos nos preocupar, mas isso seria imagino que algumas opcoes adicionais para a decriptacao) pbData = pbData (Na verdade, como podemos ver la em cima, esse eh o valor do bloco alocado de heap do processo. Segundo a API do windows, esse valor deve ser um ponteiro para o buffer que contem os dados a serem decriptados. Depois que a decriptacao eh realizada, o plain text eh colocado nesse buffer ) pbwDataLen = pbwDataLen (Eh o valor daquele calculo doido que eu nao entendi direito com o tamanho da stringona maior. Segundo a API, isso eh o tamanho do buffer a ser decriptado, que no caso ja vimos que eh 846). Entao eh isso. Essa eh a minha "nao-solucao". Nao cheguei a entender completamente (na vdd acho que n entendi foi nada kkkk) o motivo dessa stringona, seria ela apenas uma tecnica de defense-evasion ou ela tem mais algum outro motivo que eu nao consegui captar? Ajuda o maluco que ta doente aki kkkkk Atualizacao: Aparentemente 846 eh o tamando da stream de bytes que representa a stringona decodada. Entao parece justo eu assumir que esse calcula na verdade eh uma otimizacao do compilador ou o ghidra nao conseguiu interpretar isso como uma chamada de funcao? Ou talvez realmente seja algum tipo de calculo que ja existe, vou dar uma pesquisada sobre
  3. Faz tempo que eu vi o CERO, to aproveitando o tempo livre da quarentena pra re-assistir kkkkkk. Mas eu acho que fala sim, se eu nao me engano foi no seu video que aprendi sobre isso pela primeira vez, dai eu fui dar uma pesquisada sobre, mas faz tempo tambem, esses ultimos semestres foram foda, tive que focar quase que 100% na facul e deixei isso de lado, dai to voltando aos poucos. Esse cara aqui da um gas legal nessa parte de linkadores se vc tiver interessado (acho que sao 20 posts): https://www.airs.com/blog/archives/38 Vou dar uma olhada nesse livro tambem, vlw irmao! Eh noissss, manda muito
  4. Muito boa a explicacao, deu pra dar uma clareada absurda. Soh mais algumas duvidas: Pq a .got.plt precisa da permissao de escrita, alem da leitura? Seria por causa da relocacao em runtime, ou eu to viajando? Bixo, esse arquivo parece mto interessante, vou pesquisar sobre ele, parece o tipo de coisa que eu preciso saber sobre. Tem alguma leitura que vc possa me direcionar sobre ele? mto obg, mano, ajudou bagarai!!
  5. Opa! To atrasado aqui mano, mas eu nao sei se eu to viajando, mas qual a diferenca entre o layout da memoria virtual de um executavel e as secoes ELF? Eles parecem ser 2 coisas diferentes, mas parecem ser muito similares. Eu to viajando?
  6. Ola, eu recentemente comecei a me embananar com certos conceitos. Por exemplo, eu sei (acho que sei pelo menos) que todo processo tem uma memoria virtual, e a o layout dessa memoria virtual eh dividido em nos segmentos data, bss, stack, heap, etc... Mas um arquivo ELF tambem eh divido em secoes. E algumas secoes tem o mesmo nome dos segmentos da memoria virtual (.data, .text, etc). No post tem duas imagens uma com o layout da memoria e outro representando as ELF sections Minhas duvidas: Qual a diferenca entre os segmentos da memoria virtual e as secoes de um arquivo ELF? As secoes que tem o mesmo nome sao na vdd as mesmas? Eles se complementam? Na imagem da memoria, a gnt ve que tem espacos nao alocados. As ELF section sao carregadas neles? Obg desde ja!
  7. Opa, cara, valeu pela resposta, admiro muito seu trabalho! Eu comentei no video que vc postou sobre o curso de analise de malware, que se tudo der certo esse ano eu comeco um projeto na facul e vou ganhar bolsa, e certamente vou me tornar um apoiador! Acho que ta na hora de eu passar pra analise dinamica entao! Mto obrigado cara, vc eh foda, juro q ate hj nunca achei nenhum conteudo igual a de vcs, vcs tem meu eterno respeito, serio!
  8. Ola, estou tentando resolver um crackme, e nele existe uma funcao que compara um valor de um vetor que esta contigo na secao .data. Queria saber se ha algum modo de: Coletar o conteudo desse vetor sem precisar esperar o loop rodar ate o final, ja que o loop demora para terminar Caso eu consiga coletar o conteudo desse vetor, identificar o tipo dele com correteza Caso eu consiga identificar o tipo dele, como eu faco para o Ghidra passar a identificar ele pelo tipo correto? Obs: O vetor eh uma variavel global, entao ele nao eh passado na stack, por isso que eu sei que ele esta na secao .data, segue o print da funcao em questao Obs2: Pelo modo que o Ghidra esta manipulando esse vetor, eu imagino que ele seja de inteiros (ele converte ele em um ponteiro e e pega o conteudo dele, alem de trabalhar com 4 bytes, e o arquivo eh 64 bits, entao me parece um chute plausivel), mas como saber se estou correto?
×
×
  • Create New...