• Sign in
 

LATAM Team blog

Search Blogs
Tags
  • Cloud
  • Cluster
  • Crash
  • Desarrollo
  • Desenvolvimento
  • Directory Services
  • DST
  • Español
  • Exchange/Outlook
  • Hang
  • High Availability
  • IIS
  • Networking
  • Office
  • People
  • Performance
  • Português
  • PowerShell Scripts
  • Security
  • Setup
  • Sharepoint
  • SQL
  • Virtualization
  • Windbg Scripts
  • Windows
Blog - News

Where Are You Coming From Today?

Where are you now?

Follow us on:

Options
  • Blog Home
  • About
  • Share this
  • RSS for posts
  • Atom
  • RSS for comments
Archive
Archives
  • May 2013 (4)
  • April 2013 (5)
  • March 2013 (6)
  • February 2013 (3)
  • January 2013 (3)
  • December 2012 (2)
  • November 2012 (1)
  • October 2012 (4)
  • September 2012 (5)
  • August 2012 (2)
  • July 2012 (2)
  • June 2012 (3)
  • May 2012 (13)
  • April 2012 (6)
  • March 2012 (6)
  • February 2012 (4)
  • January 2012 (7)
  • December 2011 (11)
  • October 2011 (6)
  • September 2011 (1)
  • August 2011 (3)
  • July 2011 (7)
  • June 2011 (6)
  • May 2011 (5)
  • April 2011 (2)
  • March 2011 (13)
  • February 2011 (1)
  • January 2011 (5)
  • December 2010 (6)
  • November 2010 (1)
  • October 2010 (6)
  • September 2010 (2)
  • August 2010 (3)
  • July 2010 (3)
  • June 2010 (5)
  • May 2010 (1)
  • April 2010 (10)
  • March 2010 (21)
  • February 2010 (8)
  • January 2010 (3)
  • December 2009 (5)
  • November 2009 (5)
  • October 2009 (6)
  • September 2009 (8)
  • August 2009 (9)
  • July 2009 (1)
  • June 2009 (3)
  • May 2009 (2)
  • April 2009 (7)
  • March 2009 (4)
  • February 2009 (7)
  • January 2009 (7)
  • December 2008 (8)
  • November 2008 (7)
  • October 2008 (22)
  • September 2008 (17)
  • August 2008 (13)
  • July 2008 (11)
  • June 2008 (7)
  • May 2008 (3)
  • April 2008 (2)
  • March 2008 (6)
  • January 2008 (4)
  • December 2007 (9)
  • November 2007 (4)
  • October 2007 (3)
  • September 2007 (8)
  • August 2007 (4)
  • July 2007 (2)
  • June 2007 (5)
  • May 2007 (7)
  • April 2007 (9)
  • March 2007 (7)
  • February 2007 (6)
  • January 2007 (4)
  • December 2006 (14)
  • November 2006 (10)
  • October 2006 (10)
  • September 2006 (11)
  • August 2006 (15)
  • July 2006 (7)
  • June 2006 (14)
  • May 2006 (22)
  • April 2006 (16)
  • March 2006 (20)
  • January 2006 (1)

Resposta ao Desafio da Semana #8 [Crash - Buffer Overflow em C/C++]

TechNet Blogs > LATAM Team blog > Resposta ao Desafio da Semana #8 [Crash - Buffer Overflow em C/C++]

Resposta ao Desafio da Semana #8 [Crash - Buffer Overflow em C/C++]

LatamBlog
24 Jul 2006 2:25 PM
  • Comments 2

Por: Roberto Alexis Farah

 

Olá!

Eis o link para o Desafio: http://blogs.technet.com/latam/archive/2006/07/14/441892.aspx

 

Agora vamos a resposta...

 

Esse é um bug bastante difícil de se identificar e extremamente nocivo pois o sintoma nem sempre é um crash de aplicação! Além disso, bugs desse gênero, caracterizados como buffer overflow, podem ser explorados, por exemplo, através de shellcodes.

 

<SOBRE A COMPLEXIDADE DOS DESAFIOS>

 

Conforme venho fazendo nos desafios, o problema dessa vez também é bastante simples, embora não necessariamente fácil de se achar a primeira vista.

