Maya Copeland

| git | posts | email: me -at- maya -dot- cx

Playing around with the Dead by Daylight API

First of all, I would like to thank Andrei Baciu for helping out on this project, especially for helping out with writing a CDN decryptor.

Firstly, if you've never heard of Dead by Daylight, it's an asymmetrical horror game (4vs1) that has been around since 2016,
and the game is no stranger to hacks and exploits with a lot of top players facing cheaters seemingly everyday.
In this post I will explain how the API for the game works and how myself and a friend were able to submit fake matches played in order to recieve rewards for challenges from previous updates.

Logging into the API

The game has multiple endpoints for accessing the API, one for every platform (e.g steam.live.bhvrdbd.com), the one that we used for the aforementioned challenge completer.
In order to access the steam endpoint you need to find a library that has the ability to generate a steam access ticket, this will be used for authenticating yourself as if you are the games' client.

       example POST request to get your BHVR authentication token:
       curl -X POST -H "token: {steamaccesstickethere}" "https://steam.live.bhvrdbd.com/api/v1/auth/provider/steam/login"
      

Decoding data from the API

Different endpoints on the API use different forms of encoding, these have prefixes such as "DbdDAgAC" which is used for a users' save profile or "DbdDAQEB" which specify that it's compressed.
The game stores all of the decryption keys for every game version within an ini file inside its' pak files, so finding it wasn't too hard, I used fmodeland extracted the configs using it.

Here is an example of a function that is able to decode data from the API, put elsewhere for conciseness.

Submitting fake matches

Now that we have the ability to decode data from the API, it's time to scrape for every single challenge, thankfully BHVR make this very easy
with the fact that they store it on their CDN, cdn.live.bhvrdbd.com at /clientData/4fabea45-bce0-4461-8950-162659636437/content/{game_version}/archiveQuests/Tome{id}.json.
At the time of writing, there's only 17 sets, so in our sofware we hardcoded that limit to 17, and just loop from 1 through 17.

The endpoint for selecting challenges is /api/v1/archives/stories/update/active-node-v3 and to select a challenge you need to make a POST request with the following body:

      "node": {
        "level": -tome's level-,
        "nodeId": -id of the challenge-,
        "storyId":  -id of the tome-,
      },
      "role": -killer/survivor/both-
    

Once you do this, you can go ingame and see that the challenge was selected. Now onto submitting the fake match,
the endpoint for which is: /api/v1/archives/stories/update/quest-progress-v2, make a POST request with the following body:
    {
      matchId: -random uuid generated here-,
      "questEvents": [{
        // this is an array of an object of all the events for a given challenge
        repetition: -amount of times you need to do it-,
        questEventId: -event id, will be in the object from either the CDN or the active node setter-
        parameters: -paramaters to complete it (if exists)-
      }],
      role: -killer/survivor/both-
    }
  

And now, you should be able to successfully submit fake matches in order to complete tomes on Dead by Daylight!











      ooo. .oo.  .oo.    .oooo.   oooo    ooo  .oooo.        .ooooo.  oooo    ooo 
      `888P"Y88bP"Y88b  `P  )88b   `88.  .8'  `P  )88b      d88' `"Y8  `88b..8P'  
       888   888   888   .oP"888    `88..8'    .oP"888      888          Y888'    
       888   888   888  d8(  888     `888'    d8(  888  .o. 888   .o8  .o8"'88b   
      o888o o888o o888o `Y888""8o     .8'     `Y888""8o Y8P `Y8bod8P' o88'   888o 
                                  .o..P'                                          
                                  `Y8P'