-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stats vulnerability #28
Comments
bump. cen from eurobattle.net can confirm this problem. |
Fake action packets is fundamental issue with how stats are processed by host bots. Replay parsers would have the same issue. But this is a bit confusing:
How does the packet sent by the attacker make it to the CStatsDOTA of a different game? It should only be parsed on this line in game.cpp:
Only accepting action packets from bot IP wouldn't help because the bot doesn't understand what action packets are at all. Basically the bot is just a router that forwards action packets from one player to all the other players. Anyway, one solution might be to only process the action packets after the player has KeepAlive packet, which includes a checksum based on the game state. Because if they are sending fake stats then probably their Warcraft III state will not match that of other players (unless they are not just injecting the packets into the TCP connection, but actually sending them through WC3 by modifying WC3 memory). I could provide more pointers on that but the first thing to do is probably to figure out why the attacker can modify stats in other games. |
The "all current running games" comment is incorrect, you need to join the game to cause this. My understanding is that replay generated by ghost will contain the same actions and is therefore not good for parsing stats. However, if such replay is opened in W3, the game seems to play fair and stats seem OK also, need to investigate this further. Packets can be generated out of thin air so to rely on game state is probably not an option. At the moment I am brainstorming whether a modification in DotA map itself could give some secure solution. |
Players would need to send legitimate KeepAlive packets in order to avoid desync'ing. It seems to me that it's much harder for the player to compute the checksum in the KeepAlive correctly than merely send spoofed GameAction packets that contain fake stats data. Because that means the player would need their WC3 client to maintain the game state correctly. (I expect that the player would desync because other players would receive the fake GameAction packets and update their game states accordingly. But the player would not be able to receive their own GameAction packets without modifying WC3 client because WC3 would reject receiving packets that it did not send.) Edit: (if the player is not able to compute checksum correctly, their checksum would not match that of other players. Certainly if the attacker had two players in the game then they could borrow the checksum from the other player.) |
I'll produce a wireshark dump to see what kind of checksum is present in the fake packets. |
It seems I have already discussed this in Skype. But since I now for the PC, then I can answer deployed here. All statiscs work on the SyncStoredInteger native in Warcraft. The bot sees that some data is synchronized and counts as statistics. And the main problem is that synchronization does not give clear signs that it was not the one who called it. I can independently generate the necessary SyncStoredInteger and the bot will consider this as an action. There will be no desynchronization. As a solution - to alter the bot and the map so that all clients of the game sent a notification of the event to the bot, and the bot in turn processed it when it came from everyone, and not from one. Alternatively, put FakePlayer on the game slot (11 or 12). When the bot receives Sync, it sends the action on behalf of FakePlayer "Sync came from the player ". If the event is correct, the players are silent. If not, send your Sync supposedly wrong event. In this case, to hack the statistics you need to have several slots in the game for the hacker, which may not always be possible. |
RECEIVED W3GS_OUTGOING_ACTION Locally calculated CRC (matches): If packet is generated outside the engine and distributed to clients I see no desync issues since clients probably just discard it. |
@kirill-782 focus on the bot side, in the maps side i spoke with 'gods' map creators and you can do nothing! |
Interesting, I remember trying this before, I guess I had a bug (maybe the issue I ran into was WC3 crashing after receiving an action packet that it didn't send, but simply not forwarding that packet to WC3 gets around it). If the map can be edited then kirill your solutions seem quite good, especially the first one (more straightforward to implement). If the map can't be edited, do y'all think that the impact could be minimized by shuffling the players prior to game start, and only accepting the packets from blue player? I ran parser on some GHost++ replays and it seems like DotA always sends the synchronization through blue player, at least for the keys sent at end of game. (Based on W3MMD which probably takes same approach I think it's the first slot or something right? so if player leaves I imagine it'd transfer to teal.) (If this works, you could just shuffle within the teams, and then also flip a coin to decide who is sentinel/scourge, then at least people can still play together and attacker with one player in the game has 1/10 chance of getting blue.) (BTW I don't understand why the attacker needs to slowly send these packets to increment the kills one at a time, because there seems to be a set of keys "1"/"2"/etc sent at end of game which directly set the number of kills.) Edit: oh, I think W3MMD already implements a "NUM_SENDERS_SAFE" approach where multiple players send the stats data? So it's like kirill's approach but it just does 3 random players I think. But I guess DotA always picks first slot, with no redundancy. Edit2: very cool, from https://www.ghostpp.com/forum/index.php?topic=8.0 it looks like W3MMD defaults to 2 players but when it detects players are tampering with the messages, it increases it to 3. I don't think the host bot currently does anything special though. |
I made a lot of edits so here's summary of my thoughts:
|
Shuffling is an interesting idea but it's mostly a band aid. We usually balance in lobby per player stats and allow slot locking so at best that would be ~1/5 chance. Still, as last resort it's better than no solution. If map could be updated it would have to send from all players, anything less and you compromise on a team of hackers locking slots or voting over fair players. I forwarded the info to d1stats for input. |
here are a live with the tool: https://gaming.youtube.com/watch?v=LNmDjlGkSV4&feature=share and here are stats with a hacked game: http://prntscr.com/n0mthx players suicides http://prntscr.com/n0mu7l @cen1 Before starting this topic i spoke with d1, they said cant help. |
@styla01 well if you want an even more temporary solution, just kick the player if they send 6+ kills within, say, ten seconds. |
W3MMD has this comment:
I guess the bandwidth issue isn't relevant anymore so all 10 players would make a lot of sense. |
we cant, players are suicides |
The host bot knows who sent the action packet corresponding to each "suicide" event though. Just whichever player it got the action packet from. |
can u add a commit? please |
Nah it is temporary fix anyway, just if you want it fixed in next few days it may be the simplest way; but you'd need to implement it yourself. The shuffling is slightly longer term, but still just means attacker won't be able to do it every game. If you are okay with modifying DotA map (only need to edit war3map.j) then you could actually implement the fix proposed by kirill and cen without assistance from the map creators. If you post link to DotA map you're using I could take a stab at it using umpqx. |
Ofcourse I am ok to modify map script, Maybe @cen1 and @kirill-782 can implement the fix but I'm afraid will took too long. Kicking the flooder was a very good temp solution. Edit. Saving stats by map with all slots instead of the blue only wont change anything, already tried. |
Why wouldn't it change anything? You're saying you modified the map to run SyncStoredInteger from every player instead of just first slot player, and you updated the host bot to do something like majority voting, but one attacker can still mess up the stats? It seems like it should work to me so I don't understand exactly. If you post a link to the DotA map that you're using I can try to edit it to run SyncStoredInteger from every player, assuming you haven't already implemented that solution. If you updated the map already, but not the host bot fix, I could look at implementing majority voting if that'd be useful, but that part seems quite straightforward. |
i made the changes only in map side. |
That's pretty cool! In that case can you post the modified map where all players send packets? Then I (or someone else) may have some time to update the host bot to do majority voting, and check if it is all working. To me the map editing is harder than the majority voting! |
is done, all players save the stats. I need your discord to sent to you |
Can you upload map somewhere and post link here so anyone can download? That way if someone else gets to it first they can go ahead and implement a solution. Anyway anyone can download the map by joining your game! So would be good to have the link here. |
I will upload. |
So the only problem is you need the corresponding changes on the bot side to make this block the attacker, right? |
Since the stats come in async I guess the voting is to be done at the very end by comparing each player report? |
@uakfdotb yes |
Very cool! Can you upload the w3x though? That way on bot side can just stick the map in and don't need to create new w3x. @cen1 I haven't thought about it much but that may be the simplest. Or could wait until (# players)/2+1 come in. |
map, https://files.fm/u/nnv5s665 and is compatible only 1.26 |
@uakfdotb, |
@kirill-782 I have no idea, I haven't upgraded 1.30.4, because Battle.net banned my personal CD keys. I think it'd be difficult with the new LAN system. |
@uakfdotb, Blizzard bans CD keys? |
To disassemble this package. And so it’s not hard to deal with MDNS |
I got started here but I wasn't able to test it (it does compile though). As you can see it is a very small change, I don't have time to set up WC3 and all but hopefully it is enough to point you in the right direction to complete the implementation. Of course there may be additional changes needed in your replay parser but that is separate from GHost++. |
i made a test with the patch, but bot crash when tryed to save dota stats. I have also noticed a huge lag from the hack tool, we need a way to detect and kick the hack tool user. |
I have a working patch, lightly tested but it should be a great start for anyone who wants to integrate it into upstream. Unfortunately our code base has diverged too much and I can't make a clean pull request. I most probably won't have the time to rebase this against this repo so anyone is welcome to take this work and integrate it. https://gist.github.com/cen1/6dda290d3f397a15701553705beb8aea |
First, i must say I use same statsdota.cpp like this repo, but I have adapted the ghostone interface to see live events.
I am attacked with a tool who sent fake stats(Kills and Deaths) to the bot.
I made live prints one from game:
and after 2 seconds i saw live the ghostone interface:
The fake kills/deaths trick the bot, and the atacker can sent 10 fake kills/deaths per second, until the game end all players have scores like K/D: 887/865
@uakfdotb Please help us! Maybe you can make a filter to read/accept action packets only from the bot ip (localhost only), or stats must be read'ed only from replay.
The text was updated successfully, but these errors were encountered: