Anticheating engine - how to improve this?

General FreeBASIC programming questions.
Post Reply
mrminecrafttnt
Posts: 131
Joined: Feb 11, 2013 12:23

Anticheating engine - how to improve this?

Post by mrminecrafttnt »

Hi i am actually improving my anticheating engine. Any ideas? :)
It encrypts the orignal value and hashes this encrypted value after this. Good look to cheat.. :)

Code: Select all

type anticheat
    value as integer
    key as integer
    hash as integer
    declare sub set (v as integer)
    declare function get as integer
end type

sub anticheat.set (v as integer)
    key = int(rnd*999999999)
    value = v xor key
    hash = key + value
end sub

function anticheat.get as integer
    if hash = key + value then
        return value xor key
    else
        return 0
    end if
end function


'###example starts here###

dim as anticheat score
score.set 10000
Print "CHEAT ME! INCRASE WITH + / DECRASE WITH -"

do
    locate 2
    print score.get
    select case input(1)
    case "+"
        score.set score.get + 1
    case "-"
        score.set score.get - 1
    case else
        exit do
    end select
loop
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Anticheating engine - how to improve this?

Post by counting_pine »

I guess ultimately it will probably always be crackable by someone with the source code.
One vulnerability to note is, if the salt is 0, the hash will be the same as the value.
Also, in general, if the value is low, there will be a lot of similarity between the salt (key) and the hash.

It would give more (not complete) protection if it were harder to calculate the required hash from the value and the salt.

Unfortunately there's probably no practical way to protect the salt. But making it a global instead of an instance variable would actually give a lot of protection (you can't change it without fixing every variable), and would be more time/space efficient.

Also, you should probably quit or something if the value has the wrong hash. Returning 0 might be desirable for a cheater (for a trivial example, maybe a stopwatch or an enemy's stats)
mrminecrafttnt
Posts: 131
Joined: Feb 11, 2013 12:23

Re: Anticheating engine - how to improve this?

Post by mrminecrafttnt »

New features:
-some obusfactoring
-error compension
-returning random numbers when a cheat was detected in multiple cases
-timer based anti debugging
Good look to cheat this! :)

Code: Select all

type anticheat
    T as integer
    errorcompension as integer
    value(2) as integer
    key(2) as integer
    hash as integer
    declare sub set (v as integer)
    declare function get as integer
end type

sub anticheat.set (v as integer)
    dim as integer trys = 10
    do
        key(0) = int(rnd*999999999)
        key(1) = int(rnd*999999999)
        trys-=1
        if trys = 0 then exit do
    loop until key(0) > 0 and key(1) > 0
    if errorcompension = 0 then
       
        value(0) = v xor key(0)
    else
       
        value(1) = v xor key(1)
        errorcompension = 1
    end if
    if errorcompension > ubound(value) then set v
    if (value(errorcompension) xor key(errorcompension)) <> v then errorcompension = 1 : set v
    hash = key(errorcompension) + value(errorcompension)
    if hash = 0 or key(errorcompension) = 0 then set v
    T =CINT(TIMER)
end sub

function anticheat.get as integer
   
    if hash = 0 and key(errorcompension) = 0 then return int(rnd*9999999) : errorcompension = 1
    if hash = key(errorcompension) + value(errorcompension) then
        if value(errorcompension) = (value(errorcompension) xor key(errorcompension)) then
            return int(Rnd*9999999)
        end if
        if cint(timer)-t > 1 then set int(rnd*9999999) 'anti debugging.. ;)
        set value(errorcompension) xor key(errorcompension)
        return value(errorcompension) xor key(errorcompension)
    else
        return int(rnd*9999999)
    end if
end function


'###example starts here###
locate ,,0
dim as anticheat score
score.set 10000
Print "CHEAT ME! INCRASE WITH + / DECRASE WITH -, ESC TO EXIT"

do
    locate 2
    print score.get
    select case inkey
    case "+"
        score.set score.get + 1
    case "-"
        score.set score.get - 1
    case chr(27)
        exit do
    end select
loop
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Anticheating engine - how to improve this?

Post by counting_pine »

Unfortunately I can't follow the code any more, so the most I can say is it's secure by obscurity to some extent.

A quick note about arrays: 'dim a(2)' is equivalent to 'dim a(0 to 2)', which of course gives three elements.
I always recommend doing 'dim a(0 to N-1)'. If N is known of course, it is probably clearer to just put e.g. '0 to 1' instead '0 to 2-1'.

I see a lot of 'int(rnd()*9999...)', with different numbers of 9's. note that this gives a number between 0 and 9999...98, so for a specific number of decimal digits, something like 'int(rnd()*1e10)' would be clearer and more accurate.

Presumably though, the intent is to get a random 32-bit integer, so it's worth writing a function that does this exactly:

Code: Select all

function rnd32() as ulong
  return int(rnd * 2^32)
end function
For a random 64-bit integer, you'd have to do something like 'rnd32() + culngint(rnd32()) shl 32', because rnd() doesn't return 64 bits of precision.