Os problemas simples que passam despercebido por desenvolvimento e testes se tornam problemas difíceis de serem isolados quando a aplicação está finalizada e rodando. E, por incrível que pareça, a causa raiz de complexos incidentes que nos chegam, na grande maioria das vezes são problemas simples que passaram despercebidos no início! Essa é a maior motivação pela qual insisto em colocar desafios que são simples. A beleza deles está na simplicidade! Embora simples eles continuam a ocorrer frequentemente.

 

Isolar um problema simples escondido no meio de um enorme sistema é algo complexo. Como sempre digo, a solução costuma ser a parte mais simples e isolar o problema em si é a parte mais complicada.

 

Imaginem, no caso desse desafio #8, se o problema tivesse, como numa situação real, escondido sob milhares de linhas de código fonte!

 

</SOBRE A COMPLEXIDADE DOS DESAFIOS>

 

Shellcodes são códigos de máquina usados para explorar um bug de software, de modo a permitir que um usuário não autorizado possa ter acesso ao computador. Para aqueles que desejam saber mais colocarei uma bibliografia ao final do artigo.

 

 

PROBLEMA

 

O problema ocasionando o intermitente sintoma de Crash é um buffer overflow. Ele é ocasionado sempre que o parâmetro que representa a quantidade de strings for negativo.

 

Exemplo:

 

App.exe -60 “aadlfhsfsjdhsjkhjskhggkhjghaghdjghdsjghjsgsdghghsdghdsjghdsjghdsjghdsghsdjk”

 

O que ocorre aqui é bastante interessante.

Um número negativo é menor que o tamanho do buffer interno da aplicação, logo, pela lógica da mesma, ela considera esse valor como válido.

Entretanto, na chamada de memcpy() temos:

 

void *memcpy( void *dest, const void *src, size_t count );

 

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_crt_memcpy.asp

 

O terceiro parâmetro vai tratar o valor negativo como um unsigned, ou seja, um tipo que não aceita números negativos, portanto, o número negativo se tornará um enorme número positivo!

Sendo um grande número positivo, memcpy() vai sobreescrever a área reservada para o buffer interno, que, no caso, é de 10 bytes.

Dependendo da sobreposição dessa área poderemos ter um crash de aplicação!

 

Eis o que ocorre na prática, usando o Visual C++ 6.0 e o Visual Studio 2005. Depurei a aplicação compilada como Debug para ficar mais fácil visualizar o problema.

 

Versão compilada com Visual C++ 6.0:

 

0012ff70  cccccccc cccccccc cccccccc ffffffc4        ß 0xCCCCCCCC representa a memória não inicializada de cBuffer em modo Debug.

0012ff80  0012ffc0 00401809 00000003 00321190    ß Endereço da pilha em vermelho.

0012ff90  00321258 00011970 7c9118f1 7ffdf000

0012ffa0  00000001 00000001 0012ff94 afe75d08

0012ffb0  0012ffe0 004048d0 00422180 00000000

0012ffc0  0012fff0 7c816d4f 00011970 7c9118f1

0012ffd0  7ffdf000 8054a6ed 0012ffc8 88e8c790

0012ffe0  ffffffff 7c8399f3 7c816d58 00000000

 

 

ChildEBP RetAddr                                             ß Pilha durante execução.

0012ff80 00401809 BUG1!main+0x29

0012ffc0 7c816d4f BUG1!mainCRTStartup+0xe9

0012fff0 00000000 kernel32!BaseProcessStart+0x23

 

Após algumas execuções:

 

0012ff70  73676466 73646764 73736467 67736664    ß Passou a área do buffer e sobreescreveu pilha...

0012ff80  67736467 00401809 00000003 00321190

0012ff90  00321258 00011970 7c9118f1 7ffdf000

0012ffa0  00000001 00000001 0012ff94 afe75d08

0012ffb0  0012ffe0 004048d0 00422180 00000000

0012ffc0  0012fff0 7c816d4f 00011970 7c9118f1

0012ffd0  7ffdf000 8054a6ed 0012ffc8 88e8c790

0012ffe0  ffffffff 7c8399f3 7c816d58 00000000

 

 

Versão compilada com Visual Studio 2005:

 

 

0012ff48  cccccccc cccccccc cccccccc cccccccc           ß Área de buffer de cBuffer.

0012ff58  cccccccc 00000000 cccccccc 3574e29d

0012ff68  0012ffb8 00411a36 00000003 00352650

0012ff78  00353288 3574e24d 00011970 7c9118f1

0012ff88  7ffde000 b25fe8f0 00000000 00000000

0012ff98  00130000 00000000 0012ff7c 0000431a

0012ffa8  0012ffe0 0041107d 3527742d 00000000

0012ffb8  0012ffc0 0041187d 0012fff0 7c816d4f

 

ChildEBP RetAddr                                                      ß Início da execução...

0012ff68 00411a36 Bug!main+0x39

0012ffb8 0041187d Bug!__tmainCRTStartup+0x1a6

0012ffc0 7c816d4f Bug!mainCRTStartup+0xd

0012fff0 00000000 kernel32!BaseProcessStart+0x23

 

 

Apos algumas execuções temos:

 

0012ff48  4f535349 20274520 54204d55 45545345        ß Reparem no buffer overflow!

0012ff58  54202d20 41545345 214f444e fdfdfd00

0012ff68  abababfd abababab 00000003 00352650

0012ff78  00353288 3574e24d 00011970 7c9118f1

0012ff88  7ffde000 b25fe8f0 00000000 00000000

0012ff98  00130000 00000000 0012ff7c 0000431a

0012ffa8  0012ffe0 0041107d 3527742d 00000000

0012ffb8  0012ffc0 0041187d 0012fff0 7c816d4f

 

 

ChildEBP RetAddr                                                

0012fe04 10233732 MSVCR80D!fastcopy_I+0x41

0012fe34 10233794 MSVCR80D!_VEC_memcpy+0x52

0012fe64 0041140f MSVCR80D!_VEC_memcpy+0xb4

0012fe04 10233732 Bug!main+0x6f

0012fe34 10233794 MSVCR80D!_VEC_memcpy+0x52

0012fe64 0041140f MSVCR80D!_VEC_memcpy+0xb4

0012fe34 10233794 Bug!main+0x6f

0012fe64 0041140f MSVCR80D!_VEC_memcpy+0xb4

0012fe64 0041140f Bug!main+0x6f

0012ff68 abababab Bug!main+0x6f                ß Pilha sendo corrompida!

0012ff80 7c9118f1 0xabababab                     ß Pilha sendo corrompida!

00011970 00000000 ntdll!RtlDeleteCriticalSection+0x72   ß Pilha sendo corrompida!

 

 

 

Em seguida temos uma exceção gerada após sobreescrever boa parte da pilha:

 

eax=0012ff50 ebx=003526b0 ecx=01fffffe edx=00000000 esi=00352730 edi=0012ffd0

eip=10233811 esp=0012fdfc ebp=0012fe04 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202

MSVCR80D!fastcopy_I+0x41:

10233811 660f7f5f30      movdqa  xmmword ptr [edi+30h],xmm3 ds:0023:00130000=00002498000000010000002078746341

 

 

E olhem a área de buffer da variável cBuffer após exceção:

 

0012ff48  4f535349 20274520 54204d55 45545345        ß Lindo né, gente? J

0012ff58  54202d20 41545345 214f444e fdfdfd00

0012ff68  abababfd abababab feeefeab feeefeee

0012ff78  00000000 00000000 00170124 00ee04ee

0012ff88  00350178 00350178 feeefeee feeefeee

0012ff98  feeefeee feeefeee feeefeee feeefeee

0012ffa8  feeefeee feeefeee feeefeee feeefeee

0012ffb8  feeefeee feeefeee feeefeee feeefeee

 

E a pilha corrompida:

 

ChildEBP RetAddr 

0012fe04 10233732 MSVCR80D!fastcopy_I+0x41

0012fe34 10233794 MSVCR80D!_VEC_memcpy+0x52

0012fe64 0041140f MSVCR80D!_VEC_memcpy+0xb4

0012fe04 10233732 Bug!main+0x6f

0012fe34 10233794 MSVCR80D!_VEC_memcpy+0x52

0012fe64 0041140f MSVCR80D!_VEC_memcpy+0xb4

0012fe34 10233794 Bug!main+0x6f

0012fe64 0041140f MSVCR80D!_VEC_memcpy+0xb4

