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
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
Thanks for the kind words Adam! I think I’m making good progress so far and can share some more in the near future 🙂
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…
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.