####################################################################### Luigi Auriemma Application: NeoEngine http://www.neoengine.org Versions: <= 0.8.2 and CVS 3422 Platforms: Windows, *nix, *BSD and more Bugs: A] visualization format string B] crash caused by failed allocation Exploitation: remote Date: 27 Jun 2006 Author: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduction 2) Bugs 3) The Code 4) Fix ####################################################################### =============== 1) Introduction =============== NeoEngine is an open source game engine released under the MPL license. ####################################################################### ======= 2) Bugs ======= Differently to my usual way the following bugs have not been tested in practice due to the absence of a working program for my tests, like a minimal server for example, and for the lack of feedback from the developers. ------------------------------ A] visualization format string ------------------------------ The visualization functions used in NeoEngine are affected by some format string vulnerabilities caused by the absence of the format argument: From neoengine/console.cpp: bool Console::Render( Frustum *pkFrustum, bool bForce ) ... m_pkFont->Printf( m_iX + m_iWidth - 2, m_iY + iHeight, strCmd.c_str() ); ... m_pkFont->Printf( m_iX + 4, m_iY + iHeight, strCmd.c_str() ); ... From neowtk/textarea.cpp: bool TextArea::Render( Frustum *pkFrustum, bool bForce ) ... if( !m_bPassword ) m_pkFont->Printf( kPos.x + m_kPadding.x, kPos.y + m_kPadding.y, m_strText.c_str() ); else m_pkFont->Printf( kPos.x + m_kPadding.x, kPos.y + m_kPadding.y, string( m_strText.length(), '*' ).c_str() ); ------------------------------------ B] crash caused by failed allocation ------------------------------------ It's possible to crash the engine through a too big uiMessageLength value (32 bit number) which causes the assignment of a NULL pointer to the pucMessage pointer and the subsequent reading from the socket withouth verifying the return value. From neonet/core.cpp: void Core::Receive() ... unsigned int uiMessageLength; ... if ( pkTCPSocket->Read( &uiMessageLength, sizeof( unsigned int ) ) <= 0 ) ... char *pucMessage; pucMessage = ( char* )malloc( uiMessageLength + 1 ); if ( uiMessageLength > 0 ) { pkTCPSocket->Read( pucMessage, uiMessageLength ); } pucMessage[ uiMessageLength ] = 0; Message *pkMessage = pkMessageTemplate->Deserialize( string( pucMessage, uiMessageLength ) ); free( pucMessage ); ####################################################################### =========== 3) The Code =========== No proof-of-concept available. ####################################################################### ====== 4) Fix ====== No fix. I contacted the author one month ago and after an initial reply I have received no other feedback. #######################################################################