cpp
void AddWeapon( WEAPON *wp )
{
rgWeapons[ wp->iId ] = *wp;
LoadWeaponSprites( &rgWeapons[ wp->iId ] );
}
There are no boundary check, and the range of iId is [-128, 128), so I can modify many things in the data section.
In client.dll, there's an object called gEngfuncs, it is a function table that has various functions of the engine. After some calculations on latest CS 1.6 client.dll, I concluded that this function table could be overwritten using the above bug.
I have attached a PoC that will pop calc.exe on latest CS 1.6 client when connected to malicious server. The AMXX plugin will catch InitHUD message, and send crafted WeaponList message to overwrite the address of function used in HUD_DirectorMessage to execute client cmds to a ROP gadget that will trigger the chain sent in the next SendCmd call. To overwrite that address, I used a crafted weapon sprite list (weapon_pwn.txt) (see WEAPON struct, file cl_dll/ammo.h in the HLSDK).
Impact
Since it's RCE, attacker can do almost anything that don't require higher privilege (ex. compromise account, inject malware, ...)
{"id": "H1:513154", "type": "hackerone", "bulletinFamily": "bugbounty", "title": "Valve: Unchecked weapon id in WeaponList message parser on client leads to RCE", "description": "Let's look at WeaponList message parser code in the HLSDK:\n``` cpp\nint CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )\n{\n\tBEGIN_READ( pbuf, iSize );\n\t\n\tWEAPON Weapon;\n\n\tstrcpy( Weapon.szName, READ_STRING() );\n\tWeapon.iAmmoType = (int)READ_CHAR();\t\n\t\n\tWeapon.iMax1 = READ_BYTE();\n\tif (Weapon.iMax1 == 255)\n\t\tWeapon.iMax1 = -1;\n\n\tWeapon.iAmmo2Type = READ_CHAR();\n\tWeapon.iMax2 = READ_BYTE();\n\tif (Weapon.iMax2 == 255)\n\t\tWeapon.iMax2 = -1;\n\n\tWeapon.iSlot = READ_CHAR();\n\tWeapon.iSlotPos = READ_CHAR();\n\tWeapon.iId = READ_CHAR();\n\tWeapon.iFlags = READ_BYTE();\n\tWeapon.iClip = 0;\n\n\tgWR.AddWeapon( &Weapon );\n\n\treturn 1;\n}\n```\n\nAnd `WeaponResource::AddWeapon`:\n\n``` cpp\nvoid AddWeapon( WEAPON *wp ) \n{ \n\t\trgWeapons[ wp->iId ] = *wp;\t\n\t\tLoadWeaponSprites( &rgWeapons[ wp->iId ] );\n}\n```\nThere are no boundary check, and the range of `iId` is `[-128, 128)`, so I can modify many things in the data section.\n\nIn `client.dll`, there's an object called `gEngfuncs`, it is a function table that has various functions of the engine. After some calculations on latest CS 1.6 `client.dll`, I concluded that this function table could be overwritten using the above bug.\n\nI have attached a PoC that will pop `calc.exe` on latest CS 1.6 client when connected to malicious server. The AMXX plugin will catch `InitHUD` message, and send crafted `WeaponList` message to overwrite the address of function used in `HUD_DirectorMessage` to execute client cmds to a ROP gadget that will trigger the chain sent in the next `SendCmd` call. To overwrite that address, I used a crafted weapon sprite list (`weapon_pwn.txt`) (see `WEAPON` struct, file `cl_dll/ammo.h` in the HLSDK).\n\n## Impact\n\nSince it's RCE, attacker can do almost anything that don't require higher privilege (ex. compromise account, inject malware, ...)", "published": "2019-03-21T13:30:56", "modified": "2019-09-17T17:34:14", "cvss": {"score": 0.0, "vector": "NONE"}, "href": "https://hackerone.com/reports/513154", "reporter": "nyancat0131", "references": [], "cvelist": [], "lastseen": "2019-09-17T17:56:16", "viewCount": 22, "enchantments": {"dependencies": {}, "score": {"value": 0.3, "vector": "NONE"}, "backreferences": {}, "exploitation": null, "vulnersScore": 0.3}, "bounty": 3000.0, "bountyState": "resolved", "h1team": {"url": "https://hackerone.com/valve", "handle": "valve", "profile_picture_urls": {"small": "https://hackerone.com/rails/active_storage/representations/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBL0VTQVE9PSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--09e96cedf7ca1ed6f64f7c55d5f51c7a12c43dfd/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCam9VWTI5dFltbHVaVjl2Y0hScGIyNXpld2c2REdkeVlYWnBkSGxKSWd0RFpXNTBaWElHT2daRlZEb0xjbVZ6YVhwbFNTSUxOako0TmpKZUJqc0hWRG9KWTNKdmNFa2lEall5ZURZeUt6QXJNQVk3QjFRPSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--c38a870d322217b0422c840e7586b68994be38b4/valve_logo.png", "medium": "https://hackerone.com/rails/active_storage/representations/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBL0VTQVE9PSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--09e96cedf7ca1ed6f64f7c55d5f51c7a12c43dfd/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCam9VWTI5dFltbHVaVjl2Y0hScGIyNXpld2c2REdkeVlYWnBkSGxKSWd0RFpXNTBaWElHT2daRlZEb0xjbVZ6YVhwbFNTSUxPREo0T0RKZUJqc0hWRG9KWTNKdmNFa2lEamd5ZURneUt6QXJNQVk3QjFRPSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--0e71f6791faebe1c35f4452bd21d67fb6decfbc2/valve_logo.png"}}, "h1reporter": {"disabled": false, "username": "nyancat0131", "url": "/nyancat0131", "profile_picture_urls": {"small": "https://hackerone.com/rails/active_storage/representations/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBMHltQ1E9PSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--3dd88f75943bc74a60293970cf9772f30a8c56c0/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCam9VWTI5dFltbHVaVjl2Y0hScGIyNXpld2c2REdkeVlYWnBkSGxKSWd0RFpXNTBaWElHT2daRlZEb0xjbVZ6YVhwbFNTSUxOako0TmpKZUJqc0hWRG9KWTNKdmNFa2lEall5ZURZeUt6QXJNQVk3QjFRPSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--c38a870d322217b0422c840e7586b68994be38b4/34198388_1684856424939251_6921952895495569408_n.jpg"}, "is_me?": false, "hackerone_triager": false, "hacker_mediation": false}, "immutableFields": [], "cvss2": {}, "cvss3": {}, "_state": {"dependencies": 1645589082}}