####################################################################### Luigi Auriemma Application: S.T.A.L.K.E.R.: Shadow of Chernobyl http://www.stalker-game.com Versions: <= 1.0006 Platforms: Windows Bugs: A] IPureServer::_Recieve buffer-overflow B] NET_Compressor::Decompress integer overflow C] MultipacketReciever::RecievePacket INT3 Exploitation: remote, versus server (probably clients too) Date: 28 Jun 2008 Author: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduction 2) Bugs 3) The Code 4) Fix ####################################################################### =============== 1) Introduction =============== S.T.A.L.K.E.R. is a FPS game developed by GSC Game World (http://www.gsc-game.com) and released at the beginning of the 2007 (the Clear Sky sequel is planned for the next months). ####################################################################### ======= 2) Bugs ======= ---------------------------------------- A] IPureServer::_Recieve buffer-overflow ---------------------------------------- MultipacketReciever::RecievePacket is a function used in the game when a packet beginning with the byte 0x39 is received. The main actions performed by this function are: - checking if a specific value in the packet is equal to 0xe0 or 0xe1 - calling NET_Compressor::Decompress for checking the availability of compressed data and decompress it through the lzo1x algorithm and a specific dictionary (mp\lzo-dict.bin) - calling _Recieve for handling the content of this data The _Recieve function gets the 16 bit number specified in the incoming packet and uses memcpy with a 8 kilobytes stack buffer as destination, the data from the packet as source and that 16 bit value as amount of bytes to copy. Each UDP packet in S.T.A.L.K.E.R. has a maximum size of 1472 bytes but through the LZO compression implemented in the game is possible to place up to 32 kilobytes of data in the packet resulting in a stack based buffer-overflow fully controllable by the attacker. ---------------------------------------------- B] NET_Compressor::Decompress integer overflow ---------------------------------------------- This function checks if a specific byte in the packet is equal to 0xc1 in which case is performed a CRC check and the decompression of the data using the rtc9_decompress function (lzo1x_decompress_dict_safe). If the data is not compressed the function gets the current size of the data in the packet and performs a memcpy(dst, data, data_size - 1), so the sending of a packet without data causes a crash of the server due to the copying of 0xffffffff (0 - 1) bytes. ------------------------------------------ C] MultipacketReciever::RecievePacket INT3 ------------------------------------------ One of the first operations made by this interesting function is checking if a certain byte in the packet is equal to 0xe0 or 0xe1 otherwise an INT3 instruction is executed leading to the immediate termination of the server: 01906F33 8A45 00 MOV AL,BYTE PTR SS:[EBP] 01906F36 3C E1 CMP AL,0E1 01906F38 56 PUSH ESI 01906F39 57 PUSH EDI 01906F3A 894C24 18 MOV DWORD PTR SS:[ESP+18],ECX 01906F3E 74 05 JE SHORT xrNetSer.01906F45 ; jump if 0xe1 01906F40 3C E0 CMP AL,0E0 01906F42 74 01 JE SHORT xrNetSer.01906F45 ; jump if 0xe0 01906F44 CC INT3 ; boom The attacker needs to join the server for exploiting the above vulnerabilities, but although it supports the banning of the IP addresses is possible to spoof the packets and bypassing this limitation due to the lack of handshakes in the protocol of the game. ####################################################################### =========== 3) The Code =========== http://aluigi.org/poc/stalker39x.zip ####################################################################### ====== 4) Fix ====== No fix ####################################################################### --- Luigi Auriemma http://aluigi.org