####################################################################### Luigi Auriemma Application: id Tech 4 engine http://www.idsoftware.com http://iddevnet.com Games: Enemy Territory: Quake Wars <= 1.5.12642.33243 http://www.enemyterritory.com Wolfenstein <= 1.3.344272 http://www.wolfenstein.com the problem exists in a different way (and in some cases probably not exploitable) also in the other games based on this engine like Quake 4 <= 1.4.2, Doom 3 <= 1.3.1 and Prey <= 1.4 Platforms: Windows (tested), Linux, Mac OS X, PlayStation 3, Xbox 360 Bug: possible code execution through array overflow Exploitation: remote, versus clients (from maliciou server) Date: 19 Jun 2010 Author: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduction 2) Bug 3) The Code 4) Fix ####################################################################### =============== 1) Introduction =============== id Tech 4 is currently the latest version of the game engine developed by id Software. ####################################################################### ====== 2) Bug ====== A little introduction: as main test platform I have used ETQW and Wolfenstein that are the most recent games developed with the id Tech 4 engine and that contains this bugged function for which I have been able to confirm the possibility of code execution. Additionally I have tested also Doom 3 and Quake 4 but in that case the code is completely different (just not the same) and from my tests probably it can be dangerous only for Quake 4 where are involved some function pointers partially controlled by the attacker. So consider this advisory ONLY for the latest versions of the id Tech4 engine containing the idGameLocal::GetGameStateObject function! The following are the details: --- A particular 32bit field in the connectResponse packet of the server is used by the client for calling some function pointers located in an internal structure through the function called idGameLocal::GetGameStateObject. This function seems to exist only in the latest versions of the id Tech4 engine used in games like ETQW and Wolfenstein. The result is pretty interesting because with some luck is possible to execute malicious code (successfully in my tests). The following is the "path" done by such 32bit value till the instruction that calls the function pointer: 1A29326F 69D2 0C610000 IMUL EDX,EDX,610C ; step 1 1A293275 8D8432 78370300 LEA EAX,DWORD PTR DS:[EDX+ESI+33778] ; step 2 1A29327C 50 PUSH EAX 1A29327D 8BCE MOV ECX,ESI 1A29327F E8 6CFDFFFF CALL gamex86.1A292FF0 | /---------------------------/ V ... 1A293000 8BB4BD 04610000 MOV ESI,DWORD PTR SS:[EBP+EDI*4+6104] ; step 3 1A293007 85F6 TEST ESI,ESI 1A293009 74 10 JE SHORT gamex86.1A29301B 1A29300B 8BCE MOV ECX,ESI 1A29300D E8 1EB10000 CALL gamex86.1A29E130 | /---------------------------/ V 1A29E130 8B49 04 MOV ECX,DWORD PTR DS:[ECX+4] ; step 4 1A29E133 85C9 TEST ECX,ECX 1A29E135 74 08 JE SHORT gamex86.1A29E13F 1A29E137 8B01 MOV EAX,DWORD PTR DS:[ECX] ; step 5 1A29E139 8B10 MOV EDX,DWORD PTR DS:[EAX] ; step 6 1A29E13B 6A 01 PUSH 1 1A29E13D FFD2 CALL EDX ; code execution 1A29E13F C3 RETN --- Now, only as reference, I post some snippests regarding Quake 4 and Doom 3. Note that in this case the problem happens after the loading of the map when the player is starting the match: Quake 4 1.4.2: 0C5BA644 8B3C85 84F0890C MOV EDI,DWORD PTR DS:[EAX*4+C89F084] ; EAX is the 32bit field 0C5BA64B 85FF TEST EDI,EDI 0C5BA64D 8BDF MOV EBX,EDI 0C5BA64F 74 25 JE SHORT gamex86.0C5BA676 0C5BA651 80BF 07190000 00 CMP BYTE PTR DS:[EDI+1907],0 0C5BA658 74 11 JE SHORT gamex86.0C5BA66B 0C5BA65A 8B87 F8180000 MOV EAX,DWORD PTR DS:[EDI+18F8] 0C5BA660 8B3C85 84F0890C MOV EDI,DWORD PTR DS:[EAX*4+C89F084] 0C5BA667 85FF TEST EDI,EDI 0C5BA669 74 0B JE SHORT gamex86.0C5BA676 0C5BA66B 8B17 MOV EDX,DWORD PTR DS:[EDI] 0C5BA66D 8BCF MOV ECX,EDI 0C5BA66F FF52 14 CALL DWORD PTR DS:[EDX+14] or 1007ED39 |> 8B86 F8000000 MOV EAX,DWORD PTR DS:[ESI+F8] ; EAX is the 32bit field 1007ED3F |. 33C9 XOR ECX,ECX 1007ED41 |. 05 29840000 ADD EAX,8429 1007ED46 |. 8D1440 LEA EDX,DWORD PTR DS:[EAX+EAX*2] 1007ED49 |. 8D0496 LEA EAX,DWORD PTR DS:[ESI+EDX*4] 1007ED4C |. 8908 MOV DWORD PTR DS:[EAX],ECX 1007ED4E |. 8948 04 MOV DWORD PTR DS:[EAX+4],ECX 1007ED51 |. 8948 08 MOV DWORD PTR DS:[EAX+8],ECX Doom 3 1.3.1: 1006904E 8B2C8D D4EA1E10 MOV EBP,DWORD PTR DS:[ECX*4+101EEAD4] ; ECX is the 32bit field 10069055 85ED TEST EBP,EBP 10069057 8BFD MOV EDI,EBP 10069059 896C24 64 MOV DWORD PTR SS:[ESP+64],EBP 1006905D 897C24 10 MOV DWORD PTR SS:[ESP+10],EDI 10069061 74 25 JE SHORT gamex86.10069088 10069063 8A85 93140000 MOV AL,BYTE PTR SS:[EBP+1493] 10069069 84C0 TEST AL,AL 1006906B 8DB5 93140000 LEA ESI,DWORD PTR SS:[EBP+1493] 10069071 74 1C JE SHORT gamex86.1006908F 10069073 8B95 7C140000 MOV EDX,DWORD PTR SS:[EBP+147C] 10069079 8B2C95 D4EA1E10 MOV EBP,DWORD PTR DS:[EDX*4+101EEAD4] 10069080 85ED TEST EBP,EBP 10069082 896C24 64 MOV DWORD PTR SS:[ESP+64],EBP 10069086 75 07 JNZ SHORT gamex86.1006908F 10069088 32C0 XOR AL,AL 1006908A E9 A4040000 JMP gamex86.10069533 1006908F 8BCB MOV ECX,EBX 10069091 E8 1ACBFFFF CALL gamex86.10065BB0 ####################################################################### =========== 3) The Code =========== http://aluigi.org/poc/idtech4carray.zip ####################################################################### ====== 4) Fix ====== No fix. #######################################################################