Assassin's Creed Unity [Engine:AnvilNEXT64]

Status
Not open for further replies.
SunBeam

SunBeam

Administrator
Staff member
Administrator
Joined
Feb 4, 2018
Messages
3,483
Game Name: Assassin's Creed Unity
Game Vendor: ► UPlay ◄
Game Version: ► 1.5.0 ◄
Game Process: ACU.exe


Hello folks.

Given the high demand for this table to get updated, here you go. Revamped + an integrity check bypass - - thread-kill version - - based on the video tutorial and discussions in this article: https://fearlessrevolution.com/threads/9605/.

The table is designed for the current UPlay (don't have UPlay Plus, so don't ask) version 1.5.0. I understand that not everyone around here is playing this version, which sucks, but that's life. Know by the means of this post that it's the user's job to adapt to the table or trainer he wants to use, rather than complain it's not working for *his* version (yeah, *hers* too). Please don't request making it compatible with "your version"; just so it's said and known up-front.

I'm leaving below some version-related information extracted from ACU.exe:

Code:
ChangeList:1102304
Version:DEV
User:artem.kotsiuba
Branch://assassin/acu/pc
Project Name:ACUPC
Time:Wed Feb 11 08:26:17 2015
SDK:N/A
Exec:scimitar_engine_win64_f.exe
MD5:be2a570d5fbd8cd1617258f009a88a0d
DataCL:335689
SoundCL:33060
DataCL:335689
SoundCL:33060
As you can read from above, the binary was last compiled in 2015. I understand you will look at your ACU.exe and see it was 'last modified' when you downloaded it. However, if you open up the executable in a PE editor (e.g.: CFF Explorer) you will see this in the File Header field:



If you copy that DWORD, then open up Calculator and convert hex to decimal, you would get this:



54DB5826‬ (hexa) == 1423661094 (decimal)

And lastly, if you go to this site: https://www.unixtimestamp.com/index.php and type in the decimal above for conversion, you will get this:



And that's how you find out a file's timestamp. Hope you learned something out of this.

Now.. that being said, statements like "the recent UPlay update" should not exist in your vocabulary. The game hasn't been updated since 2015. That doesn't mean Ubisoft might not pull a fast one like they did with Syndicate, removing "the DRM", as you people seem to call VMProtect. Yeah, I insist it's called by its name, because if you look-up DRM vs. VMProtect on google, you will get better results and leads to approach the protection (cuz that's what it is) than learning what DRM means (and that's all you'll learn).

Instructions:
  • Run the game and get to main menu. Then alt-tab.
  • Open CE, target ACU.exe process. Don't know how to? Learn how to use CE: https://www.wikihow.com/Use-Cheat-Engine.
  • Open ACU.CT cheat table. Don't see the .CT extension? See here why: https://www.thewindowsclub.com/show-file-extensions-in-windows.
  • Run [ Bypass Integrity Checks ] script. It will take a few seconds; you will see a pop-up when it's done, sign that everything worked out fine and the script will become active.


    If nothing happens and the script doesn't activate, then, assuming you've opened ACU.exe process in CE, you either already killed the thread (perhaps you're testing to see if it runs again?) -OR- have a different version of the game (it's important to know that I specifically said the UPlay 1.5.0 version, as Ubisoft compiles different builds for different game platforms: Steam, UPlay, Origin, etc) -OR- see the 2 suggestions at the bottom, regarding UAC and Administrator privileges.
  • The success of the above script will open up a sub-list of other scripts. Which I'm currently reviewing to bring them up to my latest standards. Will update this post as I progress.

If you have any other problems with CE or the table, apart from "script not working", please try the below:

Emphasis on the word 'try'. Don't say I forced you to do so and now, because of this, your PC is fucked. I won't tolerate such an attitude, especially from clueless people who don't plan on getting documented what the above mean or do, but quickly jump to the conclusion that, considering either of the above is the last thing they did, then that surely is the cause for their PC not working fine now T_T.

Lastly, if you think my post is condescending and/or rude, you can bite me :) It means you really don't care much for anything explained above; just download the table and be done with it. Talks about how I write, how I behave, how that might be perceived and all that e-psychology-101 bullshit don't bring any value to either you or me.

Best regards,
Sun

P.S.: Yes, table is not yet posted. Review in progress.


How to use this cheat table?
  1. Install Cheat Engine
  2. Double-click the .CT file in order to open it.
  3. Click the PC icon in Cheat Engine in order to select the game process.
  4. Keep the list.
  5. Activate the trainer options by checking boxes or setting values from 0 to 1
 