What does 'errorcompension' do? "compension" isn't an English word, so possibly you mean "compensation", but the meaning still isn't clear.

By the way, it occurs to me that if anyone debugs your program and finds the functions that set/get the values, it would be possible for them just to call the functions directly.
mrminecrafttnt
Posts: 131
Joined: Feb 11, 2013 12:23

Re: Anticheating engine - how to improve this?

Post by mrminecrafttnt »

-Selftest added for Randomizer and the main functions
-Instructioncounter added that detected if too much code changed -> output is an random value
-Warning added for cheaters, this will be triggered when too much code is changed
Happy hacking! :)

Code: Select all

type ash
    value as integer
    declare constructor
end type

constructor ash
    value = -2
end constructor
   

dim shared instruction as ubyte 'for checking the amount of instructions
type anticheat
    T as integer
    errorcompension as integer 'if have one group (value and key) have bad values
                               'so try next (up to errorcompension 2)
                               'if this fails so is the thread trapped in an loop now :)
    value(2) as integer
    key(2) as integer
    hash as integer
    dim as integer cheatdetection 'cheatid code
    anti_selftesthack as ash
    declare sub set (v as integer)
    declare function get as integer
    declare function rnd32 as integer
    declare constructor
end type

constructor anticheat
    cheatdetection = anti_selftesthack.value   
    dim as integer v1 = rnd32
    dim as integer v2 = rnd32
    if v1 = v2 then cheatdetection = 8
    dim as integer v = 123456
    if v = 0 then cheatdetection = 7
    color 15
    Print "Selftest results: ";
    Print "RANDOMIZER..";
   
    if rnd32 > 0 and (rnd32 <> rnd32) and (v1 <> v2-1) then
        color 10 :
        pRINT "PASSED";
        cheatdetection+=1
    else
        color 12
        print "FAILED";
        cheatdetection = 5
    end if
    color 15
    PRINT "..SABOTAGE DETECTION..";
   
    set v
    if get <> v then cheatdetection = 1
    set v + 1
    if get <> v + 1 then cheatdetection = 2
    set get - 2
    if get <> v - 1 then cheatdetection = 3
    set 0
    if get <> 0 then cheatdetection = 4
    cheatdetection+=1
    if cheatdetection = 0 then
        color 10
        print "PASSED"
       
    ELSE
       
        color 12
        PRINT "FAILED"
    end if
    color 7
end constructor

function anticheat.rnd32 as integer
  static x as integer
  x+=1
  return int(rnd * 2^31)
end function
   
   
sub anticheat.set (v as integer)
    if cheatdetection > 0 then exit sub
    instruction+=1
    dim as integer trys = 10
    do
        key(0) = rnd32
        key(1) = rnd32
        trys-=1
        if trys = 0 then exit do
    loop until key(0) > 0 and key(1) > 0
    do
        if errorcompension = 0 then
            value(0) = v xor key(0)
            if value(0) <> (v xor key(0)) then
                errorcompension = 1
                end if
            else
                value(1) = v xor key(1)
                errorcompension = 1
                if value(1) <> (v xor key(1)) then
                    errorcompension = 2
                key(2)= rnd32
                value(2) = v xor key(2)
            end if
        end if
    trys-=1
    if errorcompension > 0 then print "WARNING! TRYING TO CHEAT WAS DETECTED! - THIS WILL NOT BE TOLERATED!"
loop until value(errorcompension) = (v xor key(errorcompension)) or trys <= 0
    if errorcompension > ubound(value) then set v
    if (value(errorcompension) xor key(errorcompension)) <> v then errorcompension = 1 : set v
    hash = key(errorcompension) + value(errorcompension)
    if hash = 0 or key(errorcompension) = 0 then set v
    T =CINT(TIMER)
end sub

function anticheat.get as integer
    if cheatdetection > 0 then return rnd32
    static oi as integer
    oi = instruction
   instruction+=1
    if hash = 0 and key(errorcompension) = 0 then return rnd32: errorcompension = 1
    if hash = key(errorcompension) + value(errorcompension) then
        if value(errorcompension) = (value(errorcompension) xor key(errorcompension)) then
            return rnd32
        end if
        if cint(timer)-t > 1 then set rnd32 'anti debugging.. ;)
        set value(errorcompension) xor key(errorcompension)
        if instruction-oi <> 2 then cheatdetection = 6
        instruction = 0
        return value(errorcompension) xor key(errorcompension)
    else
        return rnd32
    end if
end function


'###example starts here###
locate ,,0
dim as anticheat score
score.set 10000
Print "CHEAT ME! INCRASE WITH + / DECRASE WITH -, ESC TO EXIT"

do
    locate 3
    print hex(@score)
    print score.get
    select case inkey
    case "+"
        score.set score.get + 1
    case "-"
        score.set score.get - 1
    case chr(27)
        exit do
    end select
loop
Post Reply