1. Please help test custom maps and more on the latest PTR!
    Dismiss Notice
  2. Create competitive 1v1 maps in the Melee Mapping Contest #2!
    Dismiss Notice
  3. Evolution complete! Make Darwin proud and go vote in the Techtree Contest #12 - Poll.
    Dismiss Notice
  4. Icon Contest #17 - Results are out! Step by to congratulate our winners!
    Dismiss Notice
  5. Succumb to the whispers and join our Texturing Contest #29 - Old Gods!
    Dismiss Notice
  6. The results for Texturing Contest #28 are out! Step by to congratulate our winners!
    Dismiss Notice
  7. We've created the Staff Job Openings thread. We're currently in need of icon, video production, and social/multimedia positions to be filled. Thank you!
    Dismiss Notice

Is it possible to crash a wc3 client via a hack?

Discussion in 'World Editor Help Zone' started by sethmachine, Aug 3, 2014.

  1. sethmachine

    sethmachine

    Joined:
    Aug 7, 2013
    Messages:
    1,318
    Resources:
    0
    Resources:
    0
    Hi,

    I was playing a semi-competitive game today and when I typed GG to my opponent, he responded with something. I couldn't see what he typed, only that he typed something because my WC3 instantly crashed.

    Was this simply bad luck? I have heard WC3 can crash when a player is defeated or leaves the game.

    Or did the player crash my client in response to losing? I know this is possible for older Blizzard titles.

    Here is the crash message. Also, the music from the game is still playing (albeit looping) until I press "ok."

    [​IMG]
     
  2. Bannar

    Bannar

    Joined:
    Mar 19, 2008
    Messages:
    3,085
    Resources:
    20
    Spells:
    5
    Tutorials:
    1
    JASS:
    14
    Resources:
    20
    Unfortunately battle net 1.0 isn't well protected and if you just willing to, you can be the one using hacks too. Google will take you to sites of interest immidiately. Although this error hasn't had to appear due to his bad mood.
     
  3. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,380
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    Were you playing melee or a custom map? It is definitely possible to crash wc3 via code. You can always detect a particular chat message and locally force a crash.

    If so, then that guy is a douche. Ask him for his P.O. box and send him hate mail.

    But that aside, it could be coincidental. Did anything, besides the chat message, happen at that time? Also, do you still have a log of the crash report?
     
  4. sethmachine

    sethmachine

    Joined:
    Aug 7, 2013
    Messages:
    1,318
    Resources:
    0
    Resources:
    0
    Hi Purgeandfire.

    Well I know for sure the map isn't rigged. I am asking if there's a third party hack can cause someone elses wc3 to crash.

    I just played another game, and the same thing happened. I kicked some guy's ass, then I see a player type a text message but I can't see what it says, as the game immediately crashes. Here's the image.

    [​IMG]

    What do you mean by the log?

    BTW I've been playing this map for a few years (yes the same map). Crashes like this have never happened before.

    I'm attaching the 2 replays found in the log. These are the games where it crashed in the circumstances I described.

    View attachment SETH-PC_080314_164825_replay.w3g

    View attachment SETH-PC_080314_174409_replay.w3g
     
  5. jonhysone

    jonhysone

    Joined:
    Oct 29, 2012
    Messages:
    1,224
    Resources:
    1
    Maps:
    1
    Resources:
    1
    I think maphack causes crash , when the host opens maphack which itself was used the last game, it will crash the next game if the host didn't re-open, If the host's game crashes, all players' games will crash too :)
     
  6. muzzel

    muzzel

    Joined:
    Jun 27, 2008
    Messages:
    1,303
    Resources:
    2
    JASS:
    1
    Wurst:
    1
    Resources:
    2
    Which map is it? Upload or link it, then we can check if there is a "drop" command..

    But there were different drophacks in the past, most of them usually dont crash wc3 tho, they just disconnect you. Doesnt mean its not possible..
     
  7. Dr Super Good

    Dr Super Good

    Spell Reviewer

    Joined:
    Jan 18, 2005
    Messages:
    24,630
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    Yes a hack can crash WC3 clients.

    The most famous was the order queue stack overflow crash that would occur if you queued up ~8,000 orders on a unit. Obviously blizzard used iterative function calls so eventually it overflowed the thread stack which for security reasons generally causes a process crash. You could tell someone was doing this by the horrific lag that occurred as he sent orders so fast that it caused network congestion between clients and host. He obviously protected himself with a modified executable with larger stack size so you all would crash before he did so it registers him as the winner.

    This is why we now have a limit on the number of orders you can queue on a unit. They patched it simply by enforcing a limit to the number of orders you can queue so a stack overflow was no longer possible.

    That said this is just one of the old ways to crash it. Beyond a doubt people will have found new ways.

    By the sounds of it they are injecting some kind of invalid chat message into the game. The crash is caused by an instruction trying to write over itself! It crashes due to the pages reserved for program code being write protected so writing over an instruction results in the OS sending a critical error to the process and shutting it down. This is very bad as this means that they some how have write control over some piece of game code. If they can do this to crash it, it may also be possible that they can use messages to manipulate the game state however this would be very detectable.

    Could you try recording your sessions with a video capture program? Maybe you can then read what they type.

    Have you checked the replay files? Try and get them from the robot administrator if yours are invalid since they will show what happens as all messages are recorded.

    This is very similar to an old crash the game Empire Earth had in 2000. If you typed a very long message (max length of 'W' characters which were among the widest in the typeset) it would cause everyone who saw it to crash. This was patched for the expansion.
     
  8. sethmachine

    sethmachine

    Joined:
    Aug 7, 2013
    Messages:
    1,318
    Resources:
    0
    Resources:
    0
    From the crash windows I showed are you sure this is what is happening or is this a hypothesis, e.g. could it just me some miscellaneous WC3 crash and it was just a coincidence both times that some unfortunate events caused this? As in are you certain that both these crashes were caused by a malicious human?

    Also I attached the replays to my last post. Unfortunately they crash and you can't see the message being sent at all, as the replays crash in the frame right before the message was sent.
     
  9. Dr Super Good

    Dr Super Good

    Spell Reviewer

    Joined:
    Jan 18, 2005
    Messages:
    24,630
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    The error is very unusual as I mentioned. Explanation below.

    I am mostly certain it is not related to malicious players. Explanation below.

    EDIT:

    Ok what is happening is that the game is trying to call a function in a page that does not exist (not allocated at all!). Basically a dynamic function call (using a function pointer) gone wrong. The error generated is probably garbage as a result that there is nothing to call there.

    The chat message you are seeing before the crash is probably sent by the host robot. At least 1 other player has less latency than you to the server so is ever so slightly ahead of you. As a result he crashes before you, this is picked up as a TCP disconnect by the host robot which then forwards this message on to you. This message is processed and displayed just before you crash due to the same error (your client reaches the same progression). There is no crash hack involed, purely WC3 being an annoying piece of buggy... um... stuff.

    This is not all. Here is the actual game function call responsible for the crash! *queue law suit as I am not sure Blizzard completely agrees to people doing this*
    Code (Text):

    6F049510  /$ 8B4424 04      MOV EAX,DWORD PTR SS:[ESP+4]
    6F049514  |. 56             PUSH ESI
    6F049515  |. 57             PUSH EDI
    6F049516  |. 8B78 0C        MOV EDI,DWORD PTR DS:[EAX+C]
    6F049519  |. 85FF           TEST EDI,EDI
    6F04951B  |. 8BF1           MOV ESI,ECX
    6F04951D  |. 74 76          JE SHORT Game.6F049595
    6F04951F  |. F647 20 01     TEST BYTE PTR DS:[EDI+20],1
    6F049523  |. 75 25          JNZ SHORT Game.6F04954A
    6F049525  |. 8B46 30        MOV EAX,DWORD PTR DS:[ESI+30]
    6F049528  |. 85C0           TEST EAX,EAX
    6F04952A  |. 75 05          JNZ SHORT Game.6F049531
    6F04952C  |. E8 5F934200    CALL Game.6F472890
    6F049531  |> 6A 04          PUSH 4
    6F049533  |. 6A 00          PUSH 0
    6F049535  |. 57             PUSH EDI
    6F049536  |. 8BC8           MOV ECX,EAX
    6F049538  |. E8 A3B92300    CALL Game.6F284EE0
    6F04953D  |. 85C0           TEST EAX,EAX
    6F04953F  |. 74 09          JE SHORT Game.6F04954A
    6F049541  |. F747 20 000080>TEST DWORD PTR DS:[EDI+20],800000
    6F049548  |. 74 4B          JE SHORT Game.6F049595
    6F04954A  |> 6A 00          PUSH 0
    6F04954C  |. 56             PUSH ESI
    6F04954D  |. 8BCF           MOV ECX,EDI
    6F04954F  |. E8 8C1E2600    CALL Game.6F2AB3E0
    6F049554  |. 6A 00          PUSH 0
    6F049556  |. 56             PUSH ESI
    6F049557  |. 8BCF           MOV ECX,EDI
    6F049559  |. E8 721D2600    CALL Game.6F2AB2D0
    6F04955E  |. 8B16           MOV EDX,DWORD PTR DS:[ESI]
    6F049560  |. 8B82 14030000  MOV EAX,DWORD PTR DS:[EDX+314]
    6F049566  |. 8BCE           MOV ECX,ESI
    [U][B]6F049568  |. FFD0           CALL EAX[/B][/U]
    6F04956A  |. 85C0           TEST EAX,EAX
    6F04956C  |. 74 1B          JE SHORT Game.6F049589
    6F04956E  |. F746 20 004000>TEST DWORD PTR DS:[ESI+20],4000
    6F049575  |. 74 12          JE SHORT Game.6F049589
    6F049577  |. 8BCE           MOV ECX,ESI
    6F049579  |. E8 22E4FEFF    CALL Game.6F0379A0
    6F04957E  |. 85C0           TEST EAX,EAX
    6F049580  |. 74 07          JE SHORT Game.6F049589
    6F049582  |. 8166 20 FFBFFF>AND DWORD PTR DS:[ESI+20],FFFFBFFF
    6F049589  |> 68 80E4AA6F    PUSH Game.6FAAE480
    6F04958E  |. 8BCE           MOV ECX,ESI
    6F049590  |. E8 DBEBFEFF    CALL Game.6F038170
    6F049595  |> 5F             POP EDI
    6F049596  |. 5E             POP ESI
    6F049597  \. C2 0400        RETN 4

    This is the thread state...
    EAX 3F028F5C
    ECX 22B94F84
    EDX 22B94A24
    EBX 1F167964
    ESP 0018EF5C
    EBP 0DF6BA04
    ESI 22B94F84
    EDI 1F515404
    EIP 3F028F5C
    C 0  ES 002B 32bit 0(FFFFFFFF)
    P 0  CS 0023 32bit 0(FFFFFFFF)
    A 1  SS 002B 32bit 0(FFFFFFFF)
    Z 0  DS 002B 32bit 0(FFFFFFFF)
    S 0  FS 0053 32bit 7EFDD000(FFF)
    T 0  GS 002B 32bit 0(FFFFFFFF)
    D 0
    O 0  LastErr ERROR_SUCCESS (00000000)
    EFL 00210212 (NO,NB,NE,A,NS,PO,GE,G)
    ST0 empty 0.0
    ST1 empty 0.4602382779121398926
    ST2 empty 0.4602382779121398926
    ST3 empty -17344.562500000000000
    ST4 empty 23872.000000000000000
    ST5 empty 186.50000000000000000
    ST6 empty 10752.000000000000000
    ST7 empty 0.0
                   3 2 1 0      E S P U O Z D I
    FST 0020  Cond 0 0 0 0  Err 0 0 1 0 0 0 0 0  (GT)
    FCW 027F  Prec NEAR,53  Mask    1 1 1 1 1 1

     
    Underlined is the actual source of the error (that call will throw the fatal error and crash the game).

    As we can see the dynamic function is part of a structure. Following that structure will be not at all useful since the fact the call is nonsense means likely the structure is also nonsense. However that structure is located by another pointer. This pointer appears to be computed by some very complicated spaghetti function.

    How to progress from here is to find when this function runs normally what its purpose is. Dumping a functional instance of the struct (as far as known) would help as it could possibly allow one to guess what object it represents and so where the error is coming from. The fact it is of considerable size (at least 318 bytes) means that this is no light weight structure as it holds a considerable amount of state information.
     
    Last edited: Aug 4, 2014
  10. Imp Midna

    Imp Midna

    Joined:
    May 6, 2013
    Messages:
    123
    Resources:
    0
    Resources:
    0
    Are you sure that it's that call that causes the crash? That seems a bit fishy to me:
    1: esi is a non-volatile register and therefor the call above does not modify it. Also, as can be seen in the beginning of the function, it's used to store the this* of this function.
    2: seeing how esi this the this*, we can be pretty sure that the call is a regular call to a virtual function. Since the virtual table is located in constant memory and modifying it would have crashed the game, and the compiler wouldn't compile a call to a non-existent function, this can only be an invalid number if either the class has been typecasted "up" (into an extended type that has functions that the actual object doesn't), which would be a major oversight to the max, or if blizzard somehow wrote *(DWORD*)(classPtr) = xyz, which allready looks incredibly wrong.
    3: calling an invalid function should crash when the memory has no execute access right (which it doesn't if its not even allocated). However, the errors complained about a missing write access right.

    To be honest, i can't even think of any way how an instruction could possibly write to itself as a result of an exploit; you can't write to or read from eip, so even getting the codes location is far from a trivial task.
     
  11. Dr Super Good

    Dr Super Good

    Spell Reviewer

    Joined:
    Jan 18, 2005
    Messages:
    24,630
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    1. Dynamic function call return point is the last stack frame before the thread raises a fatal error.
    2. The register it uses to determine the call jump location is set to the exact address that the fatal error message is reporting is trying to be "written" to.
    3. The address being called is not in the program code sections of memory. It is not even allocated in the heap (why it crashes). It may have been allocated in the heap at one stage as it is close to the top of the heap.

    ESI gets pushed multiple times onto the stack and I am not sure where it is getting popped. ESI itself is unimportant since itself is used as a pointer to lookup the actual pointer of a structure. This structure causes the crash meaning that retrieved structure is invalid. There are two possible causes for this, ESI pointing to invalid data or the address ESI points to is pointing to invalid data. In any cases the addresses used look like heap addresses but that could be coincidence.
    This is a false assumption. The same could could be generated by doing very stupid stuff with function pointers ("this" points to a pointer to a structure with a function pointer as a member). It could also be a virtual function call like you said but that helps little to track the error down. However something stupid like calling a virtual function on a destroyed member that has since been overwritten by other data would give the effects witnessed and not throw any compile errors and not even look stupid since nothing stops you calling a virtual function on an object that was deleted as long as the addresses resolved reside in an appropriate page.

    Except you are calling un-allocated pages. The error generation is done by a kernel level interrupt that eventually cascades to an error handler in user space. It is possible that the error handler or the error capture is reporting incorrect results in this case. The debugger I used captures the error itself displaying it as "does not know how to continue" so it is easily possible that the error report mechanisms is not designed to pickup on these errors. The stack dump WC3 makes confirms it is a dynamic function call gone wrong by the return address being present to the dynamic function call instruction which happens to be trying to call the same address reported in the error.

    Easily possible with memory garbage however certainly is improbable. Unless you force it to a certain address that you know will call it since usually the program files get loaded into similar pieces of memory based on how the OS generates processes.
     
    Last edited: Aug 5, 2014
  12. Imp Midna

    Imp Midna

    Joined:
    May 6, 2013
    Messages:
    123
    Resources:
    0
    Resources:
    0
    Guess you never stop learning :)

    considering that it was not the intention to do this, it's really not that easy to make a bug do this (easy and probability go hand in hand on this one). Anyways, i did a short test run (im kind of busy right now, stupid exams :goblin_cry:), and for me, the crashing instruction didn't even access itself (well, the crashing instruction doesn't even really exist, so i guess this is a quirk of the error message, which, as you explained before, seems to have problems with these kinds of errors in general.)

    Calling it a false assumption is a bold move when the alternative is so incredibly unlikely. In fact, i checked it: it really is the virtual table, and this really is a virtual call. For reasons unknown to me, the call right before the virtial call overwrites the virtual table with some nonsense (though it does not call msvcr.free or msvcr80.free). The Function it's supposed to call is Game.dll+69160 (seems to simply check a flag from a member), and if you restore the virtual table pointer using a debugger before the call, everything works totally fine. Can't wait for the weekend to find out why the heck they modify the virtual table :thumbs_up:
     
  13. Dr Super Good

    Dr Super Good

    Spell Reviewer

    Joined:
    Jan 18, 2005
    Messages:
    24,630
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    Depends how it over writes it. Does it do so in an array operation? Maybe it is copying some other object over the "this" object which was deleted so this gets replaced with garbage data. Could even be an invalid pointer (pointing to parts of this as it was previously a different object or that the object was deleted and overwritten so the pointer represents some other data).

    It would be so easy if we had the source code... We would not have to guess what is going on.