Maximilian 25 Report post Posted January 28, 2022 (edited) Hello everybody. Recently, a very damaging bug came to my attention, it's possible with a bit of manipulation to combine gems without destroying any in the process. I will not exactly explain how to fully reproduce it so if people were to notice this before server-owners did. The bug works this way: while the inventory is locked, no items can be deleted from it. This is usually not a problem because GiveItem does not work either, it will just give you an error. This is an example in said situation: When analyzing items while the inventory is locked, no abuse is possible because while no items are deleted from the player's inventory, no items can be added to it either, thus "operation failed" being added to the system message. However, if we were to look at the combining function : "begin_unite_item" function begin_unite_item (...) local arg = {...} local Check_CanUnite = 0 Check_CanUnite = can_unite_item_main ( arg ) if Check_CanUnite == 0 then return 0 end local role = 0 local ItemBag = {} local ItemCount = {} local ItemBagCount = {} local Get_Count = 4 local ItemReadCount = 0 local ItemReadNow = 1 local ItemReadNext = 0 local ItemBag_Now = 0 local ItemCount_Now = 0 local ItemBagCount_Num = 0 role , ItemBag , ItemCount , ItemBagCount , ItemBag_Now , ItemCount_Now , ItemBagCount_Num = Read_Table ( arg ) local BagItem1 = ItemBag [0] local BagItem2 = ItemBag [1] local BagItem3 = ItemBag [2] local BagItem1 = arg [3] local BagItem2 = arg [6] local BagItem3 = arg [9] local Item1 = GetChaItem ( role , 2 , BagItem1 ) local Item2 = GetChaItem ( role , 2 , BagItem2 ) local Item3 = GetChaItem ( role , 2 , BagItem3 ) local ItemID1 = GetItemID ( Item1 ) local ItemID2 = GetItemID ( Item2 ) local ItemID3 = GetItemID ( Item3 ) local ItemType2 = GetItemType ( Item2 ) local Item2_Lv = Get_StoneLv ( Item2 ) local Item3_Lv = Get_StoneLv ( Item3 ) local i = 0 local j = 0 i = RemoveChaItem ( role , ItemID1 , 1 , 2 , BagItem1 , 2 , 1 , 0) j = RemoveChaItem ( role , ItemID3 , 1 , 2 , BagItem3 , 2 , 1 , 0) if i == 0 or j == 0 then -- important part LG( "Hecheng_BS" , "Delete item failed" ) end Item2_Lv =Item2_Lv + 1 -- important part 2 Set_StoneLv ( Item2 , Item2_Lv ) -- important part 3 local Money_Need = getunite_money_main ( arg ) local Money_Have = GetChaAttr ( role , ATTR_GD ) Money_Have = Money_Have - Money_Need SetCharaAttr ( Money_Have , role , ATTR_GD ) ALLExAttrSet( role ) local Sklv = 1 local StateLv = GetChaStateLv ( role , STATE_HCGLJB ) Sklv = Sklv + StateLv local b = Check_CG_HechengBS ( Item2_Lv , ItemType2 , Sklv ) if b == 0 then -- important part 3 i = RemoveChaItem ( role , ItemID2 , 1 , 2 , BagItem2 , 2 , 1 , 0) if i == 0 then LG( "Hecheng_BS" , "Delete item failed" ) end local cha_name = GetChaDefaultName ( role ) LG( "JingLian_ShiBai" , "Player"..cha_name.."Gem combining failed" ) SystemNotice( role , "Very sorry, combining has failed. Gem has vanished...") return 2 end local cha_name = GetChaDefaultName ( role ) LG( "JingLian_ShiBai" , "Player"..cha_name.."Gem combining successful" ) return 1 end As you can see, this script does not "give" any item, it sets the gem level to 1 higher than it originally was. Therefore, if people were able to lock their inventory. They would prevent the deletion of their gem, and get one of their gems upgraded. Furthermore, this would work even if the combining were to fail given that the deletion of the gem due to failure happens *after* the gem level is increased, and items are not deleted when inventory is locked. The fix is trivially simple, just have the function stop when items are supposed to get deleted, like this : Or whatever suits your code-base, interrupt the function when items that should be deleted aren't. if i == 0 or j == 0 then LG( "Hecheng_BS" , "Delete item failed" ) return 0 end If any site admin wants any further proof I will oblige, however I will not go into detail on the process a player can use to lock their inventory in such a way. I would suggest to also check other functions which have the same behavior when items aren't deleted, I don't think any is susceptible to this same exploitation, but you never know. A screenshot of the bug in action: Before this I had 1 refining gem level 2 and two level 1 in my inventory, after I had two level two and one level one. And now one is level three one is level two and one is level one Neither the level 2 nor the level 1 of previous gem combinings got deleted Edited January 28, 2022 by Maximilian 1 1 Quote Share this post Link to post Share on other sites
squaller 21 Report post Posted January 28, 2022 combining while trade? Quote Share this post Link to post Share on other sites
Maximilian 25 Report post Posted January 28, 2022 1 hour ago, squaller said: combining while trade? No that's checked by the server, this kind of inventory-locking is non-trivial to acquire, I'm sorry but I do not want to disclose any more information on how that's achievable since this bug will likely be exploitable in several major servers untill this gets more attention. Quote Share this post Link to post Share on other sites
Dan 184 Report post Posted January 28, 2022 1 hour ago, Maximilian said: No that's checked by the server, this kind of inventory-locking is non-trivial to acquire, I'm sorry but I do not want to disclose any more information on how that's achievable since this bug will likely be exploitable in several major servers untill this gets more attention. This looks like CO files based on the client? If you are using CO server files, take a look at lua\plugin\gem.lua. That is where they load forge/combine function. Quote Share this post Link to post Share on other sites
Maximilian 25 Report post Posted January 29, 2022 (edited) 11 hours ago, Dan said: This looks like CO files based on the client? If you are using CO server files, take a look at lua\plugin\gem.lua. That is where they load forge/combine function. The screenshots are taken in a server that alleges to use CO server files, so there's empirical evidence of this working. Furthermore not every server is using the custom gem.lua function, most are likely using the vulnerable one.@Dan I checked the function in gem.lua I think that there's a problem on it too if i == 0 or j == 0 or k == 0 then LG( "Hecheng_BS" , "Delete item failed" ) return -- does not return a value end -- this part of the function should probably be the following: if i == 0 or j == 0 or k == 0 then LG( "Hecheng_BS" , "Delete item failed" ) return 0 end Edited January 29, 2022 by Maximilian updated information Quote Share this post Link to post Share on other sites
Rinor 59 Report post Posted January 29, 2022 (edited) @Maximilian This is an issue caused from the “exploit” or “missing code” at lua side which is related to the gem stack feature that CO has. Ex: keep like 2 or any amount of lv 1 gem (any gem) on invertory and extract a gem lv 2 or higher from equips (same gem that you have as lv 1 on invertory). Ex: if you extracted a lv 5 gem of rage and you had 20x lv 1 or more in invertory then all those 20x will turn lv 5. This fix is already shared on forum on CO community topics by Angelix or Fritt one of them. This would probably fix the issue you mentioned (Not tested). Edit: If your not able to find the fix, let me know i’ll share it here. Edited January 29, 2022 by Rinor Quote Share this post Link to post Share on other sites
Maximilian 25 Report post Posted January 29, 2022 36 minutes ago, Rinor said: @Maximilian This is an issue caused from the “exploit” or “missing code” at lua side which is related to the gem stack feature that CO has. Ex: keep like 2 or any amount of lv 1 gem (any gem) on invertory and extract a gem lv 2 or higher from equips (same gem that you have as lv 1 on invertory). Ex: if you extracted a lv 5 gem of rage and you had 20x lv 1 or more in invertory then all those 20x will turn lv 5. This fix is already shared on forum on CO community topics by Angelix or Fritt one of them. This would probably fix the issue you mentioned (Not tested). Edit: If your not able to find the fix, let me know i’ll share it here. Honestly, I do not see how they are related. The issue I am talking about stems from the fact that locked inventories prevent items from being deleted from the inventory, and the vanilla lua "begin_unite_item" function does not interrupt when items fail to be deleted. CO files have nothing to do with it, do not get confused by the fact that the screenshots show that the server I tested this on - with the GM's permission - has a CO-based client. If I read CO's sourcecode correctly this exploit does not work when CO's begin_unite_item is used, because CO uses an AddItem function which in the server c++ code checks for the inventory being locked or not, however the vanilla function doesn't add any item, it just increases the level attribute of one of the two gems used in combining. Having the function return 0 when item deletion files fixes the issue. Quote Share this post Link to post Share on other sites
Maximilian 25 Report post Posted January 29, 2022 Another fix that came to my attention: the forcible flag: i = RemoveChaItem ( role , ItemID1 , 1 , 2 , BagItem1 , 2 , 1 , 0) the last attribute of this function is "0" which sets forcible deletion to false, when the function is set as: i = RemoveChaItem ( role , ItemID1 , 1 , 2 , BagItem1 , 2 , 1 , 1) Forcible deletion is set to true, which means that items are deleted even when the character's inventory is locked. Quote Share this post Link to post Share on other sites
squaller 21 Report post Posted January 29, 2022 so how to replicate , i want to know if my server has this bug Quote Share this post Link to post Share on other sites
Rinor 59 Report post Posted January 30, 2022 (edited) @Maximilian you already sharing the fix, means you should give an example how you did it so people here can test to know if this exploits works in their files and apply the fix you shared, as diff devs uses diff files/extensions/addons. Edited January 30, 2022 by Rinor Quote Share this post Link to post Share on other sites
Maximilian 25 Report post Posted January 31, 2022 21 hours ago, Rinor said: @Maximilian you already sharing the fix, means you should give an example how you did it so people here can test to know if this exploits works in their files and apply the fix you shared, as diff devs uses diff files/extensions/addons. Use gm commands to lock inventory and try. Note: the main C++ function checks for some locks, so you can either disable the checks temporary for testing purposes or set the lock that's not checked which is the bLock boolean value. I will not explain how a non-gm can acquire the particular lock because probably a lot of servers are unsafe. You should have all the information needed if you actually own a server and have access to GM level commands. Quote Share this post Link to post Share on other sites
mkhzaleh 132 Report post Posted February 2, 2022 so much drama for such old bugs tho? but you mentioned that for combine only so you should know its also called as gold hack as other name? and can use same method for the rest of any process ingame as most checks in top base on client side and they were so dumb to check one type of locks top have 4 type of locks: 1- inventory > most codes check it< 2- trade locks >GetTradeData() < most codes doesn't check it in server side, just in client 3- stall locks > GetStallData() < most codes check that in client side, not checked on sell items/ forge/combine analyze 4- item lock stone Block states so if you server owner and wrote a code you should start with small check for item itself if locked or not item =GetChaItem(role,2,slot) if(IsItemLocked(item)) then create new code for check all states at one function inline int lua_IsChaLocked(lua_State* L) { BOOL bValid = lua_gettop(L) == 1 && lua_islightuserdata(L, 1); if (!bValid) { E_LUAPARAM; return 0; } CCharacter* pChar = (CCharacter*)lua_touserdata(L, 1); if (!pChar) { E_LUANULL; return 0; } if (pChar->GetPlyMainCha()->m_CKitbag.IsPwdLocked() || pChar->GetPlyMainCha()->GetStallData() || pChar->GetPlyMainCha()->GetTradeData()) { lua_pushnumber(L, LUA_TRUE); } else { lua_pushnumber(L, LUA_FALSE); } return 1; } or just create it in lus side and use in your codes function IsChaLocked(character) if KitbagLock(character, 1) == LUA_TRUE or GetChaStateLv(character, STATE_BAT) >= 1 or GetChaStateLv(character, STATE_JY) >= 1 then return true else return false end end 1 Quote Share this post Link to post Share on other sites
AlGhoul 66 Report post Posted February 2, 2022 8 hours ago, mkhzaleh said: so much drama for such old bugs tho? what do you mean so much drama? hey kid, everyone here is learning and helping each other, if that's your point of view on everything just "drama" then you won't move on in life, no wonder why the community is dead already and everyone that has had a real impact on it left, it's because it was built on toxicity, people like you like to come here and show off that they know something... huh, what do you know? some fixes, adjustments to a game that was created around 2007 and those fixes/adjustments are mostly copied from Wrexor or V3ct0r so there's no credits for your ass here, your brain is full of shit bro, you need to change your behaviour, if you have something to share, then share it in a gentle way, if you want to show off then fuck off of here, this is men's world and you're behaving like a child, so you'll be treated like a child Quote Kind regards, AG. Share this post Link to post Share on other sites
mkhzaleh 132 Report post Posted February 2, 2022 (edited) 24 minutes ago, J0k3r said: what do you mean so much drama? hey kid, everyone here is learning and helping each other, if that's your point of view on everything just "drama" then you won't move on in life, no wonder why the community is dead already and everyone that has had a real impact on it left, it's because it was built on toxicity, people like you like to come here and show off that they know something... huh, what do you know? some fixes, adjustments to a game that was created around 2007 and those fixes/adjustments are mostly copied from Wrexor or V3ct0r so there's no credits for your ass here, your brain is full of shit bro, you need to change your behaviour, if you have something to share, then share it in a gentle way, if you want to show off then fuck off of here, this is men's world and you're behaving like a child, so you'll be treated like a child so mad kid? your way of reply shows how kiddo you are don't you? and i say what ever i want and yea i see its drama comments and i already shared such a fix 3 years ago so what ever and nope not everything there to v3ctor or wrexor credit dude , that's show how kid and useless you are all credit goes to real top team , if you like this truth or not .. people does mods, fix exploits that's their credits , no less no more? what is your impact in this situation ? zero? big mouth? useless ? that's is you Edited February 2, 2022 by mkhzaleh Quote Share this post Link to post Share on other sites
V3ct0r 2,117 Report post Posted February 3, 2022 @mkhzaleh, @J0k3r, Guys please don't fight. Quote Some useful links / Полезные ссылки Tips for making a topic in 'Questions & Help' / Рекомендации по созданию тем в разделе "Помощь" Server Advertising Section Rules / Правила раздела "Реклама серверов" Available e-mail domains for registration / Допустимые e-mail домены для регистрации User groups / Группы пользователей User ranks / Звания пользователей "Broken" pictures on the forum / "Битые" изображения на форуме Beware of scammers! / Осторожно, мошенники! My developments / Мои разработки Mods for client and server / Моды для клиента и сервера PKOdev.NET website for Tales of Pirates Server / PKOdev.NET веб-обвязка для сервера Пиратии I do not provide any help in private messages and outside the forum. Use 'Questions & Help' section please. Thank you for understanding! Я не оказываю какую-либо помощь в личных сообщениях и вне форума. Пожалуйста, используйте раздел "Пиратия: Помощь". Благодарю за понимание! Share this post Link to post Share on other sites
mkhzaleh 132 Report post Posted February 3, 2022 well i don't even know who is this kid so what ever if he can't handle sarcasm "drama word" and skipped the rest of explaining how the bug works shows how kiddo he is Quote Share this post Link to post Share on other sites