FORUM DARKERS

Tecnologia & Informática => Programação => C/C#/C++ => Topic started by: blackwinner on 20 de July , 2008, 07:39:23 PM

Title: A hora que o bicho pega!
Post by: blackwinner on 20 de July , 2008, 07:39:23 PM
Hoje resolvi fazer um tuto bem pequeno sobre "A hora que o bicho pega!". lolz =P
Essa hora acontece para um programador C/C++, não quando quebram o seu software, mas quando você mesmo o faz!

Vamos falar de uma forma muito comum e dúbia em que muitos programadores caem e não sabem o que está acontecendo.. essa forma é o tratamento de unsigned int's como int's comuns.

Vamos entender através de um código bem simples:
#include <windows.h>
#include <stdlib.h>

#define Error_Msg(txt) MessageBox(0,txt,"Error",MB_ICONERROR)
#define Pause system("pause > nul")


int main()
{
 int iNum = -48;
 unsigned int nNum2 = 48;

 if(iNum > nNum2)
  Error_Msg("Verifique se a sentença acima esta correta..");
 
 
 
 Pause;
}

Segundo o que conhecemos de matemática, é óbvio que "-48" é bem menor do que "48", no entanto a diretiva if não concorda com isso.
É exatamente o que você está pensando, enquanto tratarmos tipos diferentes em uma mesma sentença matemática, um dos dois será convertido.
Nesse caso, o nosso int -48, vira 0xFFFFFFD0.

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

#define Error_Msg(txt) MessageBox(0,txt,"Error",MB_ICONERROR)
#define Pause system("pause > nul")


int main()
{
 int iNum = -48;
 unsigned int nNum2 = 48;

 if(iNum > nNum2)
  Error_Msg("Verifique se a sentença acima esta correta..");
 
 printf("valor de iNum apos a conversao: %u\nEm Hexa: %x", iNum, iNum);
 Pause;
}

Se você quiser que o código de certo, você terá que usar um cast no nNum2.
Bem, não vou me prender a isso, mais tarde talvez eu me prenda a explicar como e porque os certos bugs ocorrem..

Vamos a um exemplo desse pequeno erro que resulta num overflow de proporções bíblicas..


#include <windows.h>
#include <stdlib.h>
#include <string>
#include <iostream>

#define Error_Msg(txt) MessageBox(0,txt,"Error",MB_ICONERROR)
#define Pause system("pause > nul")

using namespace std;

int main()
{
 HGLOBAL hGlobal;   
 string m_Str;   
 
 cout << "Digite uma string: ";
 cin >> m_Str;
 
 hGlobal = GlobalAlloc(0x0040,m_Str.size());
 memset(hGlobal, 'M', m_Str.size()-2);
 
 cout << 4[(char*)hGlobal];
 
 GlobalFree(hGlobal);
 Pause;
}

Esse é um exemplo bem chulo mas que serve as nossas necessidades.

N'ele nós tentamos alocar uma nova string com vários M's, que terá  dois caracteres a menos que a primeira..

memset(hGlobal, 'M', m_Str.size()-2);
Se o usuário fornece menos de 2 caracteres na string, o programa quebra já que memset converte o valor resultante em um unsigned o que gera um overflow enorme.. isso geralmente acontece através da chamada de memcpy, mas eu resolvi ilustrar com memset só para fugir dos padrões.. mas normalmente acontece quando o programador tenta transferir a string digitada pelo usuário para uma Cstring através de memcpy, CopyMemory e la vai o trem.

Se o usuário tem o controle da primeira string tratada por memcpy, então é um possível buffer overflow surgindo no seu código.. e tudo, graças a você. =P

Bem pequenininho como eu prometi.. =]

PS: isso é apenas um pequeno exemplo de como o código pode quebrar, use sua imaginação porque isso ocorre de várias formas muito parecidas.. eu recomendo a leitura de "Writing Secure Code"¹ bem como "Software fault injection: inoculating software against errors", "How to break software" entre outros.. cya

¹:http://www.microsoft.com/mspress/books/5957.aspx