Watch Dogs: First RE impressions

Hello,

so yesterday I started messing around with Watch Dogs and its Disrupt engine. The main code is located in Disrupt_b64.dll, but it’s packed. To unpack, simply attach IDA to the process and dump the loader segments. The following information is based on my base address: 000007FB46240000

Lua base functions

Watch Dogs makes heavy use of lua, almost all things internally are scripted using it. The lua base functions can be found at 000007FB4906FEA0. You’ll find something along these lines:


.rdata:000007FB4906FEA0 baseFuncs       dq offset aAssert       ; DATA XREF: sub_7FB47A528C0+27o
.rdata:000007FB4906FEA0                                         ; "assert"
.rdata:000007FB4906FEA8                 dq offset luaB_assert
.rdata:000007FB4906FEB0                 dq offset aCollectgarbage ; "collectgarbage"
.rdata:000007FB4906FEB8                 dq offset luaB_collectgarbage
.rdata:000007FB4906FEC0                 dq offset aDofile       ; "dofile"
.rdata:000007FB4906FEC8                 dq offset luaB_dofile
.rdata:000007FB4906FED0                 dq offset aError_1      ; "error"
.rdata:000007FB4906FED8                 dq offset luaB_error
.rdata:000007FB4906FEE0                 dq offset aGcinfo       ; "gcinfo"
.rdata:000007FB4906FEE8                 dq offset luaB_gcinfo

These are the core lua functions and it’s useful to name them and also have a look at how they work (source can be found here to help understanding them http://www.lua.org/source/5.1/lbaselib.c.html)

Lua scripting functions

The lua scripting functions start with GetBaseHealth at 000007FB48E7F300 and look like this:


.rdata:000007FB48E7F300 off_7FB48E7F300 dq offset aGetbasehealth
.rdata:000007FB48E7F300                                         ; DATA XREF: .text:000007FB46632DE0o
.rdata:000007FB48E7F300                                         ; .text:000007FB46638130o
.rdata:000007FB48E7F300                                         ; start of lua scripting functions
.rdata:000007FB48E7F308                 dq offset lua_GetBaseHealth
.rdata:000007FB48E7F310                 dq offset aGetcurrentheal ; "GetCurrentHealth"
.rdata:000007FB48E7F318                 dq offset lua_GetCurrentHealth
.rdata:000007FB48E7F320                 dq offset aIsalive      ; "IsAlive"
.rdata:000007FB48E7F328                 dq offset lua_IsAlive
.rdata:000007FB48E7F330                 dq offset aIsdead       ; "IsDead"
.rdata:000007FB48E7F338                 dq offset lua_IsDead

Mapping the functions

This might be just plain data for you in IDA due to the dump, but my following IDC script should help you finding all offsets and assigning all function names:


auto base = 0xSTART;
auto end = 0xEND;
auto c = (end - base) / 8;
auto i;
auto adr;
auto name;
auto ref;
auto lastWasString;
for (i=0;i<c;i++)
{
        adr = base + i*8;
        MakeQword(base + i*8);
        if (GetSegmentAttr(adr, SEGATTR_TYPE) != 3)
        {
                SetSegmentType(base + i*8, 3);
        }

        // Check if string
        Message("Checking %x", adr);
        ref = Qword(adr);
        Message(" -- ref: %x", ref);
        auto type;
        type = GetStringType(ref);
        Message(" -- stringType: %x", type);
        if (type == 0)
        {
            Message("--> IsString");
            auto string;
            string = GetString(ref, -1, 0);
            Message(" -- %s", string);
            lastWasString = 1;
            name = string;
        }
        else
        {
            lastWasString = 0;
        }
        
        // If no string, try to make code at target location
        if (!lastWasString)
        {
            auto result;
        
            // If no code
            if (GetSegmentAttr(ref, SEGATTR_TYPE) != 2)
            {
                result = MakeCode(ref);
                Message("-- MakeCode: %x", result);
            }
            
            // Try making function
            result = MakeFunction(ref, BADADDR);
            Message("-- MakeFunction: %x", result);
            
            // Rename
            auto tempName = "lua_" + name;            
            result = MakeName(ref, tempName);
            Message("-- MakeName: %x", result);
        }
        
        Message("\n");
}

Just edit start/end at the top to match it to your offsets and let it run. This may take quite a while and will also toggle some IDA reanalysis afterwards, because it creates code out of data segments. But as a result, you get some nice looking lua functions properly named.

Lua functions dump

For those of you interested, here are some functions dumped from memory with their address: http://lms-dev.com/files/lua_functions_dump.txt

4 thoughts on “Watch Dogs: First RE impressions

  1. AdamP

    LMS,
    it was extremely interesting to read about getting deeper into the Watch Dogs, I hope your knowledge will open a door of using this game as a base for modders. I’m looking forward to see further articles, it’s a huge enjoyment for me to read them after a busy day.

    Best regards!
    Adam

    Reply
    1. LMS Post author

      Thanks for the kind words Adam! I think I’m making good progress so far and can share some more in the near future 🙂

      Reply
  2. Leftas

    Was looking at your lua dump. And saw that Ubisoft Montreal are lazy to take function whick was used in E3:
    IsE3StageDemoNoCompanion.
    And I want to thank you for you effort: for finding D3DX(D3D11) hook, also for lua hook(I will try to find where to hook too :D), even I hate lua(JI don’t like its coding style) I will try to do something with your hook…
    P.S. About D3D11 hook, What about hooking SwapChain(I know that it’s using by Steam and maybe uplay) Because hackers/cheaters/programmers/modders, find useful to hook swapchain::present…

    Reply
    1. LMS Post author

      Yes, they were too lazy, but at first glance in IDA it seems the function always returns 0 now, so it was probably a special build returning 1 as constant.
      Thanks, I don’t really like lua too, though it makes scripting in this case pretty easy via its loadfile/pcall functionality. I hook Present already, if you check my latest post here I can draw on the screen just fine. But I need to port it to lua still.

      Reply

Leave a Reply

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