Watch Dogs Lua Engine Hook #2

I’ve continued working on my script hook for Watch Dogs and now also added support for GetAsyncKeyState in lua. Also, as it can be very handy, I allow lua scripts to run in a loop now, since each is spawned in a new thread. This allows code like this:


while true do
-- Change time when C is down
local result = wdHook.GetAsyncKeyState(67);
if (result == 1) then
test:SetScriptedTimeOfDay(18, 00);
end

wdHook.Wait(50)
end

Quite useful, right?

D3D11 hook

In addition, I got a basic D3D11 hook working, so I’m now able to draw on the rendered image (upper left corner):

Watch_Dogs2014-6-16-22-59-59

I need to move this into a lua callback to add drawing support for lua too, but that shouldn’t be too hard to implement. Once I got that working I’ll do some final tests and then hope to release my hook for all the scripters out there! πŸ™‚

For those of you trying to get ad3d11 hook to work, keep in mind you need to save the jmp Steam places in the function, for instance atΒ D3D11Present. I do this by reading the target address of the Steam call, adding the current location (RIP) to get the full address and then executing something like this:


mov rax, addr
jmp rax

This will keep the Steam overlay working and you can still use your own hooked function by executing it right before.

Furthermore, if you have trouble detouring D3D11DrawIndexed, this might help you (reversed to C++ from original WD implementation):


DWORD64 dwContext = (DWORD64)pContext + 0x0009C08;
D3D11DrawIndexedHook dwCallTarget = (D3D11DrawIndexedHook)*(DWORD64*)(pContext + 0x8D);
return dwCallTarget((ID3D11DeviceContext*)dwContext, IndexCount, StartIndexLocation, BaseVertexLocation);

Happy coding!