SunBeam

SunBeam

Administrator
Staff member
Administrator
Joined
Feb 4, 2018
Messages
3,483
Integrity Check bypass explanation:

Lua:
-- create a stringlist class object to hold future thread ids as strings
local tl = createStringlist()

-- fill the stringlist object with the threadlist of the currently opened process
getThreadList( tl )

-- before going into the loop, time for some declarations

-- we will make use of several APIs, hence CE needs to know their addresses; so..
local OpenThread = getAddressSafe( "OpenThread" )
local NtQueryInformationThread = getAddressSafe( "NtQueryInformationThread" )
local TerminateThread = getAddressSafe( "TerminateThread" )
local CloseHandle = getAddressSafe( "CloseHandle" )
-- note that I'm not checking any above in the next part of the code for NULLs
-- I really hope you're doing this after you've opened up ACU.exe in CE

-- do a quick search for "#define THREAD_ALL_ACCESS" on google and you will find what its value is
-- e.g.: https://bbs.pediy.com/thread-89713.htm
local THREAD_ALL_ACCESS = 0x001F03FF
-- we're going to use this with OpenThread

-- do a quick search for "#define ThreadQuerySetWin32StartAddress" on google and you will find what its value is
-- e.g.: https://stackoverflow.com/questions/24728979/ntqueryinformationthread-sometimes-fails-no-error-code
local ThreadQuerySetWin32StartAddress = 0x9
-- we're going to use this with NtQueryInformationThread

-- we'll use this in the loop to store the text-to-number converted thread id
local thread_id
-- we'll use this in the loop to store the handle to the thread
local thread_handle
-- we'll use this in the loop to store our NtQueryInformationThread result, the thread's Entry address
local dwStartAddress = allocateMemory( 0x1000 )
-- we'll use this to check NtQueryInformationThread's result
local nt_status

-- we'll need this in the loop, to check if the thread's Entry address matches the one we know
local module_base = getAddressSafe( process )
-- ACU.exe+275DE50 - E9 E5F11803           - jmp ACU.exe+58ED03A
local func_addr = module_base + 0x275DE50
-- yes, the above will be most likely different in any other executable; replace it with the one you'd find based on my video tutorial

-- now we want to loop all list items, from first till last and..
for i = 1, tl.Count do
  -- ..open each thread with THREAD_ALL_ACCESS parameter
  -- each string in the list needs to be converted to a number before being used
  thread_id = tonumber( tl[i], 16 ) -- no idea if you'd get ids past 0xFFFF; but just in case
  -- ..then we want to obtain a handle to the thread via OpenThread, using the id with THREAD_ALL_ACCESS privileges
  thread_handle = executeCodeEx( 0, nil, OpenThread, THREAD_ALL_ACCESS, 0, thread_id )
  -- according to this post on stackoverflow: https://stackoverflow.com/questions/3528111/how-to-find-the-entry-point-of-a-specific-thread-in-windows
  -- we can get the Entry of a thread using NtQueryInformationThread with ThreadQuerySetWin32StartAddress parameter; so..
  -- the API proto taken from some C++ code is: NTSTATUS ntStatus = NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD), NULL);
  -- we're on x64, so we need QWORD instead of DWORD, meaning 8 bytes instead of 4; so sizeof(QWORD) == 0x8
  -- then we need a dwStartAddress; & indicates this is where the information will be returned by the API, thus a buffer; that's why we allocated it up top
  -- time to run NtQueryInformationThread
  nt_status = executeCodeEx( 0, nil, NtQueryInformationThread, thread_handle, ThreadQuerySetWin32StartAddress, dwStartAddress, 0x8, 0 )
  -- the result should be NT_SUCCESS == 0x0; we want to skip any other statuses
  if nt_status == 0x0 then
    -- now we want to check if the thread Entry address is the one we're looking for, the one we KNOW
    if readQword( dwStartAddress ) == func_addr then
      -- if it's our address, then..
      -- ..terminate the thread based on thread_handle obtained in the loop from thread_id
      local t = executeCodeEx( 0, nil, TerminateThread, thread_handle, 0 )
      -- and close the current open handle before exiting 'for' loop
      executeCodeEx( 0, nil, CloseHandle, thread_handle )
      showMessage( string.format( "VMProtect Integrity Check thread with id: 0x%X killed.", thread_id ) )
      break
    end
  end
  -- then close the current open handle
  executeCodeEx( 0, nil, CloseHandle, thread_handle )
end
-- clean-up the allocation
deAlloc( dwStartAddress )
 
Status
Not open for further replies.
Top