0012fe64 0041140f Bug!main+0x6f

0012ff68 abababab Bug!main+0x6f

0012ff74 00000000 0xabababab

 

Detalhes da exceção:

 

ExceptionAddress: 10233811 (MSVCR80D!fastcopy_I+0x00000041)

   ExceptionCode: c0000005 (Access violation)

  ExceptionFlags: 00000000

NumberParameters: 2

   Parameter[0]: 00000001

   Parameter[1]: 00130000                       ß Repare nesse endereço lá em cima onde há o dump de cBuffer.

Attempt to write to address 00130000

 

 

Eis o endereço:

 

    00130000 : 00130000 - 00003000

                    Type     00040000 MEM_MAPPED

                    Protect  00000002 PAGE_READONLY

                    State    00001000 MEM_COMMIT

                    Usage    RegionUsageIsVAD

 

 

Agora olhem o endereço do buffer 'cBuffer'

 

    00030000 : 00126000 - 0000a000

                    Type     00020000 MEM_PRIVATE

                    Protect  00000004 PAGE_READWRITE

                    State    00001000 MEM_COMMIT

                    Usage    RegionUsageStack

                    Pid.Tid  1278.11d4

 

A aplicação foi sobreescrevendo a pilha até alcançar um endereço sem permissão para escrita. Entretanto, uma corrupção de pilha poderia fazer algo diferente, como apenas alterar o valor da próxima variável local. Logo, o sintoma poderia ter sido outro e bem mais difícil de diagnosticar!

 

 

SOLUÇÃO

 

Eis duas possíveis soluções...

 

1-       Mudar o tipo da variável nLen para unsigned int, portanto, em caso de número negativo o mesmo será sempre 0:

 

int main(int argc, char* argv[])

{

        if(argc < 3)

        {

                return 0;

        }

       

        unsigned int nLen = 0;  // Mudando o tipo da variavel funciona.

 

       

        // Nao assumir string com NULL terminator.

        // Por isso usei 'cBuffer' ao inves de 'pszBuffer'.

        char cBuffer[BUFFER_SIZE]; 

       

        nLen = atoi(argv[1]);

       

        if(nLen < BUFFER_SIZE)

        {

                memcpy(cBuffer, argv[2], nLen);

        }

        else

        {

                printf("Muita informacao para copiar...\n");

        }

       

        return 0;

}

 

 

2- Fazer a verificação explícita de número negativo:

 

int main(int argc, char* argv[])

{

        if(argc < 3)

        {

                return 0;

        }

       

        int nLen = 0;

       

        // Nao assumir string com NULL terminator.

        // Por isso usei 'cBuffer' ao inves de 'pszBuffer'.

        char cBuffer[BUFFER_SIZE]; 

       

        nLen = atoi(argv[1]);

       

        if( (nLen >= 0) && (nLen < BUFFER_SIZE) )

        {

                memcpy(cBuffer, argv[2], nLen);

        }

        else

        {

                printf("Muita informacao para copiar...\n");

        }

       

        return 0;

}

 

 

 

Legal, né? Pois é, boa parte dos meus cabelhos grisalhos (e precoces) são decorrência de trabalhar em incidentes com esse tipo de problema. J

 

Eis ótimos livros sobre o assunto:

 

Writing Secure Code, Second Edition (Paperback)

http://www.amazon.com/gp/product/0735617228/sr=8-2/qid=1152664556/ref=sr_1_2/104-0455824-0491134?ie=UTF8

 

Secure Coding in C and C++ (SEI Series in Software Engineering) (Paperback)

http://www.amazon.com/gp/product/0321335724/sr=8-1/qid=1152664556/ref=pd_bbs_1/104-0455824-0491134?ie=UTF8

 

Buffer Overflow Attacks (Paperback)

http://www.amazon.com/gp/product/1932266674/qid=1152664641/sr=2-3/ref=pd_bbs_b_2_3/104-0455824-0491134?s=books&v=glance&n=283155

 

The Shellcoder's Handbook : Discovering and Exploiting Security Holes (Paperback)

http://www.amazon.com/gp/product/0764544683/qid=1152664641/sr=2-1/ref=pd_bbs_b_2_1/104-0455824-0491134?s=books&v=glance&n=283155

 

