Localhost Posted December 30, 2009 at 12:37 PM Report Share #303174 Posted December 30, 2009 at 12:37 PM Olá pessoal, resolvi então escrever mais alguma coisa aqui no forúm, escolhi então que desta vez fosse sobre buffer overflow. Visto que pode causar grandes problemas se existir a possibilidade de existir eu venho aqui explicar o que ele é e como se pode evitá-lo. Este texto é 100 % da minha autoria. Vamos lá começar então. O que é o buffer overflow? Buffer overflow é o facto de se passarem os limites do buffer, o buffer é a região de memória onde são lidos e escritos dados como strings por exemplo. Como vocês sabem as strings não são mais do que vectores de elementos de 1byte, os chamados chars ou caracteres. O que o buffer overflow faz ou é, melhor dizendo, é passar os limites desse buffer atingindo assim outras zonas da memória. Agora a pergunta que fica no ar é, o que é que isso tem de perigoso e que zonas é que são "atingidas"? Vamos ver isso a seguir. O que é o/a stack? O ou A, stack é o local da memória onde são guardados dados temporários como as variáveis locais, é também o que o computador utiliza para entradas e saída de dados rápidas. É também na/no stack que são guardadas as strings. O que têm de saber da/do stack é que nele/nela, quando é chamada uma função no vosso programa, é criado um stack frame (imaginem o stack frame como uma divisão do/da stack, quando temos várias funções são criados vários stack frame(s)). Ora bem, nesse stack frame vai ser onde vão ser armazenadas todas as variáveis da função e também um endereço, um endereço muito especial, o chamado, endereço de retorno. O que é o endereço de retorno? Quando chamamos uma função então é criado um stack frame, agora imaginem na vossa mente o stack frame, agora imaginem como é que no final da função o programa sabia por onde prosseguir a execução? Então para isso existe o endereço de retorno, ele contêm o endereço da próxima instrução de onde foi chamada a função. Para perceberem melhor, vou pôr aqui um código: #include <stdio.h> int main(void){ char string[8]; gets(string); //Ainda vamos falar muito desta função. printf("%s\n", string); return (0); } Vamos perceber o programa, declaramos uma string de 8bytes, e depois chamamos a função gets, ora bem, no stack frame da função gets é criado as suas variáveis locais e também um endereço de retorno que contêm o endereço da próxima instrução do programa que neste caso é a função printf. Tentem imaginar isto como quando vamos fazer uma caminhada, pomos as pedras no caminho para não nos perdermos, digamos que a pedras são o endereço de retorno para o caminho principal. Então como ocorre o buffer overflow? Ora bem, quando nós passamos os limites do buffer a verdade é que tudo o que está "ao lado" dele vai entrar em contacto com os dados que passaram fora da string (no caso). Na verdade o buffer overflow é só isso, o "transboradamento", como o nome diz de dados pelo buffer fora. No entanto, ao lado do buffer muitas vezes está o endereço de retorno, e é aí que se tenta explorar, imaginem que se meta lixo até preencher o buffer e depois de se preencher, estando já em contacto com o endereço de retorno se coloque lá outro endereço, por exemplo um endereço para uma função maliciosa. Na verdade eu não estou aqui para vos explicar como explorar mas o que as pessoas mal intencionadas fazem não é meter um endereço mas sim uma coisa chamada de shellcode (procurem sobre isso no google). Para provar que é sobreescrito tudo que estiver ao lado do buffer (se forem passados os limites) compilem e executem este código: #include <stdio.h> int main(void){ char s_1[8], s_2[8], s_3[8]; gets(s_1); gets(s_2); gets(s_3); printf("%s\n%s\n%s\n", s_1, s_2, s_3); return 0; } E agora passem os limites da segunda string ou da primeira, neste caso não vamos estar em contacto com o endereço de retorno mas sim com a string que está a seguir dependendo da que quiserem, vejam então o output e tentem perceber o que aconteceu. Nota: Se estiverem em Linux vai dar um segmentation fault, não podendo assim verem o output, que é o meu caso. Como se proteger? Finalmente chegamos à parte da protecção, como nos podemos proteger disto tudo? É simples, usamos funções que verifiquem se a string do input é maior do que aquela que a vai receber. Vou introduzir uma lista a seguir então de funções vulneráveis e das que não são vulneráveis, relativamente a essas. Funções - Lista (ex: Função_vulnerável - Função segura) - gets - fgets; - strcpy - strncpy - strcat - strncat - scanf(strings) - fgets Lista - O porquê de serem vulneráveis - gets - A função gets, recebe um input e presupõe que o input nunca seja maior que o buffer que a vai receber. - strcpy - A função strcpy presupõe que a string destino tenha capacidade para comportar a string origem. - strcat - A função strcat presupõe que a string que a vai receber tem ainda capacidade para comportar a string que vai ser copiada - scanf(se não forem incluídas restrições) - A função scanf tem as mesmas caracteristicas que a gets no caso de estarmos a ler strings. Não confundam com inteiros e outro tipos de dados. Bem, estas são apenas algumas funções, muito poucas aliás mas já dá para ter uma ideia por isso sempre que utilizarem uma nova função pesquisem sobre ela. Bem decidi editar aqui para pôr uma imagem para melhor compreensão, afinal uma imagem vale mais do que mil palavras. Por hoje foi tudo, espero que tenham gostado. Até à próxima. B) here since 2009 Link to comment Share on other sites More sharing options...
Quadrado Posted December 30, 2009 at 12:57 PM Report Share #303180 Posted December 30, 2009 at 12:57 PM Está muito bom, quando andei a estudar esta parte os manuais/livros/tutoriais que utilizei diziam muita coisa mas explicavam pouca, porque para pessoas que estão a iniciar não interessam ainda coisas complicadas, deu para aprender mas uma coisa que facilmente se aprende em 30 minutos com tal excesso de material desnecessário uma pessoa demoraria 1 ou 2 horas, em relação a esta matéria só 3 ou 4 manuais depois é que achei um com uma explicação para isto tão rápida e concisa como esta... Muito bem... B) Será? Porquê? O quê? - Estudar Sempre - Link to comment Share on other sites More sharing options...
Localhost Posted December 30, 2009 at 01:04 PM Author Report Share #303181 Posted December 30, 2009 at 01:04 PM Obrigado B) here since 2009 Link to comment Share on other sites More sharing options...
skin Posted December 30, 2009 at 04:02 PM Report Share #303223 Posted December 30, 2009 at 04:02 PM Eu gostei B) Our lives begin to end the day we become silent about things that matter - Martin Luther King Link to comment Share on other sites More sharing options...
Localhost Posted December 30, 2009 at 04:09 PM Author Report Share #303224 Posted December 30, 2009 at 04:09 PM Obrigado, achas que devo melhorar alguma coisa? here since 2009 Link to comment Share on other sites More sharing options...
Baderous Posted December 30, 2009 at 05:00 PM Report Share #303237 Posted December 30, 2009 at 05:00 PM É na/no stack que são guardadas as strings. Todas as strings que são variáveis locais cujo valor não é hard-coded. As strings criadas dinamicamente residem na Heap, as strings literais (escritas pelo programador no código) que são variáveis globais e que são inicializadas como char[] str = "cenas" ficam no Data e as strings (locais ou globais) inicializadas como char * str = "cenas" ficam no Rodata. - scanf - A função scanf tem as mesmas caracteristicas que a gets no caso de estarmos a ler strings. Não confundam com inteiros e outro tipos de dados. A função scanf pode ser usada seguramente com strings, indicando o nº máximo de caracteres a ler, tal como a fgets. Link to comment Share on other sites More sharing options...
Localhost Posted December 30, 2009 at 05:14 PM Author Report Share #303242 Posted December 30, 2009 at 05:14 PM Baderous, o que eu queria dizer na primeira parte era que também são guardadas as strings no/na stack e não que são apenas guardados no/na stack. No segundo não conheço isso, podes-me dar um exemplo? here since 2009 Link to comment Share on other sites More sharing options...
Baderous Posted December 30, 2009 at 05:35 PM Report Share #303253 Posted December 30, 2009 at 05:35 PM scanf("%80[^\n]",str); ////lê no máximo 80 caracteres para uma string ou, caso o input seja menor que 80, lê até encontrar um '\n' que indica mudança de linha Link to comment Share on other sites More sharing options...
Localhost Posted December 30, 2009 at 05:44 PM Author Report Share #303255 Posted December 30, 2009 at 05:44 PM Ah, e também inclui o \n na string? here since 2009 Link to comment Share on other sites More sharing options...
Baderous Posted December 30, 2009 at 05:57 PM Report Share #303260 Posted December 30, 2009 at 05:57 PM Não. Link to comment Share on other sites More sharing options...
Localhost Posted December 30, 2009 at 06:18 PM Author Report Share #303266 Posted December 30, 2009 at 06:18 PM Então ainda é melhor que o fgets (: here since 2009 Link to comment Share on other sites More sharing options...
ruimike Posted August 7, 2011 at 05:44 PM Report Share #406648 Posted August 7, 2011 at 05:44 PM Muito bom este post 😁 Link to comment Share on other sites More sharing options...
mundo Posted August 7, 2011 at 10:15 PM Report Share #406694 Posted August 7, 2011 at 10:15 PM Muito bom este tutorial, foi uma das coisas que me foi dificil entrar na cabeça nas aulas de C xD Link to comment Share on other sites More sharing options...
AlexPnt Posted August 15, 2011 at 08:35 AM Report Share #407881 Posted August 15, 2011 at 08:35 AM Bom post 😛 Programming is an art form that fights back. Link to comment Share on other sites More sharing options...
Diiml_C Posted August 24, 2011 at 09:27 PM Report Share #409082 Posted August 24, 2011 at 09:27 PM Muito bom este post ! Obrigado Localhost 😉 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now