-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8c60555
Showing
3 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |