Last active
April 5, 2020 11:21
-
-
Save xps3riments/3262b2d4ada03f1ea612b5c8c4ddaab4 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
<html> | |
<head> </head> | |
<body> | |
<script src="object.keys.js"></script> | |
<script src="xRegistry.js"></script> | |
<script> | |
// Change ip here to reflect you PS3 ip | |
// Navigate this page in the browser to see the result in the console | |
// (WORKS ON PS3) Desktop used only to access to the console | |
console.log( | |
new XRegistry().load("http://xxx.xxx.xxx.xxx/dev_flash2/etc/xRegistry.sys") | |
); | |
// Uncomment for PS3 does not need a url | |
// alert( | |
// new XRegistry().load().settings.system.nickname | |
// ); | |
</script> | |
</body> | |
</html> |
This file contains hidden or 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
// https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/keys | |
if (!Object.keys) { | |
Object.keys = (function() { | |
"use strict"; | |
var hasOwnProperty = Object.prototype.hasOwnProperty, | |
hasDontEnumBug = !{ toString: null }.propertyIsEnumerable("toString"), | |
dontEnums = [ | |
"toString", | |
"toLocaleString", | |
"valueOf", | |
"hasOwnProperty", | |
"isPrototypeOf", | |
"propertyIsEnumerable", | |
"constructor" | |
], | |
dontEnumsLength = dontEnums.length; | |
return function(obj) { | |
if ( | |
typeof obj !== "object" && | |
(typeof obj !== "function" || obj === null) | |
) { | |
throw new TypeError("Object.keys called on non-object"); | |
} | |
var result = [], | |
prop, | |
i; | |
for (prop in obj) { | |
if (hasOwnProperty.call(obj, prop)) { | |
result.push(prop); | |
} | |
} | |
if (hasDontEnumBug) { | |
for (i = 0; i < dontEnumsLength; i++) { | |
if (hasOwnProperty.call(obj, dontEnums[i])) { | |
result.push(dontEnums[i]); | |
} | |
} | |
} | |
return result; | |
}; | |
})(); | |
} |
This file contains hidden or 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
// tslint:disable: arrow-parens | |
// tslint:disable: trailing-comma | |
// tslint:disable: variable-name | |
var BinaryReader = /** @class */ (function () { | |
function BinaryReader(url, pos) { | |
if (pos === void 0) { pos = 0; } | |
this.pos = pos; | |
this.data = this.load(url); | |
} | |
BinaryReader.prototype.load = function (url) { | |
var req = new XMLHttpRequest(); | |
req.open("GET", url, false); | |
req.overrideMimeType("text/plain; charset=x-user-defined"); | |
req.send(null); | |
if (req.status !== 200) { | |
return ""; | |
} | |
return req.responseText; | |
}; | |
BinaryReader.prototype.read = function (len) { | |
var _this = this; | |
var result = Array.apply(null, Array(len)) | |
.map(Number.prototype.valueOf, 0) | |
.map(function (_, index) { | |
// tslint:disable-next-line:no-bitwise | |
return _this.data.charCodeAt(_this.pos + index) & 0xff; | |
}); | |
this.pos += len; | |
return result; | |
}; | |
BinaryReader.prototype.seek = function (offset) { | |
this.pos = offset; | |
}; | |
BinaryReader.prototype.tell = function () { | |
return this.pos; | |
}; | |
return BinaryReader; | |
}()); | |
// tslint:disable-next-line:max-classes-per-file | |
var XRegistry = /** @class */ (function () { | |
function XRegistry() { | |
} | |
XRegistry.prototype.load = function (ip) { | |
var _this = this; | |
if (ip === void 0) { ip = "127.0.0.1"; } | |
var filenameEntrys = []; | |
var dataEntrys = []; | |
var file = new BinaryReader(ip === "127.0.0.1" ? "http://127.0.0.1/dev_flash2/etc/xRegistry.sys" : ip); | |
if (this._intToHex(file.read(16)) === "bcadadbc0000009000000002bcadadbc") { | |
var filenameEntry = this._getFileEntry(file, filenameEntrys); | |
while (filenameEntry) { | |
filenameEntry = this._getFileEntry(file, filenameEntrys); | |
} | |
file.seek(0xfff0); | |
if (this._isDataMark(file)) { | |
var dataEntry = this._getDataEntry(file, dataEntrys); | |
while (dataEntry) { | |
dataEntry = this._getDataEntry(file, dataEntrys); | |
} | |
var r_1 = this._compactFields(filenameEntrys, dataEntrys); | |
return Object.keys(r_1).reduce(function (acc, key) { | |
_this._setPathValue(acc, key, r_1[key]); | |
return acc; | |
}, {}); | |
} | |
return null; | |
} | |
return null; | |
}; | |
XRegistry.prototype._compactFields = function (filenameEntrys, dataEntrys) { | |
var _this = this; | |
var listObj = {}; | |
var key; | |
var value; | |
var filenameEntry; | |
dataEntrys.forEach(function (dataEntry) { | |
var i = 0; | |
var found = false; | |
while (!found && i < filenameEntrys.length) { | |
filenameEntry = filenameEntrys[i]; | |
i = i + 1; | |
var filename = dataEntry.filename, dataValue = dataEntry.dataValue, type = dataEntry.type; | |
if (filename === filenameEntry.offset - 16) { | |
found = true; | |
key = _this._intToChar(filenameEntry.setting); | |
switch (type) { | |
case 0: | |
value = Boolean(dataValue); | |
break; | |
case 1: | |
value = _this._hexToInt(dataValue); | |
break; | |
case 2: | |
value = _this._intToChar(dataValue); | |
break; | |
} | |
listObj[key] = value; | |
} | |
} | |
}); | |
return listObj; | |
}; | |
XRegistry.prototype._getDataEntry = function (f, list) { | |
var offset = f.tell(); | |
var flagsHex = this._intToHex(f.read(2)); | |
var flags = parseInt(flagsHex, 16); | |
var filenameHex = this._intToHex(f.read(2)); | |
var filename = parseInt(filenameHex, 16); | |
var checksumHex = this._intToHex(f.read(2)); | |
var checksum = parseInt(checksumHex, 16); | |
var lenHex = this._intToHex(f.read(2)); | |
var len = parseInt(lenHex, 16); | |
var typeHex = this._intToHex(f.read(1)); | |
var type = parseInt(typeHex, 16); | |
var dataValue = f.read(len); | |
this._intToHex(f.read(1)); | |
if (flagsHex !== "aabb" && | |
filenameHex !== "ccdd" && | |
checksumHex !== "ee00") { | |
list.push({ offset: offset, flags: flags, filename: filename, checksum: checksum, len: len, type: type, dataValue: dataValue }); | |
return true; | |
} | |
else { | |
return false; | |
} | |
}; | |
XRegistry.prototype._getFileEntry = function (f, list) { | |
var offset = f.tell(); | |
var idHex = this._intToHex(f.read(2)); | |
var id = parseInt(idHex, 16); | |
var lenHex = this._intToHex(f.read(2)); | |
var len = parseInt(lenHex, 16); | |
var valueHex = this._intToHex(f.read(1)); | |
var value = parseInt(valueHex, 16); | |
var setting = f.read(len); | |
var sep = this._intToHex(f.read(1)); | |
if (sep === "00" && idHex !== "aabb" && lenHex !== "ccdd") { | |
list.push({ offset: offset, id: id, setting: setting, value: value }); | |
return true; | |
} | |
else { | |
return false; | |
} | |
}; | |
XRegistry.prototype._hexToInt = function (bytes) { | |
return parseInt(bytes | |
.map(function (byte) { | |
return byte.toString(16); | |
}) | |
.join("") | |
.toLowerCase(), 16); | |
}; | |
XRegistry.prototype._intToChar = function (bytes) { | |
return bytes | |
.map(function (byte) { | |
return String.fromCharCode(byte); | |
}) | |
.join(""); | |
}; | |
XRegistry.prototype._intToHex = function (bytes) { | |
return bytes | |
.map(function (byte) { | |
return byte < 16 ? "0" + byte.toString(16) : byte.toString(16); | |
}) | |
.join("") | |
.toLowerCase(); | |
}; | |
XRegistry.prototype._isDataMark = function (f) { | |
return this._intToHex(f.read(2)) === "4d26"; | |
}; | |
XRegistry.prototype._setPathValue = function (obj, path, value) { | |
if (path.charAt(0) === "/") { | |
path = path.substring(1); | |
} | |
var parts = path.split("/"); | |
var partsLength = parts.length; | |
parts.forEach(function (part, index) { | |
if (index + 1 === partsLength) { | |
obj[part] = value; | |
return; | |
} | |
obj[part] = obj[part] || {}; | |
obj = obj[part]; | |
}); | |
}; | |
return XRegistry; | |
}()); |
This file contains hidden or 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
class BinaryReader { | |
public data: string; | |
constructor(url: string, public pos = 0) { | |
this.data = this.load(url); | |
} | |
public load(url: string) { | |
const req = new XMLHttpRequest(); | |
req.open("GET", url, false); | |
req.overrideMimeType("text/plain; charset=x-user-defined"); | |
req.send(null); | |
if (req.status !== 200) { | |
return ""; | |
} | |
return req.responseText; | |
} | |
public read(len: number): number[] { | |
const result = Array.apply(null, Array(len)) | |
.map(Number.prototype.valueOf, 0) | |
.map((_: unknown, index: number) => { | |
// tslint:disable-next-line:no-bitwise | |
return this.data.charCodeAt(this.pos + index) & 0xff; | |
}); | |
this.pos += len; | |
return result; | |
} | |
public seek(offset: number): void { | |
this.pos = offset; | |
} | |
public tell() { | |
return this.pos; | |
} | |
} | |
interface IXRegistrySettings { | |
[key: string]: string | number | boolean; | |
} | |
interface IFileEntry { | |
offset: number; | |
id: number; | |
setting: number[]; | |
value: number; | |
} | |
interface IDataEntry { | |
offset: number; | |
flags: number; | |
filename: number; | |
checksum: number; | |
len: number; | |
type: number; | |
dataValue: number[]; | |
} | |
// tslint:disable-next-line:max-classes-per-file | |
class XRegistry { | |
public load(ip: string = "127.0.0.1"): IXRegistrySettings | null { | |
const filenameEntrys: IFileEntry[] = []; | |
const dataEntrys: IDataEntry[] = []; | |
const file = new BinaryReader( | |
ip === "127.0.0.1" ? "http://127.0.0.1/dev_flash2/etc/xRegistry.sys" : ip | |
); | |
if (this._intToHex(file.read(16)) === "bcadadbc0000009000000002bcadadbc") { | |
let filenameEntry = this._getFileEntry(file, filenameEntrys); | |
while (filenameEntry) { | |
filenameEntry = this._getFileEntry(file, filenameEntrys); | |
} | |
file.seek(0xfff0); | |
if (this._isDataMark(file)) { | |
let dataEntry = this._getDataEntry(file, dataEntrys); | |
while (dataEntry) { | |
dataEntry = this._getDataEntry(file, dataEntrys); | |
} | |
const r = this._compactFields(filenameEntrys, dataEntrys); | |
return Object.keys(r).reduce((acc, key) => { | |
this._setPathValue(acc, key, r[key]); | |
return acc; | |
}, {}); | |
} | |
return null; | |
} | |
return null; | |
} | |
private _compactFields( | |
filenameEntrys: IFileEntry[], | |
dataEntrys: IDataEntry[] | |
) { | |
const listObj: IXRegistrySettings = {}; | |
let key: string; | |
let value: string | number | boolean; | |
let filenameEntry: IFileEntry; | |
dataEntrys.forEach(dataEntry => { | |
let i = 0; | |
let found = false; | |
while (!found && i < filenameEntrys.length) { | |
filenameEntry = filenameEntrys[i]; | |
i = i + 1; | |
const { filename, dataValue, type } = dataEntry; | |
if (filename === filenameEntry.offset - 16) { | |
found = true; | |
key = this._intToChar(filenameEntry.setting); | |
switch (type) { | |
case 0: | |
value = Boolean(dataValue); | |
break; | |
case 1: | |
value = this._hexToInt(dataValue); | |
break; | |
case 2: | |
value = this._intToChar(dataValue); | |
break; | |
} | |
listObj[key] = value; | |
} | |
} | |
}); | |
return listObj; | |
} | |
private _getDataEntry(f: BinaryReader, list: IDataEntry[]) { | |
const offset = f.tell(); | |
const flagsHex = this._intToHex(f.read(2)); | |
const flags = parseInt(flagsHex, 16); | |
const filenameHex = this._intToHex(f.read(2)); | |
const filename = parseInt(filenameHex, 16); | |
const checksumHex = this._intToHex(f.read(2)); | |
const checksum = parseInt(checksumHex, 16); | |
const lenHex = this._intToHex(f.read(2)); | |
const len = parseInt(lenHex, 16); | |
const typeHex = this._intToHex(f.read(1)); | |
const type = parseInt(typeHex, 16); | |
const dataValue = f.read(len); | |
this._intToHex(f.read(1)); | |
if ( | |
flagsHex !== "aabb" && | |
filenameHex !== "ccdd" && | |
checksumHex !== "ee00" | |
) { | |
list.push({ offset, flags, filename, checksum, len, type, dataValue }); | |
return true; | |
} else { | |
return false; | |
} | |
} | |
private _getFileEntry(f: BinaryReader, list: IFileEntry[]) { | |
const offset = f.tell(); | |
const idHex = this._intToHex(f.read(2)); | |
const id = parseInt(idHex, 16); | |
const lenHex = this._intToHex(f.read(2)); | |
const len = parseInt(lenHex, 16); | |
const valueHex = this._intToHex(f.read(1)); | |
const value = parseInt(valueHex, 16); | |
const setting = f.read(len); | |
const sep = this._intToHex(f.read(1)); | |
if (sep === "00" && idHex !== "aabb" && lenHex !== "ccdd") { | |
list.push({ offset, id, setting, value }); | |
return true; | |
} else { | |
return false; | |
} | |
} | |
private _hexToInt(bytes: number[]) { | |
return parseInt( | |
bytes | |
.map(byte => { | |
return byte.toString(16); | |
}) | |
.join("") | |
.toLowerCase(), | |
16 | |
); | |
} | |
private _intToChar(bytes: number[]) { | |
return bytes | |
.map(byte => { | |
return String.fromCharCode(byte); | |
}) | |
.join(""); | |
} | |
private _intToHex(bytes: number[]) { | |
return bytes | |
.map(byte => { | |
return byte < 16 ? "0" + byte.toString(16) : byte.toString(16); | |
}) | |
.join("") | |
.toLowerCase(); | |
} | |
private _isDataMark(f: BinaryReader) { | |
return this._intToHex(f.read(2)) === "4d26"; | |
} | |
private _setPathValue(obj: any, path: string, value: unknown) { | |
if (path.charAt(0) === "/") { | |
path = path.substring(1); | |
} | |
const parts = path.split("/"); | |
const partsLength = parts.length; | |
parts.forEach((part, index) => { | |
if (index + 1 === partsLength) { | |
obj[part] = value; | |
return; | |
} | |
obj[part] = obj[part] || {}; | |
obj = obj[part]; | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment