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 //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: //lms-dev.com/files/lua_functions_dump.txt

Exploring IV’s vehicle liveries

Hi,

I had a look at the vehicle livery system of IV earlier today. Yard1 – once again – asked me whether I could take a look at this, since he said IV would limit the amount of liveries to four per vehicle even if more than four textures were added to the WTD file.

Edit: Video: Click here.

So I launched IDA and took a look at the native function SET_CAR_LIVERY to find out how changing a livery works at all. The second argument for the native is the livery texture index, ranging from 0-3 normally. A quick back trace led to the following code:

mov ecx, [ebx+eax*4+CVehicleModelInfo.m_adwLiveryTextureHashes]
movsx edx, [ebx+CVehicleModelInfo.__parent.m_wTxdId]

 

The register EAX holds the index of the texture and since it’s multiplied by 4 we know each entry has the size of 4 bytes, a DWORD. When passing a value from 0-3 to the native, the name of the texture as a hash is returned. However when passing 4, we get CDCDCDCD, so unallocated memory. This leads to the conclusion that the game either didn’t load our 5th texture or that we’re dealing with an array of size 4. The latter is the case. We only have a dwHashes[3] here, so anything past 4 textures will simply not be stored and thus can’t be retrieved later. Note that higher values might lead to unexpected behavior, since no range check is done and the code will just grab the value from memory exceeding the array bounds.

How to allow more liveries then? Simply hook into the function and change the specific location to return the hash for modelName_sign_n to bypass the array limitation. This way it wil look up the texture later by hash (it’s loaded by the game already) and assign it to the vehicle. Using such a simpe hook, you can extend the allowed range to any number you like. I might post an example later which does this for you.

On another note, I’m currently doing a research project on the texture/model loading of the rage engine and how it is stored/used in EFLC with cp702 which is getting along pretty good so far. I hope to be able to tell you more about this soon!

Lennart

ELS 8 behind the scenes

Hello,

today I’d like to share the story behind the version 8 release of ELS and the techniques used. The other day, Yard1 sent me a message about the same old topic: ELS and its biggest problem, namely repairing the vehicle all the time. This topic has been discussed by me and Lt.Caine hundreds of times and we spent many days looking for possible solutions. I think it was back in 2011 when I first took a look at the issue, but I never really came up with a solution. My attempt back then was to kill the “repair” part of the repair function. Sounds great, right? It worked partly, the extras got enabled and disabled just fine and I was able to prevent windows from repairing and also managed to keep bulletholes. The car body was still repaired though and I gave up after a few weeks.

But this time it was different. I had done a lot of research since 2011 and I thought I might be able to get it to work this time. However, I knew my old approach of changing the repair code didn’t work, so I thought of something new. You have to understand that I have no experience at all with modelling, so I didn’t really know how adding custom extras for models worked. But I had a new idea, since Yard1 told me that the extra lights would act exactly the same as the indicator lights. So I thought, maybe I could clone them in memory. Put simply, that didn’t work out. While I was able to do all weird things possible with the indicators and other parts (change color, size, brightness, location) via memory hacking, I didn’t manage to make IV recognize the extras as indicators. That was my main idea, since I could toggle indicators. I had hoped making extras indicators would allow me to toggle them without repairing as well. But that didn’t work.

I was already starting to get annoyed again, when I had a small chat with NicolaiB. He explained to me in detail how the whole modelling thing works and what these extras are and encouraged me to get things going again. This time I had another idea: Why not enable all extras and then find a way to kill their render code? This way they would be hidden to the user, but the vehicle would not repair. After some research I was able to do exactly that: Disabling the rendering of an turned-on extra. So technically all extras would stay enabled, you just can not see that. I ported my quick and dirty assembler hacks to C++ and added some timer functions to make it look like a siren. And guess what? It worked perfectly! Below I’ve attached two screenshots of showing this work in progress (you might recognize them as being posted earlier on LCPDFR.com):

Lights by LMS #1

Lights by LMS #1

And the same situation a second later:

Lights by LMS #2

Lights by LMS #2

Some time after I got it working, I spoke to Lt.Caine about a possible ELS integration and I’m happy to announce that we’re working together on ELS 8!

Thanks to Yard1 and NicolaiB for their assistance with modelling knowledge and Lt.Caine for his ELS partnership. Also thanks Sam for his input.

Thanks for reading and stay tuned,

Lennart/LMS