29 thoughts on “Watch Dogs Lua Engine Hook #2

  1. xiaoxiao921

    Hey dude, still coding on this game ?
    I’m trying to launch some lua script, can do basic thing like change day time, give cash, invincibility, refill focus/battery
    my last try was changing weather but i didn’t managed to do it. Can you help me ?
    I found this in game file :

    EnvironmentEvent = {}
    function EnvironmentEvent:Create(cbox)
    end
    function EnvironmentEvent:Init(cbox)
    end
    function EnvironmentEvent:ShutDown()
    end
    function EnvironmentEvent:Start()
    local Started = self.Started
    local Out = self.Out
    self.FadeIn = self.FadeIn or 30
    if self.PresetName ~= nil and self.FadeIn ~= nil then
    BeginEnvironmentEvent(self.PresetName, self.FadeIn)
    end
    Started(self)
    Out(self)
    end
    function EnvironmentEvent:Stop()
    local Stopped = self.Stopped
    local Out = self.Out
    self.PresetName = self.PresetName or "Clear"
    self.FadeIn = self.FadeIn or 30
    if self.PresetName ~= nil and self.FadeIn ~= nil then
    EndEnvironmentEvent(self.PresetName, self.FadeIn)
    end
    Stopped(self)
    Out(self)
    end
    function EnvironmentEvent:SetCloudIntensity()
    local CloudIntensitySet = self.CloudIntensitySet
    local Out = self.Out
    if self.CloudIntensity ~= nil and self.CloudTransitionTime ~= nil then
    SetProjectedCloudsIntensity(self.CloudIntensity, self.CloudTransitionTime)
    end
    CloudIntensitySet(self)
    Out(self)
    end
    export = EnvironmentEvent
    EnvironmentEvent = nil

    My lua script is like this :
    BeginEnvironmentEvent(Storm, 999);

    Storm is a valid preset i found it on mission lua file but it’s not working.

    Reply
  2. xiaoxiao921

    wow nevermind i’m bad i forgot to put ” ” for Storm. lol
    By the way how do you spawn vehicle or firetruck ?

    Reply
  3. xiaoxiao921

    Last question i got, are the domino/user made .lua file like missions (huge script you know with cbox shit) even usable ? Never found a way to make them work lol.

    Reply
    1. LMS Post author

      No I’m not doing any modding an W_D anymore. To spawn entities I used some function called SpawnEntityFromArchetype, like this: SpawnEntityFromArchetype(“{607c45e6-715f-4b2b-af55-d7f38e5866ab}”, GetEntityPosition(GetLocalPlayerEntityId(), 0), GetEntityPosition(GetLocalPlayerEntityId(), 1), GetEntityPosition(GetLocalPlayerEntityId(), 2), 0, 0, 0)

      However, as you can see, the names are obfuscated/hashed and have to be obtained from the game files. I think those are the normal game scripts and you can use them to get a better understanding of the scripting, but yes, without the proper initialization (cbox) you can’t really use them.

      Reply
  4. xiaoxiao921

    You may be the best out there sadly you are not modding the game anymore and i don’t understand a thing about some of their code work. Dunno if you have still the time to help and sorry if i disturb you but i need to ask. D:

    How they call ParticleFX etc :
    http://pastebin.com/dqqhwDJn

    How the particlefxcontroller_v2.lua file look like :
    http://pastebin.com/UHir3myD

    I don’t even know what to write for the self.ParticleEmitter thing (well i know i need to put the FX there but i really doubt typing the name fx or number work or its hash-thing-idontknowtofindit again ? And how they do to put the fx at a given position ?
    If you find how, i need to tell you you’re a fuckin god.
    Thanks in advance

    Reply
    1. LMS Post author

      The call probably is executed like this: CDominoManager_GetInstance():SendRegisteredEventToEntity(“2076459883833590438”, “CNewParticlesComponent_PlayParticles”) (for GasPumpExplosionFX_1), so that should work fine I guess. I don’t even have the game installed anymore, so can’t do any testing sorry. I might be wrong, but I could imagine the position is associated to the FX effect. But I’m not sure about that.

      Reply
  5. xiaoxiao921

    Not working. The thing is how they get numbers like these “2076459883833590438” etc ? Maybe this number is not valable in this context ?

    Reply
    1. LMS Post author

      Could be. I have absolutely no idea how the numbers work, I had a quick look at the hash function back then, but never really made a breakthrough. Many things use hashes, even spawn points etc., pretty confusing.

      Reply
  6. rengareng

    Hi,
    I’ve tried to find code that decompress or decrypt(I dont know) language files(.loc files) in watch dogs. Using tools in http://svn.gib.me/builds/disrupt/, unpacked .loc files. Here the unpacked loc file http://www65.zippyshare.com/v/82977719/file.html. I’ve tried IDA x64 Pro to trap executable, when it comes to a code in Disruptx64.dll it says ‘close debugging tool and exits from the program’. Do you know to bypass this security? Thank you very much.

    Reply
    1. LMS Post author

      Hey,
      iirc the protection was very weak and could be bypassed by simply setting the PEB debugging flag accordingly/patching IsDebuggerPresent. Example:


      DWORD64 dwAddr = (DWORD64)GetProcAddress(GetModuleHandleA("KERNELBASE.dll"), "IsDebuggerPresent");
      DWORD dwVirtualProtectBackup;
      bool result = VirtualProtect((BYTE*)dwAddr, 0x20, PAGE_READWRITE, &dwVirtualProtectBackup);
      if (result)
      {
      *(BYTE*)(dwAddr) = 0xB8;
      memset((BYTE*)(dwAddr + 0x1), 0x0, 0x4);
      *(BYTE*)(dwAddr + 0x5) = 0xC3;
      VirtualProtect((BYTE*)dwAddr, 0x20, dwVirtualProtectBackup, &dwVirtualProtectBackup);
      }

      This will make IsDebuggerPresent always return zero.

      Reply
        1. LMS Post author

          Inject a DLL into the process before debugging. There are probably plugins for IDA that do this too, but I’m used to patch things manually.

          Reply
  7. essenthy

    Hey Lms

    thanks for the reply, i actually have the vanilla backup version of the game and another updated version, since am moding the game graphically i always keep a vanilla version aside and check if the updates dont break my mods, so for peoples like me it shouldnt be a problem

    i am trying to load the E3 trailers 2012 & 2013 and other scripts ingeneral , but unfortunately i have no idea of exactly of lua language work, am just guessing by reading the code, i tried to use an injector and also tried swapping lua files of existing main mission since the game will try to load them no matter what, for example i swapped re_launch2013.main.lua with clara mission_06 act1 ,but aiden freez in place and nothing happen, any guess on how i could load these scripts ?

    Reply
    1. LMS Post author

      If you have an injector you should be able to simply load the plain .lua file. That’s exactly what I do as well. However they might require certain globals or other stuff to be set in order to work, I’m not sure. But this will vary per script. You could try adding a command that you know will work at start to see if they get loaded properly.

      Reply
      1. essenthy

        i tried loading plain lua files using the injector , but nothing happens, but i can change weather and simple stuff like that with the injector, so it kind of work …
        i though maybe the game need to be in debug mode ? or the player ID must have some kind of superior level of lua execution privilege ?

        what happen if the lua script ask to load some audio files and the files arnt there for example ? will it freez or just continue and jump to the next task ?

        Reply
        1. LMS Post author

          Well, you can try as I said and see what happens when you place the weather stuff at the very beginning of the scripts you want to load to see if they get parsed properly at all. I don’t think it needs to be in debug mode or anything, but maybe it requires other files (I think they had something like #include, but not sure) to work correctly. It’s quite some time since I last worked on W_D, so I can only guess.

          Reply
  8. essenthy

    BTW her’s the init file of the 2012 demo that lead to the main lua file of the demo ( wich in turn load 3 other lua part that exist right there )

    http://pastebin.com/pKzhwEsC

    i check every single lua script in this init lua, and they are all there, except for the sound i think

    Reply
    1. LMS Post author

      Yeah I see, it has all this cbox stuff and different functions which have to be called. Not sure how you can get this to work, I have no experience with the cbox stuff. My only idea would be to modify the top of the script and call Create, Init etc. to simulate execution, if you get what I mean. But it might fail because it’s missing some stuff, not sure.

      Reply
  9. essenthy

    ok thanks LMS ! will try all of that , the weird thing is that when i look into main mission init files, they look nearly exactly the same as the e3 stuff, they use the same commands ect .. it just different luas

    Reply
    1. LMS Post author

      Yes, they all seem to share the same basic layout. But just like you, I wondered back then how the cbox stuff is invoked.

      Reply
  10. xiaoxiao921

    Hey, do you remember how you did to get the firetruck hash ? SpawnEntityFromArchetype(β€œ{607c45e6-715f-4b2b-af55-d7f38e5866ab}”

    Want to try some other vehicle πŸ˜‰

    Reply
  11. Adam

    Hi,

    In the line where you have written wdHook.GetAsyncKeyState(67), how are you getting wdHook to access the GetAsyncKeyState function ?? Am using the injector in game and it says Run error when it encounters this line

    Reply
    1. LMS Post author

      This hook is very outdated and does not work on the latest game version. In any case, this is a function of the wdHook instance.

      Reply
      1. Adam

        Thanks, I have the hook working for the latest game version, am able to inject the scripts as well. The interesting thing is how you are able to paint that “Hello World” on the screen. I mean, I am using it as wdHook.DrawString(“Hello World”), but that isnt drawing anything on the screen.

        Now, I did check the syntax for that – D3D11Hook::DrawString(buffer, fontSize, x, y, color)

        I haven’t changed anything in this actually, so, is there something am doing wrong in terms of the DrawString function?

        Reply

Leave a Reply to Adam Cancel reply

Your email address will not be published. Required fields are marked *