Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cohaereo committed Jun 6, 2022
0 parents commit 8c60555
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### DestinyDecryptionKeyFinder

Quick and dirty client-side tool to find packet decryption keys from a Destiny memory dump
153 changes: 153 additions & 0 deletions finder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const SEARCH_STRING = "GSFARM35011";
const STRING_OFFSET = 0x01890b39;
const CIPHERCONTEXT_ADDR = 0x01b951b0;

const CIPHERCONTEXT_ADDR_RELATIVE = CIPHERCONTEXT_ADDR - STRING_OFFSET;

const SEARCH_CHUNK_SIZE = 0x10000;

function findCipherContext(reader, baseStringAddr) {
var reader = new FileReader();
reader.seek(baseStringAddr + CIPHERCONTEXT_ADDR_RELATIVE);

var cipherContext = reader.read(92);
}

function findStringInBlock(block, searchString) {
for (var i = 0; i < block.length - searchString.length; i++) {
for (var j = 0; j < searchString.length; j++) {
let byte1 = block[i + j];
let byte2 = searchString.charCodeAt(j);
if (byte1 != byte2) {
break;
}

if (j === searchString.length - 1) {
return i;
}
}
}

return -1;
}

function findTreasureKeys(file, callback) {
var offset = 0;
var fileSize = file.size;

var reader = new FileReader();
reader.onload = function (e) {
var data = new Uint8Array(e.target.result);

let findRes = findStringInBlock(data, SEARCH_STRING.slice(0, 10));
if (findRes !== -1) {
console.log("Found treasure keys at offset: " + (offset + findRes));
let cipherContextAddr = offset + findRes + CIPHERCONTEXT_ADDR_RELATIVE;
readCipherContext(cipherContextAddr);
return;
}

offset += SEARCH_CHUNK_SIZE;
if (offset >= fileSize) {
callback(-1);
return;
}

readBlock(offset);
};

function readBlock(offset) {
reader.readAsArrayBuffer(file.slice(offset, offset + SEARCH_CHUNK_SIZE));
}

function readCipherContext(offset) {
var reader = new FileReader();
reader.onload = function (e) {
let keyData = new Uint8Array(e.target.result);
callback(offset, keyData);
};

reader.readAsArrayBuffer(file.slice(offset, offset + 76));
return;
}

readBlock(offset);
}

function setResultBox(type, text, isCode) {
var resultBox = document.getElementById("result");
resultBox.classList = "alert alert-" + type;
if (isCode) {
resultBox.classList += " font-monospace";
}

resultBox.style.display = "block";
resultBox.innerText = text;
}

function toHexString(byteArray) {
return Array.from(byteArray, function (byte) {
return ("0" + (byte & 0xff).toString(16)).slice(-2);
}).join("");
}

function decodeCipherContext(data) {
var resultText = "";

var dv = new DataView(data.buffer);
let unk1 = dv.getUint32(0, false);
let cipher = dv.getUint32(4, false);
let keylen = dv.getUint32(8, false);
let key = data.slice(12, 12 + keylen);

let hmac_key = data.slice(0x24, 0x24 + 16);

resultText += "cbc_unk1: " + unk1 + "\n";
resultText += "cbc_cipher: " + cipher + "\n";
resultText += "cbc_keylen: " + keylen + "\n";
resultText += "cbc_key: " + toHexString(key) + "\n";
resultText += "\n";
resultText += "hmac_key: " + toHexString(hmac_key) + "\n";

resultText += "\n";
resultText += "raw: " + toHexString(data) + "\n";

return resultText;
}

function dropHandler(ev) {
console.debug("File(s) dropped");

ev.preventDefault();

if (ev.dataTransfer.items) {
if (ev.dataTransfer.items[0].kind !== "file") {
setResultBox("danger", "Dropped item is not a file");
return;
}

var file = ev.dataTransfer.items[0].getAsFile();

setResultBox(
"primary",
"Searching file, please wait\n(this may take a while depending on the file size)"
);
findTreasureKeys(file, function (cipherContext, data) {
console.log(cipherContext);
if (cipherContext === -1) {
setResultBox("danger", "Could not find decryption keys");
return;
}

if (data) {
let resultText = decodeCipherContext(data);
setResultBox("success", "Found decryption keys:\n" + resultText, true);
console.log(data);
}
});
}
}

function dragOverHandler(ev) {
ev.preventDefault();
}
41 changes: 41 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="finder.js"></script>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor"
crossorigin="anonymous"
/>
<title>V4nguard Key Extractor</title>
</head>
<style>
html,
body {
background-color: #001;
height: 100%;
}
</style>
<body>
<div class="container-fluid" style="padding-top: 16rem">
<div class="d-flex justify-content-center" style="color: #fff">
<div
id="drop_zone"
ondrop="dropHandler(event);"
ondragover="dragOverHandler(event);"
class="d-flex justify-content-center align-items-center rounded-5 mb-3"
style="width: 32rem; height: 16rem; border: 0.5rem dashed #fff;" >
<b>Drag file here</b>
</div>
</div>
<div class="d-flex justify-content-center mt-3">
<div class="alert alert-primary" id="result" role="alert" style="max-width: 64rem; overflow-wrap: break-word;">
Waiting for file...
</div>
</div>
</body>
</html>

0 comments on commit 8c60555

Please sign in to comment.