Friday, 14 July 2017

0x72 Binary Options


Eu estava recentemente procurando uma maneira de enviar uma imagem com um executável sem se referir à imagem como arquivo externo. Agora você pode argumentar se é uma boa idéia em geral, mas essa é outra história. Uma vez que eu encontrei muito pouca informação sobre o assunto e necessário reunir informações de várias fontes, concluo a tarefa com esta abrangente escrever sobre o assunto. Os mecanismos descritos aqui se aplicam à inclusão de qualquer recurso - não apenas imagens - em um programa c executável. Há várias maneiras de incorporar dados fixos genéricos dentro de um aplicativo. Let039s começar com um exemplo básico que deve ser familiar: Cada aplicativo é apenas uma coleção de segmentos de dados armazenados em um arquivo. Na arquitetura moderna do PC, cada binário de aplicativos consiste em três grandes segmentos de pilha. Dados e Código. Sem entrar em detalhes, os dados fixos - tais como seqüências de texto constantes residem na parte somente leitura do Segmento de Dados do binário do aplicativo e o compilador-c criará automaticamente uma região de memória para ele. Quando você compila a linha acima com gcc - c - o mytext. o mytext. c e inspeciona o arquivo de objeto com objdump - t mytext. o you039ll encontra a seção de dados no arquivo de objeto. Que basicamente diz: mystring039 é um objeto de texto global (g) somente leitura (O) e pode ser encontrado no deslocamento 0x00 no arquivo de objeto. Para uma descrição detalhada de todos os valores veja man objdump. Agora uma solução seria simplesmente escrever o código em c e ter o compilador cuidar de tudo usando Para codificar os dados de um dado arquivo, a ferramenta xxd que vem com o editor de texto vim pode ser usada: xxd - i saídas de arquivo binário C inclui o estilo de arquivo do arquivo binário fornecido e grava uma definição de matriz estática completa com o nome do arquivo de entrada: Usando esta variante produz código C portátil e apenas works (TM). No lado negativo, requer pelo menos cinco vezes o tamanho dos dados originais (0xNN, para cada byte de dados original) e o código-fonte precisa ser atualizado sempre que os dados originais são alterados. Embora essa abordagem seja útil em alguns casos, podemos fazer melhor do que isso. O vinculador GNU pode ser usado para criar diretamente arquivos de objetos com uma seção customizada. data diretamente de qualquer arquivo de entrada. Os sinalizadores / magic / são - r para tornar o arquivo de objeto realocável e - b binário para vincular arquivos com um formato binário incomum. O exemplo de arquivo de objeto resultante pode ser vinculado a qualquer aplicativo, simplesmente com o próprio gcc. por exemplo. Gcc - o myapp myapp. c example. o. Agora o último link ausente é acessar os dados no example. o do c-code em myapp. c. Dê uma olhada na saída do objeto e compare com a saída acima para o objeto mystring. A parte gt. data ltnamegt deve tocar um sino. Esta seção de dados pode ser referenciada a partir do código C simplesmente usando: e o comprimento pode ser calculado a partir de ou simplesmente fazendo referência ao endereço de binárioexamplejpgsize. O vinculador resolverá a referência externa ao vincular o aplicativo ea aplicação usará os dados exatamente como um blob fixo no código-fonte. Agora para a parte complicada: O vinculador GNU comporta-se diferentemente dependendo da plataforma e da arquitetura. As implementações interessantes para mim são GNU / Linux, OSX e mingw (compilação cruzada de binários de janelas em um host GNU / Linux). O mingw cross-compiler se comporta quase exatamente como gnu-ld com uma pequena diferença: a seção de dados não inclui o sublinhado principal: binaryexamplejpgstart vs binaryexamplejpgstart. Bem, lá vai um pouco da elegância da solução, mas esse caso é facilmente manipulado com um ifdef. No entanto, o Mac / OSX é diferente. O ld que é fornecido com X-code vem da versão llvm 2.7svn e não suporta o recurso de formato de entrada - b. Além disso executáveis ​​universais em OSX podem incluir formatos binários para várias arquiteturas com o formato de seção. data sendo diferente para cada arquitetura. O alinhamento para os dados pode ser diferente entre as arquiteturas de 32 bits e 64 bits ea endianess pode diferir também. Assim, a criação da seção de dados precisa ser feita durante a compilação em vez da fase de ligação. No recurso OSX ld039s linking binário foi movido para o seu gcc personalizado, e está disponível via 039-sectcreate039 opção: Para criar uma compilação universal para arquiteturas Intel, adicione - arch i386 - arch x8664 para acima commandline. Objdump é também uma ferramenta GNU que não está disponível no OSX. Você pode inspecionar a seção de dados usando otool - s DATA examplejpg / path / to / executável. Ver homem otool para detalhes. Devido à natureza dos binários OSX, referenciar a seção de dados no c-code não é possível com um caractere não-assinado externo simples. O vinculador não sabe qual arquitetura será usada e não pode fornecer um endereço. O formato bin mach utilizado pelo OSX precisa ser inspecionado em tempo de execução quando a arquitetura é conhecida e mapear os dados relevantes após o início do aplicativo. A Apple fornece uma API para fazer o que é definido no arquivo de cabeçalho mach-o / getsect. h. Se você tiver x-code instalado você pode ler a documentação sobre ele em man getsectbyname. Resolver o secion só pode ser feito em tempo de execução depois que a seção de dados foi realocada e pode feito chamando getsectbyname (). No entanto, há um truque que você pode usar, para fazer isso implícito. A seção meta-variável é reconhecida pelo compilador gcc no OSX. Ele produz o mesmo resultado como chamar getsectbyname () addr. Curto de ler o código real, a informação sobre internos do ligador do osx não é fácil vir perto. Getsectbyname () realmente abre o arquivo executável e pesquisa a seção de dados relevantes enquanto o aplicativo está sendo executado. Seção pode ou não pode já ser resolvido em tempo de ligação para uma determinada arquitetura 1). Update (Oct 2016 - Obrigado a Eugene Gershnik): Em versões mais recentes do OSX / macOS que executam executáveis ​​com ASLR. A chamada para getsectbyname precisa ser substituída por getsectiondata 2). No entanto, esta API só está disponível a partir do OS 10.7. Longa história curta, pode-se usar uma abstração macro que funciona x-plataforma. Para acessar os dados e tamanho LDVAR () e LDLEN () são definidos, para a definição externa real do símbolo, EXTLD () é usado: Exemplo de uso em um programa C: Como uma nota final, alguns cuidados devem ser tomados ao escolher O identificador da variável. Ld usará o nome do arquivo para gerar o nome da seção. Se o nome do arquivo incluir caracteres que não são identificadores C válidos, eles serão transformados em sublinhados. por exemplo. Ld - r - b binário - o exemplo. o. /images/example. jpg criará uma região binaryimagesexamplejpg. O. / Assim como a barra eo ponto são transformados em sublinhados. Isso não é um problema no OSX onde o identificador precisa ser especificado com a opção - sectcreate. No entanto, os identificadores no OSX estão limitados a 16 caracteres. Portanto, para usar acima da abordagem x-platform, o caminho para o nome do arquivo passado para ld deve ser lt16 chars eo mesmo identificador precisa ser especificado no comando de compilação OSX. Um projeto completo que usa essa abordagem para incluir um arquivo de imagem jpeg e um arquivo de texto javascript é harvid. Ele também descreve como usar um x-platform Makefile para criar os arquivos de objeto e adicionando os sinalizadores relevantes para o comando OSX gcc. 1) você deve saber mais sobre isso ou ter quaisquer ponteiros para a documentação, entre em contato comigo

No comments:

Post a Comment