Will this work against cheat engine? - javascript

I started programming a few months ago. I'm making a complete client side game in Animate CC, so I'm trying a simple measure against memory scan software.
I'm trying to avoid people to change my money variable.
var canMoneyChange = false;
var money = 0;
var previousMoney = 0;
function everyFrame() { //Let's admit that this function is called every frame
if (moneyChange == true) {
lastMoney = money;
canMoneyChange = false;
} else {
if (lastMoney != money) { //If money is "magically" changed it should drop here
resetGame();
}
}
Now evertime I update the money visual display I also have to include the boolean variable:
//...
canMoneyChange = true;
money += 100; //For example
updateMoney(); //This is only for visual effects
//...
Wondering if this works at all, thanks.
EDIT: Oh damn, I was not realising that CE would find both lastMoney and money at the same time. I could do something like multiplying by a number to hide lastMoney:
function everyFrame() { //Let's admit that this function is called every frame
if (moneyChange == true) {
lastMoney = money * 8;
canMoneyChange = false;
} else {
if (lastMoney != money * 8) {
resetGame();
}
}

This will stop 50% of Cheat Engine users because most users are inexperienced and are only capable of doing simple scans and memory modifications. They will just give up because you've raised the adversarial costs above their threshold.
As others have commented, it's a cat and mouse game.
Users can still scan for "unknown initial value" and scan for decreased and increased values. This will yield the obfuscated money value and the regular value, doesn't take too much to figure it out from there.
Also users can do "Find what Writes to this address" that will put a write breakpoint on the money address, it will then give them the instruction that changes the money back to the original value. At this point they will see the:
lastMoney = money * 8;
in assembly and be able to figure it out from there.
In all anti-cheat situations, each deterrent you put in place will raise adversarial costs and filter out another tier of cheaters. Your goal should never be to stop all cheaters 'cuz that's never happening. But in a few hours you can roll up a bit of obfuscation and a couple anti-debug measures to deter 75% of the cheaters. Problem is when the other 25% representing the experienced cheaters release the cheats. At that point the 75% inexperienced group's adversarial costs represent a search on a search engine.
I would say add some IsDebuggerPresent() type checks but I imagine on your platform that's not possible.
I'm not familiar with Animate CC or Flash, but combining 1 custom obfuscation technique like you're working on right now, with a public free obfuscator will annoy a substantial number of people enough to give up.

Related

How do I implement minimax with the chess.js node module

I'm currently working on creating a chess engine using chess.js, chessboard.js, and the minimax algorithm. I eventually want to implement alpha-beta, but for right now, I just want to get minimax to work. It seems like the computer is thinking, but it usually just does Nc6. If I move the pawn to d4, it usually takes with the knight, but sometimes it just moves the rook back and forth in the spot that was opened up by the knight. If there is nothing for the knight to take, the computer moves the Rook or some other pointless move. My best guess is that all of the moves are returning the same valuation, and so it just makes the first move in the array of possible moves, hence the top left rook being a prime target. I should note that part of my confusion is around the way a recursive function works, and most of the stuff I've found online about recursive functions leaves me more confused than when I started.
I'm using Express.js with the chessboard.js config in public/javascripts as a boardInit.js that's included in the index.ejs folder, and when the user makes a move, a Post request is sent to /moveVsComp. It sends it to the server, where the app.post function for /moveVsComp tells chess.js to make the move that the player made.
After the player move is recorded, the computer calls the computerMoveBlack function.
Function call in the post request:
let compMove = computerMoveBlack(3);
game.load(currentFen)
game.move(compMove)
res.status(200).send({snapback: false, fen: game.fen()})
computerMoveBlack Function:
function computerMoveBlack(depth) {
let bestMove = ['', 105];
for (let move of game.moves()) {
game.move(move)
let value = minimax(move, depth-1, false)
if (value < bestMove[1]) {
bestMove = [move, value]
}
game.undo()
}
console.log(bestMove[0])
return bestMove[0]
}
This function loops through all of the moves, and I was using this because it seemed like this was the best way to keep the best move instead of just returning a valuation of the current position.
Minimax Function:
function minimax(node, depth, maximizingPlayer) {
let value = maximizingPlayer ? -105 : 105
if (depth === 0 || game.game_over()) return getValuation()
if (maximizingPlayer) {
for (let move of game.moves()) {
game.move(move)
value = Math.max(value, minimax(move, depth-1, false))
game.undo()
}
return value
} else {
for (let move of game.moves()) {
game.move(move)
value = Math.min(value, minimax(move, depth-1, true))
game.undo()
}
return value
}
}
getValuation Function:
function getValuation() {
let evalString = game.fen().split(' ')[0];
let score = 0;
score += (evalString.split('r').length -1) * -5 || 0;
score += (evalString.split('b').length -1) * -3 || 0;
score += (evalString.split('n').length -1) * -3 || 0;
score += (evalString.split('q').length -1) * -9 || 0;
score += (evalString.split('p').length -1) * -1 || 0;
score += (evalString.split('R').length -1) * 5 || 0;
score += (evalString.split('N').length -1) * 3 || 0;
score += (evalString.split('B').length -1) * 3 || 0;
score += (evalString.split('Q').length -1) * 9 || 0;
score += (evalString.split('P').length -1) || 0;
return score;
}
I should note that I understand using a FEN in the valuation is very slow for this use case, but I'm not really sure what a better alternative would be.
Just as kind of a recap of the questions, I'm trying to figure out why it just makes the first move in the array every time, what is wrong with the format of my functions, and what a better way to get the valuation of a position is as opposed to string manipulation of the FEN.
I will point out a few suggestions below to help you on the way if you are just getting started. First I just want to say that you are probably right that all moves get the same score and therefore it picks the first possible move. Try to add some Piece Square Tables (PST) to your Evaluation function and see if it puts pieces on appropriate squares.
I would implement a Negamax function instead of Minimax. It is way easier to debug and you won't have to duplicate a lot of code when you later make more optimizations. Negamax is one of the standard chess algorithms.
It seems like you don't do the legal move generation yourself, do you know how the board is represented in the library that you use? Instead of using the FEN for evaluation you want to use the board (or bitboards) to be able to do more advanced evaluation (more on it further down).
The min/max value of -105/105 is not a good way to go. Use -inf and inf instead to not get into troubles later on.
Regarding the evaluation you normally use the board representation to figure out how pieces are placed and how they are working together. Chessprogramming.org is a great resource to read up on different evaluation concepts.
For your simple starting evaluation you could just start with counting up all the material score at the beginning of the game. Then you subtract corresponding piece value when a piece is captured since that is the only case where the score is changing. Now you are recalculating lots of things over and over which will be very slow.
If you want to add PST to the evaluation then you also want to add the piece value change for the moving piece depending on the old and new square. To try and sum up the evaluation:
Sum up all piece values at start-up of a game (with PST scores if you use them) and save it as e.g. whiteScore and blackScore
In your evaluation you subtract the piece value from the opponent if you capture a piece. Otherwise you keep score as is and return it as usual.
If using PST you change the own score based on the new location for the moved piece.
I hope it makes sense, let me know if you need any further help.

Unbalanced binary tree not functioning properly. Node.Js

So I was solving a problem for class involving binary search and the algorithm I implemented to solve it worked fine but my hunch is that a slight gamble would be more effective given the parameters of the problem
The fictional town of HollyBroke, Fl is made up of a 30 x 30 block grid. The streets are named after the presidents of the United States and the avenues are numbered numerically. The infamous two-word arsonist is holding the town hostage. He selects a house every Saturday for destruction by fire and taunts the police department by challenging them to guess the location for each week’s crime. He will answer up 10 guesses with either a “yes”or a “no” answer during his very brief phone call right before he strikes the match. (He won’t stay on the line so the call can’t be trace.)
The city wants you to develop a program to provide a quick response when this notorious criminal calls.
The answer to that was easy enough to create an algorithm for but I thought a median-1/median+1 gamble would be more effective. My hunch is that more often than not I will arrive at the conclusion with one extra question to go allowing me to either ask a binary search question about the arsonist or if the game allowed it I would show up with police before the end of the call. If I don't outright solve it beforehand I would have a very small space to search after it was completed, like three or four blocks right next to each other,
This is my code for the "gambling" binary search.
`var array = [{"a":30,"b":30,"c":0}]
function findLower(input) {
var half = Math.floor(input/2);
if(0 == input%2)
return (half-1);
else
return (half);
};
function findUpper(input) {
var half = Math.floor(input/2);
if(input%2 == 0)
return (half+1);
else
return (half+1);
}
for (var i = 0; i <= 9; i++){
for (var z = array.length - 1; z >= 0; z--) {
if (array[z].c = i){
if (array[z].a>array[z].b)
array.push({"a":findLower(array[z].a),"b":array[z].b,"c":array[z].c + 1},{"a":findUpper(array[z].a),"b":array[z].b,"c":array[z].c + 1})
else
array.push({"a":array[z].a,"b":findLower(array[z].b),"c":array[z].c + 1},{"a":array[z].a,"b":findUpper(array[z].b),"c":array[z].c + 1})
}
};
}
console.log(array.length);`
Its coming up with an absurd array length given that it should be 2^10 +2^9 + 2^8 ..... = 2047
The program is coming up with an array length of 19683
And some of the arrays should most certainly not be 30*14 at node level 10 I'm sure the algorithm was set up properly. I've walked it through two levels by pen and paper and it seems like it should work properly.
Found it.
if (array[z].c = i){
should be
if (array[z].c == i){
its a conditional statement not declaring them equal
Also I was wrong. You only have about a 40% chance of successfully locating the house in 10 guesses.

JavaScript anti-flood spam protection?

I was wondering if it were possible to implement some kind of crude JavaScript anti-flood protection.
My code receives events from a server through AJAX, but sometimes these events can be quite frequent (they're not governed by me).
I have attempted to come up with a method of combating this, and I've written a small script: http://jsfiddle.net/Ry5k9/
var puts = {};
function receiverFunction(id, text) {
if ( !puts[id] ) {
puts = {};
puts[id] = {};
}
puts[id].start = puts[id].start || new Date();
var count = puts[id].count = puts[id].count + 1 || 0;
var time = (new Date() - puts[id].start) * 0.001;
$("text").set("text", (count / time.toFixed()).toString() + " lines/second");
doSomethingWithTextIfNotSpam(text);
}
};
which I think could prove effective against these kinds of attacks, but I'm wondering if it can be improved or perhaps rewritten?
So far, I think everything more than 3 or 2.5 lines per second seems like spam, but as time progresses forward (because start mark was set... well... at the start), an offender could simply idle for a while and then commence the flood, effectively never passing 1 line per minute.
Also, I would like to add that I use Mootools and Lo-Dash libraries (maybe they provide some interesting methods), but it would be preferable if this can be done using native JS.
Any insight is greatly appreciated!
If you are concerned about the frequency a particular javascript function fires, you could debounce the function.
In your example, I guess it would be something like:
onSuccess: function(){ _.debounce(someOtherFunction, timeOut)};
where timeout is the maximum frequency you want someOtherFunction to be called.
I know you asked about native JavaScript, but maybe take a look at RxJS.
RxJS or Reactive Extensions for JavaScript is a library for
transforming, composing, and querying streams of data. We mean all
kinds of data too, from simple arrays of values, to series of events
(unfortunate or otherwise), to complex flows of data.
There is an example on that page which uses the throttle method to "Ignores values from an observable sequence which are followed by another value before dueTime" (see source).
keyup = Rx.Observable.fromEvent(input, 'keyup').select(function(ev) {
return ev.target.value;
}).where(function(text) {
return text.length > 2;
}).throttle(500)
.distinctUntilChanged()
There might be a similar way to get your 2.5-3 per second and ignore the rest of the events until the next second.
I've spent many days pondering on effective measures to forbid message-flooding, until I came across the solution implemented somewhere else.
First, we need three things, penalty and score variables, and a point in time where last action occured:
var score = 0;
var penalty = 200; // Penalty can be fine-tuned.
var lastact = new Date();
Next, we decrease score by the distance between the previous message and current in time.
/* The smaller the distance, more time has to pass in order
* to negate the score penalty cause{d,s}.
*/
score -= (new Date() - lastact) * 0.05;
// Score shouldn't be less than zero.
score = (score < 0) ? 0 : score;
Then we add the message penalty and check if it crosses the threshold:
if ( (score += penalty) > 1000 ) {
// Do things.
}
Shouldn't forget to update last action afterwards:
lastact = new Date();

My 1 page web app reduces a variable by 2 instead of 1 after completing a certain level

For some reason after the user guesses the right number and follows the confirm to play the game again but with fewer guesses (2 less than original), each time a user guesses a number the guesses remaining is deducted by 2 and sometimes just random numbers instead of the usual 1. I tried changing the code to deduct in various different ways but to no avail:
j--;
j -= 1;
j = j - 1;
Full code in Fiddle, if anyone could help that would be awesome I've been at this for hours! Thanks
partial for guess button click event
if (currentGuess < numberToGuess) {
$hintBox.html('<p class="blue">Try higher</p>');
} else {
$hintBox.html('<p class="blue">Go lower</p>');
}
j = j - 1;
$('.numberGuesses').html(j);
} // end of if guess is not correct
else if (currentGuess === numberToGuess) {
alert('Well done the correct number was '+ numberToGuess);
var playAgain = confirm("Let's see if you can do that again with less guesses.");
if (playAgain){
$('#gameDiv').hide('pulsate', 100, function(){
$('#mode').delay(200).show('pulsate', 500);
});
lowerGuesses = lowerGuesses - 2;
$('.numberGuesses').html(lowerGuesses);
} else {
location.reload();
}
}
You don't reset the counter j to lowerGuesses after you get the number right.
The code is very difficult to follow, and IMO a bit broken. Things need to be broken out much better. Isolate the "new game" code into something you call when there's actually a new game. Create a new random number. Clear out the numbers it remembers; after I fixed it it was the same number again (possible but unlikely, so I'm assuming that logic is also broken) so it both warned me that I'd already guess the number, and told me I guessed the number correctly.
Basically your game loop should be just for the game, not for preparing a new game, etc. Consider passing in the number of guesses the player should get into a newGame function (along with many other refactorings).

how can website javascript code using same input data compute a different result depending on visitor?

The javascript code snippet below is on a website. Recently I've observed the code can produce different results for a visitor on the website than I obtain from my computer using the exact same data that the visitor input to the website. This seems to be visitor dependent (some visitors are fine). I've tried several computers/operating systems in my office, and they all produce the same (correct) results as each other, derived from the visitor's input data in question.
Part of the results (not shown below) provided by the website is a plot of the user's entered data, which I observe is always correct, so I know the visitor's input data they entered into the website (from which the javascript computation uses to compute a result) are interpreted correctly by their machine (I can see the plot the user receives (generated by auto-PDF email), and the same data entered in my computer produces the exact same plot for the entered data; just the results derived from this data are different).
In one case I analyzed, the visitor's incorrect data, mysteriously, was always a factor of 1.3 lower than the correct result. It doesn't seem like a rounding error or difference in 32b vs 64b OS.
Any ideas what could be causing such a thing? Is the code below not robust for all versions of javascript, or could different javascript versions product different results (seems hard to believe, but I'm using some fancy math below, maybe one of the mat functions is antiquated). Unfortunately I don't have access to a machine producing incorrect data to troubleshoot. I also don't know anything about the machine/OS/platform used by visitors (could be anything). Any ideas appreciated. I'm not that experienced with javascript (it could be something obvious below).
Thanks in advance.
function calculate(){
var fc=document.abcform.CF.value*1;
var of = new Array(20);
var pn = new Array(20);
var pj = new Array(19);
var cbox = new Array(20);
var alpha;
var con;
var segment;
var subttl=0;
of[0]=document.abcform.OS1.value*1; pn[0]=document.abcform.abc1.value*1;
of[1]=document.abcform.OS2.value*1; pn[1]=document.abcform.abc2.value*1;
of[2]=document.abcform.OS3.value*1; pn[2]=document.abcform.abc3.value*1;
of[3]=document.abcform.OS4.value*1; pn[3]=document.abcform.abc4.value*1;
of[4]=document.abcform.OS5.value*1; pn[4]=document.abcform.abc5.value*1;
of[5]=document.abcform.OS6.value*1; pn[5]=document.abcform.abc6.value*1;
of[6]=document.abcform.OS7.value*1; pn[6]=document.abcform.abc7.value*1;
of[7]=document.abcform.OS8.value*1; pn[7]=document.abcform.abc8.value*1;
of[8]=document.abcform.OS9.value*1; pn[8]=document.abcform.abc9.value*1;
of[9]=document.abcform.OS10.value*1; pn[9]=document.abcform.abc10.value*1;
of[10]=document.abcform.OS11.value*1; pn[10]=document.abcform.abc11.value*1;
of[11]=document.abcform.OS12.value*1; pn[11]=document.abcform.abc12.value*1;
of[12]=document.abcform.OS13.value*1; pn[12]=document.abcform.abc13.value*1;
of[13]=document.abcform.OS14.value*1; pn[13]=document.abcform.abc14.value*1;
of[14]=document.abcform.OS15.value*1; pn[14]=document.abcform.abc15.value*1;
of[15]=document.abcform.OS16.value*1; pn[15]=document.abcform.abc16.value*1;
of[16]=document.abcform.OS17.value*1; pn[16]=document.abcform.abc17.value*1;
of[17]=document.abcform.OS18.value*1; pn[17]=document.abcform.abc18.value*1;
of[18]=document.abcform.OS19.value*1; pn[18]=document.abcform.abc19.value*1;
of[19]=document.abcform.OS20.value*1; pn[19]=document.abcform.abc20.value*1;
cbox[0]=document.abcform.c1.checked; cbox[1]=document.abcform.c2.checked; cbox[2]=document.abcform.c3.checked;
cbox[3]=document.abcform.c4.checked; cbox[4]=document.abcform.c5.checked; cbox[5]=document.abcform.c6.checked;
cbox[6]=document.abcform.c7.checked; cbox[7]=document.abcform.c8.checked; cbox[8]=document.abcform.c9.checked;
cbox[9]=document.abcform.c10.checked; cbox[10]=document.abcform.c11.checked; cbox[11]=document.abcform.c12.checked;
cbox[12]=document.abcform.c13.checked; cbox[13]=document.abcform.c14.checked; cbox[14]=document.abcform.c15.checked;
cbox[15]=document.abcform.c16.checked; cbox[16]=document.abcform.c17.checked; cbox[17]=document.abcform.c18.checked;
cbox[18]=document.abcform.c19.checked; cbox[19]=document.abcform.c20.checked;
for (var i = 0; i <= 18; i++) { pj[i] = '' }
for (var j = 1; j <= 19; j++){
if (j == 1 || cbox[j]) {
alpha = (pn[j-1] - pn[j])/(10*(Math.LOG10E*Math.log(of[j]/of[j-1])));
con = (Math.pow(of[j-1],alpha))*(Math.pow(10,0.1*pn[j-1]));
if ((alpha <= (1 + 1e-14)) && (alpha >= (1 - 1e-14))) {
segment = con*Math.log(of[j]/of[j-1]); }
else { segment = (con/(1-alpha))*(Math.pow(of[j],1-alpha)-Math.pow(of[j-1],1-alpha)); }
pj[j-1] = round(1E12*(Math.sqrt(2*segment))/(2*Math.PI*fc));
subttl = subttl + Math.pow(pj[j-1],2);
} else {break;}
}
document.abcform.pj1.value=pj[0]; document.abcform.pj2.value=pj[1]; document.abcform.pj3.value=pj[2];
document.abcform.pj4.value=pj[3]; document.abcform.pj5.value=pj[4]; document.abcform.pj6.value=pj[5];
document.abcform.pj7.value=pj[6]; document.abcform.pj8.value=pj[7]; document.abcform.pj9.value=pj[8];
document.abcform.pj10.value=pj[9]; document.abcform.pj11.value=pj[10]; document.abcform.pj12.value=pj[11];
document.abcform.pj13.value=pj[12]; document.abcform.pj14.value=pj[13]; document.abcform.pj15.value=pj[14];
document.abcform.pj16.value=pj[15]; document.abcform.pj17.value=pj[16]; document.abcform.pj18.value=pj[17];
document.abcform.pj19.value=pj[18];
document.abcform.tj.value=round(Math.sqrt(subttl));
}
function round(x) { return Math.round(x*100000)/100000; }
Doesn't seem like a rounding error or
difference in 32b vs 64b OS.
Why not... this is exactly what it seems like. Maybe even a 16bit machine for that matter. You are doing lots of crazy floating point operations -- they typically perform lots of truncation and rounding.
Option two: The log or pow or sqrt functions are implemented differently on different browsers. Solution -- implement your own and see if you get the same "different" results.
Definitely sounds like rounding errors to me, and it doesn't matter what the underlying elements are (64 bit, 32 bit, implementations of pow, etc).
Consider:
alpha = (pn[j-1] - pn[j])/(10*(Math.LOG10E*Math.log(of[j]/of[j-1])));
(Math.pow(of[j-1],alpha))*(Math.pow(10,0.1*pn[j-1]))
That right there can have different results, since it's all floating math. You'll have to either use ints, or something like BigNumber.
In cases like that printf debugging is sometimes helpful - print out all the intermediate values (like alpha) for all the iterations and then compare the outputs to see where they are different. Gives you a starting point.
After debugging, it turns out this is related to a loss of precision by converting to scientific notation in code not shown above. Thus, it's a non-javascript issue (e.g. user error). Thanks for all of the insight above though.

Categories