Shellcoder's Programming Uncovered (Uncovered series) (Paperback)

http://www.amazon.com/gp/product/193176946X/qid=1152664725/sr=1-6/ref=sr_1_6/104-0455824-0491134?s=books&v=glance&n=283155

 

 

Até o próximo desafio.

  • 2 Comments
Desenvolvimento , Crash
Comments
Comments
  • LatamBlog
    24 Jul 2006 3:25 PM
    Esse desafio foi massa! (como já dizia os meus amigos paulistas) :-)

    Joao@MS-LasColinas ;-)
  • Alexandre Albuquerque
    28 Jul 2006 10:32 PM
    Bom, parabens Roberto. Continue postando desafios  para que todos aprendam (de uma forma bem mais divertida que clareamento capilar).

    Nesse desafio é importante afirmar que olhando o problema com uma aplicação ou duas chamando a problemática não seria o fim do mundo, mas se tivermos uma aplicação importante que seja acessada diversas vezes, aí meu rapaz é olhar pro espelho e aguardar cabelos brancos e olheiras.

    Também é compreensível que desenvolvedores errem ao esquecerem dos números negativos (ou qualquer outro erro óbvio), os diretores querem rapidez, e pressionam de modo que ao invéz de ajudar atrapalham o processo! Logico que nem todos.

    Mas parabenizo a toda equipe da Microsoft pelo blog, e colocando oportunidades ao pessoal latino!

    Até o Desafio 9!
Page 1 of 1 (2 items)
  • © 2013 Microsoft Corporation.
  • Terms of Use
  • Trademarks
  • Privacy & Cookies
  • 5.6.426.415
  • TechNet
  • Products
  • IT Resources
  • Downloads
  • Training
  • Support
Products
  • Windows
  • Windows
    Server
  • System
    Center
  • Internet
    Explorer
 
  • Office
  • Office 365
  • Exchange
    Server
 
  • SQL Server
  • SharePoint
    Products
  • Lync
  • See all products »
Resources
  • Evaluation Center
  • Learning Resources
  • Microsoft IT Camps
  • Microsoft Technical Communities
  • Microsoft Virtual Academy
  • Script Center
  • Server and Tools Blogs
  • Solution Accelerators
  • TechNet Blogs
 
  • TechNet Flash Newsletter
  • TechNet Gallery
  • TechNet Library
  • TechNet Magazine
  • TechNet Subscriptions
  • TechNet Video
  • TechNet Wiki
  • Windows Sysinternals
  • Virtual Labs
Solutions
  • Networking
  • Cloud and Datacenter
  • Security
  • Virtualization
Updates
  • Service Packs
  • Security Bulletins
  • Microsoft Update
Trials
  • Windows Server 2012
  • System Center 2012 SP1
  • Microsoft SQL Server 2012 SP1
  • Windows 8 Enterprise
  • See all trials »
Related Sites
  • Microsoft Download Center
  • TechNet Evaluation Center
  • Drivers
  • Compatability & Converters
  • Windows Sysinternals
  • TechNet Gallery
Training
  • Training Catalog
  • Class Locator
  • Microsoft Virtual Academy
  • Free Windows Server 2012 courses
  • Free Windows 8 courses
  • SQL Server training
  • e-Learning overview
Certifications
  • Certification overview
  • MCSA: Windows 8
  • Windows Server Certification (MCSE)
  • Private Cloud Certification (MCSE)
  • SQL Server Certification (MCSE)
Other resources
  • TechNet Events
  • Second shot for certification
  • Born To Learn blog
  • IT Camps
Support by product
  • Exchange Server
  • Forefront Server
  • Forefront Edge Security
  • Forefront Server Security
  • Internet Explorer
  • Office
  • SharePoint
 
  • SQL Server
  • System Center
  • Windows Server
  • Windows XP
  • Windows Vista
  • Windows 7
  • Windows 8
Other support links
  • Microsoft Premier Online
  • Microsoft Fix It Center
  • TechNet Forums
  • MSDN Forums
  • Security Bulletins & Advisories
  • International support solutions
  • Log a support ticket
  • Look up event IDs and error codes
Not an IT pro?
  • Microsoft Customer Support
  • Microsoft Community Forums