qwokka / cetus Goto Github PK
View Code? Open in Web Editor NEWBrowser extension for hacking WebAssembly games a la Cheat Engine
License: Apache License 2.0
Browser extension for hacking WebAssembly games a la Cheat Engine
License: Apache License 2.0
Hey!
Sorry to bother you! I found your project very interesting and spent a lot of time debugging an online game for fun.
But I found some problems with Cetus.
Uncaught TypeError: Cannot read properties of undefined (reading 'count')
at cetus.js:821:47
(anonymous) @ cetus.js:821
Maybe I didn't get something, but these two bugs make it hard to edit the certain addresses that I found in the Memory Viewer :)
Instead of listing each time a function reads/writes an address, just list it once and have a counter next to it, like how cheat engine does. You should also add a button to clear to list.
It would be very cool to integrate wasmdec into the disassembler.
This would be especially useful since we could catch compiler errors in the patcher without having to restart the binary.
I was trying to patch in some wasm and I kept running into errors when the game would try to load it. I thought this was to me being terrible at writing wasm but I tried patching the function without changing anything and it still gives me an error. Here is a screenshot of the error: https://i.imgur.com/wGZWODw.png
The function I am trying to patch is function 88266
. It is in this game: https://1v1.lol/
Any help would be appreciated!
With Cetus enabled the error gets thrown and the game gets stuck on the loading screen and never fully starts. Game works fine without Cetus.
Using Chromium and tested with both the 1.02 version and the master version.
Game
Title says it all,
I recently installed Cetus (from git clone..) and I tried following the tutorial step by step just to get some familiarity with it. However, Cetus never returns anything when I search for a value. It just keeps searching indefinitely. How can I solve this?
Hi,
Awesome work you have done ;) really looking forward to the defcon talk video.
I tried CETUS on AngryBots and it's stuck to the "Waiting for WASM" part.
AngryBots demo: https://beta.unity3d.com/jonas/AngryBots/
Also, can you explain how CETUS detect the current instance and memory related to WASM when the page is loaded?
I believe this worked as expected the very first wasm I tried this on.
Read Watch and Write Watch enabled would give me a list of function addresses, while Find a function would take an address and output a list of functions. Currently however, they all do nothing whatsoever. Tried in Chrome Dev, Chrome stable and Firefox on 3 different wasms. Tried both extension popup and devtools view.
Am I doing something wrong?
Find an address (Health for example), bookmark it, enable Read or Write watch, make the value change, nothing happens.
always waiting for WASM i install it correctly but i cant use it
When im using cetus on a online multiplayer game my game speed decreases significantly speed hack is disabled. This happens just by having the extension installed and opening the site, in this case 1v1.lol
Hi, it is possible to put some speed values between 0 and 1 for slowing down the game?
Thanks!
Cetus has numerous issues with webpages that load more than one WASM binary at once. This will probably require both backend and UI improvements to make reasonably simple.
A good example game for this problem:
https://saplings.earth/
Changes to how stacktraces appear in WASM broke Cetus's ability to show the exact instruction in stack traces.
Stack trace entries now look like this:
wasm-function[32469]:0x1499ed6
where 32469 is the index of the function and 0x1499ed6 is the absolute address of the relevant instruction.
I'd like to support the old behavior but first we would need to be able to translate absolute address to a relative instruction number in the current function.
Hi I'm playing a WebAssembly game, i want to change my avatar position i found the addresses I'm searching for and tried to change the value and it worked, but every time i transfer to another room or reloading the game i have to walk through that process again which is kinda boring and time wasting i was using cheat engine so i tried to search for pointers and found it is impossible so is is possible with Cetus ?
Hi Jack,
When playing with cetus on Tank!, i triggered an "Uncaught TypeError: Do not know how to serialize a BigInt".
Reproduction:
I know nothing about coding. I tried this on MovieStarPlanet2, got to the point where I could search for values, but wasn't able to do anything with what showed up.
Hello,
I have been encountering a problem while trying to save patches multiple times. It seems that the operation isn't executing correctly. Here's what I've been doing:
However, the issue arises when I try to export the patch (Which also probably means it's not being applied). The exported JSON file doesn't appear to contain all the necessary elements. Specifically, I'm expecting to see the 'name', 'index', 'bytes', and 'url' fields in the exported file. But when I examine the file, all I see are the 'name' and 'url' fields.
Here's an example of what my exported JSON file looks like:
{
"name": "invis",
"url": "example.io/"
}
As you can see, the 'index' and 'bytes' fields, which I believe should be present, are missing from the exported JSON file.
Thanks
Hello.
Downloading the latest commit (not the release one which is working fine), I realized that there is an issue on the "Bookmark" tab: the check done on the "Freeze" and "Read Watch" are not working and the check on "Write Watch" enables the 3 checks.
Snooping around I see these 3 lines in view.js:
const frozen = bookmark.flags & FLAG_FREEZE != 0;
const readWatch = bookmark.flags & FLAG_WATCH_READ != 0;
const writeWatch = bookmark.flags & FLAG_WATCH_WRITE != 0;
I'm not sure if I'm getting this right, because it's not very clear to me why it has been done, but it looks there are missing parenthesis. If I modify it in this way, it works:
const frozen = (bookmark.flags & FLAG_FREEZE) != 0;
const readWatch = (bookmark.flags & FLAG_WATCH_READ) != 0;
const writeWatch = (bookmark.flags & FLAG_WATCH_WRITE) != 0;
If I'm getting this wrong....sorry.... :-)
I modified it in my local copy (see issue #11).
Thanks!
Ok, I changed this because I realized what the real issue is. If you have a comment in your wasm code your patch won't save. Cetus should either specially store comments for displaying them or they should be ignored completely.
As discovered in #36, most Cetus features fail on Chrome OS. I've reproduced this issue but haven't found the root cause yet.
For some reason, Cetus refuses to search properly when used in dev tools. I get "Searching..." forever.
I got an error from chrome in "updateStringSearchForm" with const strType = stringData.strType
saying that "stringData.strType" was undefined. I also got an error "Extension Context Invalidated" with
window.addEventListener("cetusMsgIn", function(msg) { chrome.runtime.sendMessage(msg.detail); }, false);
Can Cetus not just patch functions, but call them too?
Also, are there any chances to trace function calls?
Hello!
First of all thanks for the great tool!
If you are interested, and if you are not doing it by yourself, I'm working on the string search functions.
I have a working prototype, but still WIP.
If you want we can discuss a bit on how you prefer to implement it: I started with my way, but may be it make sense to double check with you if it make sense at all :-)
Thanks,
/**
Copyright 2020 Jack Baker
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const Instruction = class {
constructor() {
this.opcode = null;
this.immediates = [];
}
};
const InstructionReader = class extends BufferReader {
readKeywords(nameArray) {
const results = [];
for (let i = 0; i < nameArray.length; i++) {
const thisName = nameArray[i];
if (typeof thisName !== "string") {
throw new Error("Invalid keyword name in InstructionReader.readKeywords()");
}
const thisValue = this.readVarUint32();
const thisString = `${thisName}=${thisValue}`;
results.push(thisString);
}
return results;
}
readBlockType() {
const blockType = this.readUint8();
switch (blockType) {
case VALUE_TYPE_I32:
return "i32";
case VALUE_TYPE_I64:
return "i64";
case VALUE_TYPE_F32:
return "f32";
case VALUE_TYPE_F64:
return "f64";
case VALUE_TYPE_ANYFUNC:
case VALUE_TYPE_FUNC:
case VALUE_TYPE_BLOCK:
return "";
default:
throw new Error("Bad block type in InstructionReader.readBlockType()");
}
}
};
const Disassembler = class {
constructor(bytes, symbols = {}) {
this.reader = new InstructionReader(bytes);
this.indentStr = " ";
this.symbols = symbols;
}
disassemble() {
const instructions = [];
const outputLines = [];
let indentDepth = 0;
let lineNumber = 0;
const byteIndexToLineNum = {};
while (this.reader.inPos < this.reader.inBuffer.length) {
byteIndexToLineNum[this.reader.inPos] = lineNumber++;
const instruction = this.disassembleInstruction();
instructions.push(instruction);
}
for (let i = 0; i < instructions.length; i++) {
const thisInstr = instructions[i];
const immediateString = thisInstr.immediates.join(" ");
const instrString = `${thisInstr.opstring} ${immediateString}`;
if (thisInstr.opcode == OP_END) {
indentDepth--;
}
if (indentDepth < 0) {
indentDepth = 0;
}
const instrFullString = (this.indentStr.repeat(indentDepth) + instrString);
switch (thisInstr.opcode) {
case OP_BLOCK:
case OP_LOOP:
case OP_IF:
case OP_ELSE:
indentDepth++;
break;
}
outputLines.push(instrFullString);
}
const resultObj = {};
resultObj.text = outputLines.join("\n");
resultObj.lineNums = byteIndexToLineNum;
return resultObj;
}
disassembleInstruction() {
const instruction = {};
instruction.opcode = this.reader.readUint8();
instruction.immediates = [];
switch (instruction.opcode) {
case OP_UNREACHABLE:
instruction.opstring = "unreachable";
break;
case OP_NOP:
instruction.opstring = "nop";
break;
case OP_BLOCK:
instruction.opstring = "block";
instruction.immediates.push(this.reader.readBlockType());
break;
case OP_LOOP:
instruction.opstring = "loop";
instruction.immediates.push(this.reader.readBlockType());
break;
case OP_IF:
instruction.opstring = "if";
instruction.immediates.push(this.reader.readBlockType());
break;
case OP_ELSE:
instruction.opstring = "else";
break;
case OP_END:
instruction.opstring = "end";
break;
case OP_BR:
instruction.opstring = "br";
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_BR_IF:
instruction.opstring = "br_if";
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_BR_TABLE:
instruction.opstring = "br_table";
let count = this.reader.readVarUint32();
instruction.immediates.push(count);
for (let i = 0; i < count; i++) {
instruction.immediates.push(this.reader.readVarUint32());
}
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_RETURN:
instruction.opstring = "return";
break;
case OP_CALL:
instruction.opstring = "call";
const callTarget = this.reader.readVarUint32();
if (typeof this.symbols[callTarget] !== "undefined") {
instruction.immediates.push(this.symbols[callTarget]);
}
else {
instruction.immediates.push(callTarget);
}
break;
case OP_CALL_INDIRECT:
instruction.opstring = "call_indirect";
instruction.immediates.push(this.reader.readVarUint32());
instruction.immediates.push(this.reader.readUint8());
break;
case OP_DROP:
instruction.opstring = "drop";
break;
case OP_SELECT:
instruction.opstring = "select";
break;
case OP_GET_LOCAL:
instruction.opstring = "get_local";
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_SET_LOCAL:
instruction.opstring = "set_local";
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_TEE_LOCAL:
instruction.opstring = "tee_local";
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_GET_GLOBAL:
instruction.opstring = "get_global";
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_SET_GLOBAL:
instruction.opstring = "set_global";
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_I32_LOAD:
instruction.opstring = "i32.load";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_LOAD:
instruction.opstring = "i64.load";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_F32_LOAD:
instruction.opstring = "f32.load";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_F64_LOAD:
instruction.opstring = "f64.load";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I32_LOAD8_S:
instruction.opstring = "i32.load8_s";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I32_LOAD8_U:
instruction.opstring = "i32.load8_u";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I32_LOAD16_S:
instruction.opstring = "i32.load16_s";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I32_LOAD16_U:
instruction.opstring = "i32.load16_u";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_LOAD8_S:
instruction.opstring = "i64.load8_s";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_LOAD8_U:
instruction.opstring = "i64.load8_u";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_LOAD16_S:
instruction.opstring = "i64.load16_s";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_LOAD16_U:
instruction.opstring = "i64.load16_u";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_LOAD32_S:
instruction.opstring = "i64.load32_s";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_LOAD32_U:
instruction.opstring = "i64.load32_u";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I32_STORE:
instruction.opstring = "i32.store";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_STORE:
instruction.opstring = "i64.store";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_F32_STORE:
instruction.opstring = "f32.store";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_F64_STORE:
instruction.opstring = "f64.store";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I32_STORE8:
instruction.opstring = "i32.store8";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I32_STORE16:
instruction.opstring = "i32.store16";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_STORE8:
instruction.opstring = "i64.store8";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_STORE16:
instruction.opstring = "i64.store16";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_I64_STORE32:
instruction.opstring = "i64.store32";
instruction.immediates = this.reader.readKeywords(["align", "offset"]);
break;
case OP_MEMORY_SIZE:
instruction.opstring = "current_memory";
instruction.immediates.push(this.reader.readUint8());
break;
case OP_MEMORY_GROW:
instruction.opstring = "grow_memory";
instruction.immediates.push(this.reader.readUint8());
break;
case OP_I32_CONST:
instruction.opstring = "i32.const";
instruction.immediates.push(this.reader.readVarUint32());
break;
// TODO Fix
case OP_I64_CONST:
instruction.opstring = "i64.const";
instruction.immediates.push(this.reader.readVarUint32());
break;
case OP_F32_CONST:
instruction.opstring = "f32.const";
const f32Bytes = this.reader.readBytes(4);
const f32ByteBuffer = new Uint8Array(f32Bytes);
const f32Array = new Float32Array(f32ByteBuffer.buffer);
instruction.immediates.push(f32Array[0]);
break;
case OP_F64_CONST:
instruction.opstring = "f64.const";
const f64Bytes = this.reader.readBytes(8);
const f64ByteBuffer = new Uint8Array(f64Bytes);
const f64Array = new Float64Array(f64ByteBuffer.buffer);
instruction.immediates.push(f64Array[0]);
break;
case OP_I32_EQZ:
instruction.opstring = "i32.eqz";
break;
case OP_I32_EQ:
instruction.opstring = "i32.eq";
break;
case OP_I32_NE:
instruction.opstring = "i32.ne";
break;
case OP_I32_LT_S:
instruction.opstring = "i32.lt_s";
break;
case OP_I32_LT_U:
instruction.opstring = "i32.lt_u";
break;
case OP_I32_GT_S:
instruction.opstring = "i32.gt_s";
break;
case OP_I32_GT_U:
instruction.opstring = "i32.gt_u";
break;
case OP_I32_LE_S:
instruction.opstring = "i32.le_s";
break;
case OP_I32_LE_U:
instruction.opstring = "i32.le_u";
break;
case OP_I32_GE_S:
instruction.opstring = "i32.ge_s";
break;
case OP_I32_GE_U:
instruction.opstring = "i32.ge_u";
break;
case OP_I64_EQZ:
instruction.opstring = "i64.eqz";
break;
case OP_I64_EQ:
instruction.opstring = "i64.eq";
break;
case OP_I64_NE:
instruction.opstring = "i64.ne";
break;
case OP_I64_LT_S:
instruction.opstring = "i64.lt_s";
break;
case OP_I64_LT_U:
instruction.opstring = "i64.lt_u";
break;
case OP_I64_GT_S:
instruction.opstring = "i64.gt_s";
break;
case OP_I64_GT_U:
instruction.opstring = "i64.gt_u";
break;
case OP_I64_LE_S:
instruction.opstring = "i64.le_s";
break;
case OP_I64_LE_U:
instruction.opstring = "i64.le_u";
break;
case OP_I64_GE_S:
instruction.opstring = "i64.ge_s";
break;
case OP_I64_GE_U:
instruction.opstring = "i64.ge_u";
break;
case OP_F32_EQ:
instruction.opstring = "f32.eq";
break;
case OP_F32_NE:
instruction.opstring = "f32.ne";
break;
case OP_F32_LT:
instruction.opstring = "f32.lt";
break;
case OP_F32_GT:
instruction.opstring = "f32.gt";
break;
case OP_F32_LE:
instruction.opstring = "f32.le";
break;
case OP_F32_GE:
instruction.opstring = "f32.ge";
break;
case OP_F64_EQ:
instruction.opstring = "f64.eq";
break;
case OP_F64_NE:
instruction.opstring = "f64.ne";
break;
case OP_F64_LT:
instruction.opstring = "f64.lt";
break;
case OP_F64_GT:
instruction.opstring = "f64.gt";
break;
case OP_F64_LE:
instruction.opstring = "f64.le";
break;
case OP_F64_GE:
instruction.opstring = "f64.ge";
break;
case OP_I32_CLZ:
instruction.opstring = "i32.clz";
break;
case OP_I32_CTZ:
instruction.opstring = "i32.ctz";
break;
case OP_I32_POPCNT:
instruction.opstring = "i32.popcnt";
break;
case OP_I32_ADD:
instruction.opstring = "i32.add";
break;
case OP_I32_SUB:
instruction.opstring = "i32.sub";
break;
case OP_I32_MUL:
instruction.opstring = "i32.mul";
break;
case OP_I32_DIV_S:
instruction.opstring = "i32.div_s";
break;
case OP_I32_DIV_U:
instruction.opstring = "i32.div_u";
break;
case OP_I32_REM_S:
instruction.opstring = "i32.rem_s";
break;
case OP_I32_REM_U:
instruction.opstring = "i32.rem_u";
break;
case OP_I32_AND:
instruction.opstring = "i32.and";
break;
case OP_I32_OR:
instruction.opstring = "i32.or";
break;
case OP_I32_XOR:
instruction.opstring = "i32.xor";
break;
case OP_I32_SHL:
instruction.opstring = "i32.shl";
break;
case OP_I32_SHR_S:
instruction.opstring = "i32.shr_s";
break;
case OP_I32_SHR_U:
instruction.opstring = "i32.shr_u";
break;
case OP_I32_ROTL:
instruction.opstring = "i32.rotl";
break;
case OP_I32_ROTR:
instruction.opstring = "i32.rotr";
break;
case OP_I64_CLZ:
instruction.opstring = "i64.clz";
break;
case OP_I64_CTZ:
instruction.opstring = "i64.ctz";
break;
case OP_I64_POPCNT:
instruction.opstring = "i64.popcnt";
break;
case OP_I64_ADD:
instruction.opstring = "i64.add";
break;
case OP_I64_SUB:
instruction.opstring = "i64.sub";
break;
case OP_I64_MUL:
instruction.opstring = "i64.mul";
break;
case OP_I64_DIV_S:
instruction.opstring = "i64.div_s";
break;
case OP_I64_DIV_U:
instruction.opstring = "i64.div_u";
break;
case OP_I64_REM_S:
instruction.opstring = "i64.rem_s";
break;
case OP_I64_REM_U:
instruction.opstring = "i64.rem_u";
break;
case OP_I64_AND:
instruction.opstring = "i64.and";
break;
case OP_I64_OR:
instruction.opstring = "i64.or";
break;
case OP_I64_XOR:
instruction.opstring = "i64.xor";
break;
case OP_I64_SHL:
instruction.opstring = "i64.shl";
break;
case OP_I64_SHR_S:
instruction.opstring = "i64.shr_s";
break;
case OP_I64_SHR_U:
instruction.opstring = "i64.shr_u";
break;
case OP_I64_ROTL:
instruction.opstring = "i64.rotl";
break;
case OP_I64_ROTR:
instruction.opstring = "i64.rotr";
break;
case OP_F32_ABS:
instruction.opstring = "f32.abs";
break;
case OP_F32_NEG:
instruction.opstring = "f32.neg";
break;
case OP_F32_CEIL:
instruction.opstring = "f32.ceil";
break;
case OP_F32_FLOOR:
instruction.opstring = "f32.floor";
break;
case OP_F32_TRUNC:
instruction.opstring = "f32.trunc";
break;
case OP_F32_NEAREST:
instruction.opstring = "f32.nearest";
break;
case OP_F32_SQRT:
instruction.opstring = "f32.sqrt";
break;
case OP_F32_ADD:
instruction.opstring = "f32.add";
break;
case OP_F32_SUB:
instruction.opstring = "f32.sub";
break;
case OP_F32_MUL:
instruction.opstring = "f32.mul";
break;
case OP_F32_DIV:
instruction.opstring = "f32.div";
break;
case OP_F32_MIN:
instruction.opstring = "f32.min";
break;
case OP_F32_MAX:
instruction.opstring = "f32.max";
break;
case OP_F32_COPYSIGN:
instruction.opstring = "f32.copysign";
break;
case OP_F64_ABS:
instruction.opstring = "f64.abs";
break;
case OP_F64_NEG:
instruction.opstring = "f64.neg";
break;
case OP_F64_CEIL:
instruction.opstring = "f64.ceil";
break;
case OP_F64_FLOOR:
instruction.opstring = "f64.floor";
break;
case OP_F64_TRUNC:
instruction.opstring = "f64.trunc";
break;
case OP_F64_NEAREST:
instruction.opstring = "f64.nearest";
break;
case OP_F64_SQRT:
instruction.opstring = "f64.sqrt";
break;
case OP_F64_ADD:
instruction.opstring = "f64.add";
break;
case OP_F64_SUB:
instruction.opstring = "f64.sub";
break;
case OP_F64_MUL:
instruction.opstring = "f64.mul";
break;
case OP_F64_DIV:
instruction.opstring = "f64.div";
break;
case OP_F64_MIN:
instruction.opstring = "f64.min";
break;
case OP_F64_MAX:
instruction.opstring = "f64.max";
break;
case OP_F64_COPYSIGN:
instruction.opstring = "f64.copysign";
break;
case OP_I32_WRAP_I64:
instruction.opstring = "i32.wrap/i64";
break;
case OP_I32_TRUNC_S_F32:
instruction.opstring = "i32.trunc_s/f32";
break;
case OP_I32_TRUNC_U_F32:
instruction.opstring = "i32.trunc_u/f32";
break;
case OP_I32_TRUNC_S_F64:
instruction.opstring = "i32.trunc_s/f64";
break;
case OP_I32_TRUNC_U_F64:
instruction.opstring = "i32.trunc_u/f64";
break;
case OP_I64_EXTEND_S_I32:
instruction.opstring = "i64.extend_s/i32";
break;
case OP_I64_EXTEND_U_I32:
instruction.opstring = "i64.extend_u/i32";
break;
case OP_I64_TRUNC_S_F32:
instruction.opstring = "i64.trunc_s/f32";
break;
case OP_I64_TRUNC_U_F32:
instruction.opstring = "i64.trunc_u/f32";
break;
case OP_I64_TRUNC_S_F64:
instruction.opstring = "i64.trunc_s/f64";
break;
case OP_I64_TRUNC_U_F64:
instruction.opstring = "i64.trunc_u/f64";
break;
case OP_F32_CONVERT_S_I32:
instruction.opstring = "f32.convert_s/i32";
break;
case OP_F32_CONVERT_U_I32:
instruction.opstring = "f32.convert_u/i32";
break;
case OP_F32_CONVERT_S_I64:
instruction.opstring = "f32.convert_s/i64";
break;
case OP_F32_CONVERT_U_I64:
instruction.opstring = "f32.convert_u/i64";
break;
case OP_F32_DEMOTE_F64:
instruction.opstring = "f32.demote/f64";
break;
case OP_F64_CONVERT_S_I32:
instruction.opstring = "f64.convert_s/i32";
break;
case OP_F64_CONVERT_U_I32:
instruction.opstring = "f64.convert_u/i32";
break;
case OP_F64_CONVERT_S_I64:
instruction.opstring = "f64.convert_s/i64";
break;
case OP_F64_CONVERT_U_I64:
instruction.opstring = "f64.convert_u/i64";
break;
case OP_F64_PROMOTE_F32:
instruction.opstring = "f64.promote/f32";
break;
case OP_I32_REINTERPRET_F32:
instruction.opstring = "i32.reinterpret/f32";
break;
case OP_I64_REINTERPRET_F64:
instruction.opstring = "i64.reinterpret/f64";
break;
case OP_F32_REINTERPRET_I32:
instruction.opstring = "f32.reinterpret/i32";
break;
case OP_F64_REINTERPRET_I64:
instruction.opstring = "f64.reinterpret/i64";
break;
default:
throw "Invalid/unknown opcode " + instruction.opcode;
}
return instruction;
}
};
In Cheat Engine, you can perform a search for all values and then filter them based on changed or unchanged values. For instance, if you have 105 health points and this information is not displayed, you can do this:
Would be a nice feature
Whenever I try to open up Cetus with flyff universe open, it keeps giving me the Waiting for WASM message. I'm fairly confident this is a WASM game according to the dev tools. Please let me know if it is just something I am doing wrong as I'd love to utilize this. Thanks!
i think it is because new v3 extensions dont work that it gets the instantiate assamblesy but is stuck in searching for wasm, so please update the extension to v3 :,(
Can i use with it any web based game?
I've been researching WASM hacking and finding resources is quite challenging. Specifically, I'm trying to find a function that would allow my player to initiate an attack, but I'm struggling because it's not a value I can easily track. I recall from your DEFCON presentation (which was fantastic, by the way) that you discovered a function which was responsible for encryption and also posted to an endpoint. This seems like a difficult function to find and it seems that the process could be similar to what I'm trying to do. I'm curious to know how you managed to identify it. From what I gather, it appears that you need to know where to look and also be able to recognize what different encryption algorithms look like in order to correctly identify the function. Was this your strategy? Could you provide a step by step on how you managed to do this? Alternatively, if you have a more relevant example, I'd appreciate it. I also think this functionality might need the use of WAIL?
P.S sorry if this is a little off topic of Cetus, I don't see another way of contacting you :/
When attempting to follow along with the demo or DEFCON talk, Web-Assembly aborts due to running out of memory.
Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value 50331648, (2) compile with -s ALLOW_MEMORY_GROWTH=1 which adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0
I have tried to edit je json file's TOTAL_MEMORY using BurpSuite, although I have had no results.
This happens on both Firefox 73.0b5 (64-bit) & Brave Version 1.2.43 Chromium: 79.0.3945.130 (Official Build) (64-bit)
Hello. When I try this step here: Press the "double arrow" button >> and then select Cetus from the list of options nothing happens when i press the double arrows in the console. Do you know the fix?
I have tried to use this on three separate WebGL Unity games, and I am unable to narrow down my search results. It always returns X results on the initial search, then the next search to narrow the results down always returns 0 results. I repeat the search using every size, same result. Here is one of the games I tried
Can anyone let me know if they can get Cetus working on this game? Don't know if it is Cetus or me that is the problem.
Hello,
I noticed that every time I use a floating point number in my patches, it gets transformed into an integer.
I added this line: f32.const 0.2
, then saved the patch. When I open it again the line is changed to: f32.const 0
.
Why is that?
This isn't very high priority because it works just fine, but there is an error after making it an extension.
"Manifest version 2 is deprecated, and support will be removed in 2023. See https://developer.chrome.com/blog/mv2-transition/ for more details."
It'd be nice to have a view in the UI where you can scroll through memory (Like CE's Memory View).
Hey just an enhancement suggestion if it wouldn't be too much trouble. the speed hack works great for speeding up but I think it would be great if we had the option to slow down a game. @Qwokka
Any games including:
https://www.wasm.com.cn/demo/Tanks/
https://suragames.com/games/CombatOnline/index.php
are not loading (all of them are stuck on the loading process)
in the tanks console i saw this error log:
Are there dependencies i need to download for this error to pass?
So I patched the game, now is there anyway to make the game run smoother but shutting off other features except the patching?
After trying to search for the value 100 I get this error in the extentions
I am using Opera GX and I have tried this in Chrome
The search also never ends
When I add the extension I get this error:
Manifest version 2 is deprecated, and support will be removed in 2023. See https://developer.chrome.com/blog/mv2-transition/ for more details.
"manifest_version": 2,
Console error when I search:
Uncaught TypeError: Cannot read properties of undefined (reading 'buffer')
at Cetus.memory (cetus.js:51:44)
at Cetus.search (cetus.js:146:29)
at cetus.js:505:34
memory @ cetus.js:51
search @ cetus.js:146
(anonymous) @ cetus.js:505
Extention Error:
Context
https://primerlearning.org/
Stack Trace
content/cetus.js:51 (memory)
content/cetus.js:146 (search)
content/cetus.js:505 (anonymous function)
memory(type) {
const memType = this.getMemoryType(type);
// We return a new object each time because the WebAssembly.Memory object
// will detach if it is resized
return new memType(this._memObject.buffer);
}
Freeze more than one variables at once . It is useful to handle time related variables
Suggested by @TSSans-art
We should be able to import/export bookmarks from the UI.
As is we can manually add bookmarks with cetus.addBookmark() but this is a hassle.
A bunch of new instructions were added to WASM this year. As of right now Cetus watchpoints aren't injected for each atomic load/store instruction.
Cetus is great. Works fine with the Tank example. Now taking it to a different application I ran into some issue.
When running it Cetus is stuck at waiting for WASM , I assume its because the application doesn't continue loading when Cetus is active.
Uncaught (in promise) RuntimeError: abort(TypeError: Cannot read property 'memory' of undefined). Build with -s ASSERTIONS=1 for more info.
Running Chrome 87 and pulled latest version of the plugin.
URL of the application: https://neuz-h5.flyff.com/client/index.html
The newest cetus version, 1.3 isnt working on any websites. (I also tried it on the tank demo game)
Looking into the console while using 1.3, shows "๐ CETUS WebAssembly.instantiateStreaming() intercepted", and not "๐ CETUS WebAssembly.instantiate() intercepted" too
I think because of this, none of the features work - no speedhacking, no searching
Version 1.0 works fine on the tank game demo but on a wasm io game called https://florr.io/ it does the infinite search issue described in #36
Looking into the console while searching in florr.io, shows cetus.js:51 Uncaught TypeError: Cannot read properties of undefined (reading 'buffer')
at Cetus.memory (cetus.js:51:44)
at Cetus.search (cetus.js:146:29)
at cetus.js:505:34
Speedhacking works fine in florr.io though
I tried to use https://github.com/vakzz/wasm-cheat-engine, in florr.io and it seemed to work fine. (would love cetus also working because of the other features it has)
Anyways, i don't know if this matters but i am using a chromebook on chrome os using chrome browser
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.