PDA

View Full Version : Script Scanner (Scans for malicious scripts)



rj
05-24-2013, 03:54 PM
Script Scanner By Officer Barbrady and Janilabo

The extension/Scanner is now updated on this thread and can be downloaded there: http://villavu.com/forum/showthread.php?t=103996
::for the autoupdate2.09abcdef::
::fgeyhfVersion 2.07 has been released as a script and a extension!jdshkhu::

Latest Version:2.09

Ian
05-24-2013, 03:56 PM
False positives in 3, 2, 1

rj
05-24-2013, 03:59 PM
False positives in 3, 2, 1

Alerts user of potential threats so they can look into them.

Janilabo
05-24-2013, 05:12 PM
...
Nice work, Officer Barbrady.
It is looking good so far. :)

I noticed just 1 issue though - the way you count string's is currently like 50/50 case-sensitive, because you never used Lowercase() for Script_Text in these parts listed below..

Line 104:

(CountString(LowerCase('user'), script_text,True)>1)

Line 116:

if (CountString(LowerCase('pass'), script_text,True)>1) then

Line 122:

if (CountString(LowerCase('pin'), script_text,True)>1) then

Although! I think you might need just 1 lowercase() in your script, to this part, at line 196:


Script_text := ScriptEdit.TEXT; // Lowercase() that, and you'll need to use Lowercase for script_text only once in your script (you can remove Lowercase()'s from FindText*()'s then)

Thumbs up for creativity with this script. :) Keep up the good work! Gotta love small but useful utilities like these!

Regards,
-Jani

rj
05-24-2013, 05:22 PM
Nice work, Officer Barbrady.
It is looking good so far. :)

I noticed just 1 issue though - the way you count string's is currently like 50/50 case-sensitive, because you never used Lowercase() for Script_Text in these parts listed below..

Line 104:

(CountString(LowerCase('user'), script_text,True)>1)

Line 116:

if (CountString(LowerCase('pass'), script_text,True)>1) then

Line 122:

if (CountString(LowerCase('pin'), script_text,True)>1) then

Although! I think you might need just 1 lowercase() in your script, to this part, at line 196:


Script_text := ScriptEdit.TEXT; // Lowercase() that, and you'll need to use Lowercase for script_text only once in your script (you can remove Lowercase()'s from FindText*()'s then)

Thumbs up for creativity with this script. :) Keep up the good work! Gotta love small but useful utilities like these!

Regards,
-Jani

Thanks, I still want to add more features to prevent false positives though

Janilabo
05-24-2013, 05:48 PM
Thanks, I still want to add more features to prevent false positives thoughI think the key would be to use regex (regular expression) functions, to prevent those false positives.
Learning to use those regex commands might take a while though, because regex is frustrating sometimes...
However, internet is full of good tutorial pages about regex. :) Also, plenty of good video tutorials @YouTube aswell..
+There is even 1 tutorial here at SRL-forums about regex, Regular Expressions (http://villavu.com/forum/showthread.php?t=84709) by Brandon.

I wrote a function to SCAR Divi, that would be PERFECT for this, but I'll need to try and convert it to Simba aswell (I am not very familiar with Simba's regex commands, to be honest).
It is this one below:


const
TEXT = 'TestesTESTTestest test TEST Test Test.';
FIND_STR = 'test';

type
TMatchMethod = (mmAll, mmBackward, mmIgnoreCase, mmOverlap, mmWholeWords, mmStrictWW);
TMatchMethods = set of TMatchMethod;

function Find(Text, FindStr: string; Methods: TMatchMethods; Offset: Integer): TIntArray;
var
tL, fsL, d, i, t: Integer;
rgx_fs: string;
r: TRegexMatchArray;
begin
fsL := Length(FindStr);
tL := Length(Text);
if ((tL < 1) or (Length(FindStr) > tL) or (FindStr = '')) then
Exit;
if (Offset < 1) then
Offset := 1;
FindStr := PregQuote(FindStr);
if (mmWholeWords in Methods) then
begin
if (mmStrictWW in Methods) then
rgx_fs := '/(?<!\S)' + FindStr + '(?!\S)/'
else
rgx_fs := '/(^|\b|(?<=\s))' + FindStr + '((?=\s)|\b|$)/';
end else
rgx_fs := '/' + FindStr + '/';
if (mmIgnoreCase in Methods) then
rgx_fs := (rgx_fs + 'i');
rgx_fs := (rgx_fs + 'm');
if (mmOverlap in Methods) then
SetLength(Result, (tL - (fsL - 1)))
else
SetLength(Result, ((tL div fsL) + 1));
case (mmBackward in Methods) of
True:
begin
Text := Copy(Text, 1, Offset);
while PregMatchEx(rgx_fs, Text, r) do
begin
Result[d] := (r[0].Offset + d);
Inc(d);
Delete(Text, r[0].Offset, 1);
SetLength(r, 0);
end;
SetLength(Result, d);
if (mmAll in Methods) then
ReverseTIA(Result)
else
if (d > 0) then
Result := [Result[(d - 1)]];
if (mmAll in Methods) then
if not (mmOverlap in Methods) then
if (d > 1) then
for i := (0 + t) to ((d - 2) - t) do
if ((Result[i] - Result[(i + 1)]) <= fsL) then
begin
Result[(i + 1)] := Result[i];
Delete(Result, i, 1);
Inc(t);
end;
end;
False:
begin
if (Offset > 1) then
Delete(Text, 1, (Offset - 1));
if (mmAll in Methods) then
begin
while PregMatchEx(rgx_fs, Text, r) do
begin
Result[d] := ((r[0].Offset + d) + (Offset - 1));
Inc(d);
Delete(Text, r[0].Offset, 1);
SetLength(r, 0);
end;
SetLength(Result, d);
if (mmAll in Methods) then
if not (mmOverlap in Methods) then
if (d > 1) then
for i := (0 + t) to ((d - 2) - t) do
if ((Result[(i + 1)] - Result[i]) <= fsL) then
begin
Result[(i + 1)] := Result[i];
Delete(Result, i, 1);
Inc(t);
end;
end else
if PregMatchEx(rgx_fs, Text, r) then
begin
Result := [((r[0].Offset + d) + (Offset - 1))];
SetLength(r, 0);
end;
end;
end;
TIAUnique(Result);
end;

var
l, h, i, i2, s, o: Integer;
TIA: TIntArray;
m_sets: array of TMatchMethods;
TSA: TStrArray;

procedure BuildSets(find_method: (fmBackward, fmForward));
begin
case find_method of
fmForward:
begin
TSA := ['[]', '[mmIgnoreCase]', '[mmIgnoreCase, mmAll]', '[mmIgnoreCase, mmAll, mmOverlap]', '[mmIgnoreCase, mmAll, mmOverlap, mmWholeWords]', '[mmIgnoreCase, mmAll, mmOverlap, mmWholeWords, mmStrictWW]'];
l := Length(FIND_STR);
o := 1;
s := High(TSA);
SetLength(m_sets, (s + 1));
m_sets[0] := [];
m_sets[1] := [mmIgnoreCase];
m_sets[2] := [mmIgnoreCase, mmAll];
m_sets[3] := [mmIgnoreCase, mmAll, mmOverlap];
m_sets[4] := [mmIgnoreCase, mmAll, mmOverlap, mmWholeWords];
m_sets[5] := [mmIgnoreCase, mmAll, mmOverlap, mmWholeWords, mmStrictWW];
end;
fmBackward:
begin
TSA := ['[mmBackward]', '[mmBackward, mmIgnoreCase]', '[mmBackward, mmIgnoreCase, mmAll]', '[mmBackward, mmIgnoreCase, mmAll, mmOverlap]', '[mmBackward, mmIgnoreCase, mmAll, mmOverlap, mmWholeWords]', '[mmBackward, mmIgnoreCase, mmAll, mmOverlap, mmWholeWords, mmStrictWW]'];
l := Length(FIND_STR);
o := Length(TEXT);
s := High(TSA);
SetLength(m_sets, (s + 1));
m_sets[0] := [mmBackward];
m_sets[1] := [mmBackward, mmIgnoreCase];
m_sets[2] := [mmBackward, mmIgnoreCase, mmAll];
m_sets[3] := [mmBackward, mmIgnoreCase, mmAll, mmOverlap];
m_sets[4] := [mmBackward, mmIgnoreCase, mmAll, mmOverlap, mmWholeWords];
m_sets[5] := [mmBackward, mmIgnoreCase, mmAll, mmOverlap, mmWholeWords, mmStrictWW];
end;
end;
end;

begin
ClearDebug;
BuildSets(fmForward);
WriteLn('FORWARD:');
for i := 0 to s do
begin
TIA := Find(TEXT, FIND_STR, m_sets[i], o);
h := High(TIA);
WriteLn('Find(''' + FIND_STR + ''', ''' + TEXT + ''', ' + TSA[i] + ', ' + IntToStr(o) + ')')
for i2 := 0 to h do
WriteLn('Match[' + IntToStr(i2 + 1) + ']: ' + Copy(TEXT, TIA[i2], l) + ' (@POS.' + IntToStr(TIA[i2]) + ')');
WriteLn('');
SetLength(TIA, 0);
end;
BuildSets(fmBackward)
WriteLn('BACKWARD:');
for i := 0 to s do
begin
TIA := Find(TEXT, FIND_STR, m_sets[i], o);
h := High(TIA);
WriteLn('Find(''' + FIND_STR + ''', ''' + TEXT + ''', ' + TSA[i] + ', ' + IntToStr(o) + ')')
for i2 := 0 to h do
WriteLn('Match[' + IntToStr(i2 + 1) + ']: ' + Copy(TEXT, TIA[i2], l) + ' (@POS.' + IntToStr(TIA[i2]) + ')');
if (i < s) then
WriteLn('');
SetLength(TIA, 0);
end;
SetLength(m_sets, 0);
SetLength(TSA, 0);
end.

Regards,
-Jani

Chicago Bull
05-24-2013, 10:43 PM
Thanks Officer, I will be using this to check any scripts I use in the future, no doubt about it. :)

Chris!
05-24-2013, 11:29 PM
Not a bad script here, Officer Barbrady. Not bad at all. Very useful.

samerdl
05-25-2013, 12:34 AM
very nice thank you!

rj
05-25-2013, 06:23 PM
Thanks guys, will be adding more once I get back home

Janilabo
05-26-2013, 03:08 AM
Been converting Find() from SCAR Divi to Simba, but uhm... Things got just a "little bit" more complicated than I expected in the first place...
The main problem is that, Simba's current regex library doesn't support lookaround (behind, ahead). :\ So I had to add in a lot of creepy workarounds..

Also, I had to leave "mmBackwards" (backwards searching) out aswell - may add it in later, not sure.

This is what the code looks like currently:


const
TEXT = 'TEST! Test, Test1 test? test TeSt testest testtest test.';
STR = 'test';

{================================================= =============================]
Explanation: Important types for Find() function! Contains the string matching methods.
[================================================== ============================}
type
TMatchMethod = (mmAll, mmIgnoreCase, mmOverlap, mmWholeWords, mmStrictWW);
TMatchMethods = set of TMatchMethod;

{================================================= =============================]
Explanation: Returns a TIA that contains all the value from start value (aStart) to finishing value (aFinish)..
[================================================== ============================}
function TIAByRange(aStart, aFinish: Integer): TIntegerArray;
var
i, s, f: Integer;
begin
if (aStart <> aFinish) then
begin
s := Integer(aStart);
f := Integer(aFinish);
SetLength(Result, (IAbs(aStart - aFinish) + 1));
case (aStart > aFinish) of
True:
for i := s downto f do
Result[(s - i)] := i;
False:
for i := s to f do
Result[(i - s)] := i;
end;
end else
Result := [Integer(aStart)];
end;

{================================================= =============================]
Explanation: Merges T2DIntegerArray (ATIA) to TIntegerArray.
Example: [[1, 2], [3, 4]] => [1, 2, 3, 4]
[================================================== ============================}
function ATIAMerge(ATIA: T2DIntegerArray): TIntegerArray;
var
i, i2, h, h2, r: Integer;
begin
h := High(ATIA);
if (h > -1) then
begin
for i := 0 to h do
IncEx(r, (High(ATIA[i]) + 1));
SetLength(Result, r);
r := 0;
for i := 0 to h do
begin
h2 := High(ATIA[i]);
for i2 := 0 to h2 do
begin
Result[r] := Integer(ATIA[i][i2]);
Inc(r);
end;
end;
end else
SetLength(Result, 0);
end;

{================================================= =============================]
Explanation: Returns the string that is behind the position in data, size being the length for result that is copied from position.
[================================================== ============================}
function Behind(data: string; position, size: Integer): string;
var
l, r: Integer;
begin
l := Length(data);
case ((l > 0) and (position > 1) and (size > 0)) of
True:
begin
if ((position - size) < 1) then
size := ((position - size) + (size - 1));
if (position > (l + 1)) then
begin
r := ((position - l) - 1);
size := (size - r);
end;
Result := Copy(data, ((position - size) - r), size);
end;
False: Result := '';
end;
end;

{================================================= =============================]
Explanation: Returns the string that is ahead from position in data, size being the length for result that is copied from position.
[================================================== ============================}
function Ahead(data: string; position, size: Integer): string;
var
l: Integer;
begin
l := Length(data);
case ((l > 0) and (position <= l) and (size > 0)) of
True:
begin
if (position < 1) then
begin
size := (size - iAbs(position - 1));
position := 1;
end;
if ((size > 0) and ((position + size) > l)) then
size := (size - (((position + size) - l) - 1));
Result := Copy(data, position, size);
end;
False: Result := '';
end;
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Contains field for offset.
[================================================== ============================}
function FindEx(text, findStr: string; methods: TMatchMethods; offset: Integer): TIntegerArray;
var
sb, sa: string;
r, l, f, o, p, d, x, y: Integer;
re: TRegExp;
ma, mb, a, s, ol: Boolean;
c: TIntegerArray;
begin
l := Length(text);
f := Length(findStr);
if ((l > 0) and (f > 0) and (offset <= (l - f))) then
begin
if (offset < 1) then
offset := 1;
SetLength(Result, l);
re := TRegExp.Create;
re.InputString := text;
re.Expression := findStr;
if (mmIgnoreCase in methods) then
re.ModifierI := True;
a := (mmAll in methods);
case a of
False: re.ModifierG := True;
True: re.ModifierG := False;
end;
ol := (mmOverlap in methods);
if not ol then
o := (Length(findStr) - 1);
Inc(o);
p := Offset;
if re.ExecPos(p) then
repeat
if (re.Match[0] <> '') then
begin
Result[r] := re.MatchPos[0];
p := (Result[r] + o);
Inc(r);
end;
until not re.ExecPos(p);
re.Free;
SetLength(Result, r);
if ((r > 0) and (mmWholeWords in methods)) then
begin
s := (mmStrictWW in methods);
if not s then
c := ATIAMerge([TIAByRange(Ord('A'), Ord('Z')), TIAByRange(Ord('a'), Ord('z')), TIAByRange(Ord('0'), Ord('9'))]);
for x := (r - 1) downto 0 do
begin
sb := Behind(text, Result[x], 1);
sa := Ahead(text, (Result[x] + f), 1);
case s of
True:
begin
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: mb := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or ((sb = ' ') or (sb = '')));
False: mb := (((Result[x] - Result[(x - 1)]) <= f) or ((sb = ' ') or (sb = '')));
end;
False:
case ((r - 1) > x) of
True: mb := (((Result[(x + 1)] - Result[x]) <= f) or ((sb = ' ') or (sb = '')));
False: mb := ((sb = ' ') or (sb = ''));
end;
end;
False: mb := ((sb = ' ') or (sb = ''));
end;
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: ma := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or ((sa = ' ') or (sa = '')));
False: ma := (((Result[x] - Result[(x - 1)]) <= f) or ((sa = ' ') or (sa = '')));
end;
False:
case ((r - 1) > x) of
True: ma := (((Result[(x + 1)] - Result[x]) <= f) or ((sa = ' ') or (sa = '')));
False: ma := ((sa = ' ') or (sa = ''));
end;
end;
False: ma := ((sa = ' ') or (sa = ''));
end;
end;
False:
begin
case (sb <> '') of
True:
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: mb := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or not InIntArray(c, Ord(sb[1])));
False: mb := (((Result[x] - Result[(x - 1)]) <= f) or not InIntArray(c, Ord(sb[1])));
end;
False:
case ((r - 1) > x) of
True: mb := (((Result[(x + 1)] - Result[x]) <= f) or not InIntArray(c, Ord(sb[1])));
False: mb := not InIntArray(c, Ord(sb[1]));
end;
end;
False: mb := not InIntArray(c, Ord(sb[1]));
end;
False: mb := True;
end;
case (sa <> '') of
True:
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: ma := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or not InIntArray(c, Ord(sa[1])));
False: ma := (((Result[x] - Result[(x - 1)]) <= f) or not InIntArray(c, Ord(sa[1])));
end;
False:
case ((r - 1) > x) of
True: ma := (((Result[(x + 1)] - Result[x]) <= f) or not InIntArray(c, Ord(sa[1])));
False: ma := not InIntArray(c, Ord(sa[1]));
end;
end;
False: ma := not InIntArray(c, Ord(sa[1]));
end;
False: ma := True;
end;
end;
end;
if not (mb and ma) then
begin
y := (r - 1);
for d := x to (y - 1) do
Result[d] := Result[(d + 1)];
SetLength(Result, y);
Dec(r);
end;
end;
end;
if (not a and (r > 0)) then
SetLength(Result, 1);
end else
SetLength(Result, 0);
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Without offset field.
[================================================== ============================}
function Find(text, findStr: string; methods: TMatchMethods): TIntegerArray;
begin
Result := FindEx(text, findStr, methods, 1);
end;

begin
ClearDebug;
WriteLn(ToStr(Find(TEXT, STR, [mmIgnoreCase, mmWholeWords, mmStrictWW])) + ' Find(TEXT, STR, [mmIgnoreCase, mmWholeWords, mmStrictWW])');
WriteLn(ToStr(Find(TEXT, STR, [mmIgnoreCase, mmWholeWords])) + ' Find(TEXT, STR, [mmIgnoreCase, mmWholeWords])');
WriteLn(ToStr(Find(TEXT, STR, [mmIgnoreCase])) + ' Find(TEXT, STR, [mmIgnoreCase])');
WriteLn(ToStr(Find(TEXT, STR, [])) + ' Find(TEXT, STR, [])');
WriteLn(ToStr(Find(TEXT, STR, [mmAll])) + ' Find(TEXT, STR, [mmAll])');
WriteLn(ToStr(Find(TEXT, STR, [mmAll, mmIgnoreCase])) + ' Find(TEXT, STR, [mmAll, mmIgnoreCase])');
WriteLn(ToStr(Find(TEXT, STR, [mmAll, mmIgnoreCase, mmWholeWords])) + ' Find(TEXT, STR, [mmAll, mmIgnoreCase, mmWholeWords])');
WriteLn(ToStr(Find(TEXT, STR, [mmAll, mmIgnoreCase, mmWholeWords, mmStrictWW])) + ' Find(TEXT, STR, [mmAll, mmIgnoreCase, mmWholeWords, mmStrictWW])');
end.

..it's a bit ugly/scary to be honest, but hay, that's mainly because I have been working on it all night today. So... :p I'll try and cut out some unneeded lines within time.

Right now, all the included methods, except "mmOverlap", are stable and working smoothly.
The logic of overlapping support still requires some work - it's not that bad really, I would say it is just fine for most uses.
Main issue of it being that right now it doesn't really pay attention to overlapped item's boundaries (start / end), like the function does without mmOverlap (sorry about the explanation, this part is hard for me to explain, ouch)

The reason why I am posting about this here, is because this particular function has potential to get rid of those false positives in your script, Officer Barbrady.. :)

-Jani

rj
05-26-2013, 03:13 AM
Been converting Find() from SCAR Divi to Simba, but uhm... Things got just a "little bit" more complicated than I expected in the first place...
The main problem is that, Simba's current regex library doesn't support lookaround (behind, ahead). :\ So I had to add in a lot of creepy workarounds..

Also, I had to leave "mmBackwards" (backwards searching) out aswell - may add it in later, not sure.

This is what the code looks like currently:


const
TEXT = 'TEST! Test, Test1 test? test TeSt testest testtest test.';
STR = 'test';

{================================================= =============================]
Explanation: Important types for Find() function! Contains the string matching methods.
[================================================== ============================}
type
TMatchMethod = (mmAll, mmIgnoreCase, mmOverlap, mmWholeWords, mmStrictWW);
TMatchMethods = set of TMatchMethod;

{================================================= =============================]
Explanation: Returns a TIA that contains all the value from start value (aStart) to finishing value (aFinish)..
[================================================== ============================}
function TIAByRange(aStart, aFinish: Integer): TIntegerArray;
var
i, s, f: Integer;
begin
if (aStart <> aFinish) then
begin
s := Integer(aStart);
f := Integer(aFinish);
SetLength(Result, (IAbs(aStart - aFinish) + 1));
case (aStart > aFinish) of
True:
for i := s downto f do
Result[(s - i)] := i;
False:
for i := s to f do
Result[(i - s)] := i;
end;
end else
Result := [Integer(aStart)];
end;

{================================================= =============================]
Explanation: Merges T2DIntegerArray (ATIA) to TIntegerArray.
Example: [[1, 2], [3, 4]] => [1, 2, 3, 4]
[================================================== ============================}
function ATIAMerge(ATIA: T2DIntegerArray): TIntegerArray;
var
i, i2, h, h2, r: Integer;
begin
h := High(ATIA);
if (h > -1) then
begin
for i := 0 to h do
IncEx(r, (High(ATIA[i]) + 1));
SetLength(Result, r);
r := 0;
for i := 0 to h do
begin
h2 := High(ATIA[i]);
for i2 := 0 to h2 do
begin
Result[r] := Integer(ATIA[i][i2]);
Inc(r);
end;
end;
end else
SetLength(Result, 0);
end;

{================================================= =============================]
Explanation: Returns the string that is behind the position in data, size being the length for result that is copied from position.
[================================================== ============================}
function Behind(data: string; position, size: Integer): string;
var
l, r: Integer;
begin
l := Length(data);
case ((l > 0) and (position > 1) and (size > 0)) of
True:
begin
if ((position - size) < 1) then
size := ((position - size) + (size - 1));
if (position > (l + 1)) then
begin
r := ((position - l) - 1);
size := (size - r);
end;
Result := Copy(data, ((position - size) - r), size);
end;
False: Result := '';
end;
end;

{================================================= =============================]
Explanation: Returns the string that is ahead from position in data, size being the length for result that is copied from position.
[================================================== ============================}
function Ahead(data: string; position, size: Integer): string;
var
l: Integer;
begin
l := Length(data);
case ((l > 0) and (position <= l) and (size > 0)) of
True:
begin
if (position < 1) then
begin
size := (size - iAbs(position - 1));
position := 1;
end;
if ((size > 0) and ((position + size) > l)) then
size := (size - (((position + size) - l) - 1));
Result := Copy(data, position, size);
end;
False: Result := '';
end;
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Contains field for offset.
[================================================== ============================}
function FindEx(text, findStr: string; methods: TMatchMethods; offset: Integer): TIntegerArray;
var
sb, sa: string;
r, l, f, o, p, d, x, y: Integer;
re: TRegExp;
ma, mb, a, s, ol: Boolean;
c: TIntegerArray;
begin
l := Length(text);
f := Length(findStr);
if ((l > 0) and (f > 0) and (offset <= (l - f))) then
begin
if (offset < 1) then
offset := 1;
SetLength(Result, l);
re := TRegExp.Create;
re.InputString := text;
re.Expression := findStr;
if (mmIgnoreCase in methods) then
re.ModifierI := True;
a := (mmAll in methods);
case a of
False: re.ModifierG := True;
True: re.ModifierG := False;
end;
ol := (mmOverlap in methods);
if not ol then
o := (Length(findStr) - 1);
Inc(o);
p := Offset;
if re.ExecPos(p) then
repeat
if (re.Match[0] <> '') then
begin
Result[r] := re.MatchPos[0];
p := (Result[r] + o);
Inc(r);
end;
until not re.ExecPos(p);
re.Free;
SetLength(Result, r);
if ((r > 0) and (mmWholeWords in methods)) then
begin
s := (mmStrictWW in methods);
if not s then
c := ATIAMerge([TIAByRange(Ord('A'), Ord('Z')), TIAByRange(Ord('a'), Ord('z')), TIAByRange(Ord('0'), Ord('9'))]);
for x := (r - 1) downto 0 do
begin
sb := Behind(text, Result[x], 1);
sa := Ahead(text, (Result[x] + f), 1);
case s of
True:
begin
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: mb := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or ((sb = ' ') or (sb = '')));
False: mb := (((Result[x] - Result[(x - 1)]) <= f) or ((sb = ' ') or (sb = '')));
end;
False:
case ((r - 1) > x) of
True: mb := (((Result[(x + 1)] - Result[x]) <= f) or ((sb = ' ') or (sb = '')));
False: mb := ((sb = ' ') or (sb = ''));
end;
end;
False: mb := ((sb = ' ') or (sb = ''));
end;
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: ma := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or ((sa = ' ') or (sa = '')));
False: ma := (((Result[x] - Result[(x - 1)]) <= f) or ((sa = ' ') or (sa = '')));
end;
False:
case ((r - 1) > x) of
True: ma := (((Result[(x + 1)] - Result[x]) <= f) or ((sa = ' ') or (sa = '')));
False: ma := ((sa = ' ') or (sa = ''));
end;
end;
False: ma := ((sa = ' ') or (sa = ''));
end;
end;
False:
begin
case (sb <> '') of
True:
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: mb := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or not InIntArray(c, Ord(sb[1])));
False: mb := (((Result[x] - Result[(x - 1)]) <= f) or not InIntArray(c, Ord(sb[1])));
end;
False:
case ((r - 1) > x) of
True: mb := (((Result[(x + 1)] - Result[x]) <= f) or not InIntArray(c, Ord(sb[1])));
False: mb := not InIntArray(c, Ord(sb[1]));
end;
end;
False: mb := not InIntArray(c, Ord(sb[1]));
end;
False: mb := True;
end;
case (sa <> '') of
True:
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: ma := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or not InIntArray(c, Ord(sa[1])));
False: ma := (((Result[x] - Result[(x - 1)]) <= f) or not InIntArray(c, Ord(sa[1])));
end;
False:
case ((r - 1) > x) of
True: ma := (((Result[(x + 1)] - Result[x]) <= f) or not InIntArray(c, Ord(sa[1])));
False: ma := not InIntArray(c, Ord(sa[1]));
end;
end;
False: ma := not InIntArray(c, Ord(sa[1]));
end;
False: ma := True;
end;
end;
end;
if not (mb and ma) then
begin
y := (r - 1);
for d := x to (y - 1) do
Result[d] := Result[(d + 1)];
SetLength(Result, y);
Dec(r);
end;
end;
end;
if (not a and (r > 0)) then
SetLength(Result, 1);
end else
SetLength(Result, 0);
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Without offset field.
[================================================== ============================}
function Find(text, findStr: string; methods: TMatchMethods): TIntegerArray;
begin
Result := FindEx(text, findStr, methods, 1);
end;

begin
ClearDebug;
WriteLn(ToStr(Find(TEXT, STR, [mmIgnoreCase, mmWholeWords, mmStrictWW])) + ' Find(TEXT, STR, [mmIgnoreCase, mmWholeWords, mmStrictWW])');
WriteLn(ToStr(Find(TEXT, STR, [mmIgnoreCase, mmWholeWords])) + ' Find(TEXT, STR, [mmIgnoreCase, mmWholeWords])');
WriteLn(ToStr(Find(TEXT, STR, [mmIgnoreCase])) + ' Find(TEXT, STR, [mmIgnoreCase])');
WriteLn(ToStr(Find(TEXT, STR, [])) + ' Find(TEXT, STR, [])');
WriteLn(ToStr(Find(TEXT, STR, [mmAll])) + ' Find(TEXT, STR, [mmAll])');
WriteLn(ToStr(Find(TEXT, STR, [mmAll, mmIgnoreCase])) + ' Find(TEXT, STR, [mmAll, mmIgnoreCase])');
WriteLn(ToStr(Find(TEXT, STR, [mmAll, mmIgnoreCase, mmWholeWords])) + ' Find(TEXT, STR, [mmAll, mmIgnoreCase, mmWholeWords])');
WriteLn(ToStr(Find(TEXT, STR, [mmAll, mmIgnoreCase, mmWholeWords, mmStrictWW])) + ' Find(TEXT, STR, [mmAll, mmIgnoreCase, mmWholeWords, mmStrictWW])');
end.

..it's a bit ugly/scary to be honest, but hay, that's mainly because I have been working on it all night today. So... :p I'll try and cut out some unneeded lines within time.

Right now, all the included methods, except "mmOverlap", are stable and working smoothly.
The logic of overlapping support still requires some work - it's not that bad really, I would say it is just fine for most uses.
Main issue of it being that right now it doesn't really pay attention to overlapped item's boundaries (start / end), like the function does without mmOverlap (sorry about the explanation, this part is hard for me to explain, ouch)

The reason why I am posting about this here, is because this particular function has potential to get rid of those false positives in your script, Officer Barbrady.. :)

-Jani

Thanks, I'm looking into it only looking for user and pas outside of declare players and also a couple other stuff to prevent script auto update false positives

Ian
05-26-2013, 03:26 AM
Thanks, I'm looking into it only looking for user and pas outside of declare players and also a couple other stuff to prevent script auto update false positives

I lol'd at the adult content finder :p

Maybe add the thing Kevin told us on Skype that takes the first x many lines of the script.

rj
05-26-2013, 03:34 AM
I lol'd at the adult content finder :p

Maybe add the thing Kevin told us on Skype that takes the first x many lines of the script.

Already did, it used addpostvar, not sure how I will be able to avoid false positives with shatters hams scripts though

Janilabo
05-26-2013, 03:49 AM
Already did, it used addpostvar, not sure how I will be able to avoid false positives with shatters hams scripts thoughOfficer, added in new CountString():


{$i SRL/SRL.simba}
Var
DsgnForm:TForm;
ScriptEdit:TMemo;
TitleLabel:TLabel;
ScanButton, UpdateButton:TButton;
Script_text:string;
HTTPThreats, WebThreats, BadCode, threats, Fishy:Integer;
pressed:boolean;
const
default = 'Times New Roman';

(*
Auther: BobboHobbo
*)
function FindTextC(word: string): boolean;
begin
Result := (Pos(lowercase(Word), LowerCase(Script_Text)) > 0);
end;
(*
Auther: BobboHobbo
*)
function FindTextMultiC(Text: TStringArray): boolean;
var
i, n: Integer;
begin
n := High(Text);
for i := 0 to n do
if (Pos(LowerCase(Text[i]), Script_Text) <> 0) then
begin
Result := True;
Exit;
end;
end;

{================================================= =============================]
Explanation: Important types for Find() function! Contains the string matching methods.
[================================================== ============================}
type
TMatchMethod = (mmAll, mmIgnoreCase, mmOverlap, mmWholeWords, mmStrictWW);
TMatchMethods = set of TMatchMethod;

{================================================= =============================]
Explanation: Returns a TIA that contains all the value from start value (aStart) to finishing value (aFinish)..
[================================================== ============================}
function TIAByRange(aStart, aFinish: Integer): TIntegerArray;
var
i, s, f: Integer;
begin
if (aStart <> aFinish) then
begin
s := Integer(aStart);
f := Integer(aFinish);
SetLength(Result, (IAbs(aStart - aFinish) + 1));
case (aStart > aFinish) of
True:
for i := s downto f do
Result[(s - i)] := i;
False:
for i := s to f do
Result[(i - s)] := i;
end;
end else
Result := [Integer(aStart)];
end;

{================================================= =============================]
Explanation: Merges T2DIntegerArray (ATIA) to TIntegerArray.
Example: [[1, 2], [3, 4]] => [1, 2, 3, 4]
[================================================== ============================}
function ATIAMerge(ATIA: T2DIntegerArray): TIntegerArray;
var
i, i2, h, h2, r: Integer;
begin
h := High(ATIA);
if (h > -1) then
begin
for i := 0 to h do
IncEx(r, (High(ATIA[i]) + 1));
SetLength(Result, r);
r := 0;
for i := 0 to h do
begin
h2 := High(ATIA[i]);
for i2 := 0 to h2 do
begin
Result[r] := Integer(ATIA[i][i2]);
Inc(r);
end;
end;
end else
SetLength(Result, 0);
end;

{================================================= =============================]
Explanation: Returns the string that is behind the position in data, size being the length for result that is copied from position.
[================================================== ============================}
function Behind(data: string; position, size: Integer): string;
var
l, r: Integer;
begin
l := Length(data);
case ((l > 0) and (position > 1) and (size > 0)) of
True:
begin
if ((position - size) < 1) then
size := ((position - size) + (size - 1));
if (position > (l + 1)) then
begin
r := ((position - l) - 1);
size := (size - r);
end;
Result := Copy(data, ((position - size) - r), size);
end;
False: Result := '';
end;
end;

{================================================= =============================]
Explanation: Returns the string that is ahead from position in data, size being the length for result that is copied from position.
[================================================== ============================}
function Ahead(data: string; position, size: Integer): string;
var
l: Integer;
begin
l := Length(data);
case ((l > 0) and (position <= l) and (size > 0)) of
True:
begin
if (position < 1) then
begin
size := (size - iAbs(position - 1));
position := 1;
end;
if ((size > 0) and ((position + size) > l)) then
size := (size - (((position + size) - l) - 1));
Result := Copy(data, position, size);
end;
False: Result := '';
end;
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Contains field for offset.
[================================================== ============================}
function FindEx(text, findStr: string; methods: TMatchMethods; offset: Integer): TIntegerArray;
var
sb, sa: string;
r, l, f, o, p, d, x, y: Integer;
re: TRegExp;
ma, mb, a, s, ol: Boolean;
c: TIntegerArray;
begin
l := Length(text);
f := Length(findStr);
if ((l > 0) and (f > 0) and (offset <= (l - f))) then
begin
if (offset < 1) then
offset := 1;
SetLength(Result, l);
re := TRegExp.Create;
re.InputString := text;
re.Expression := findStr;
if (mmIgnoreCase in methods) then
re.ModifierI := True;
a := (mmAll in methods);
case a of
False: re.ModifierG := True;
True: re.ModifierG := False;
end;
ol := (mmOverlap in methods);
if not ol then
o := (Length(findStr) - 1);
Inc(o);
p := Offset;
if re.ExecPos(p) then
repeat
if (re.Match[0] <> '') then
begin
Result[r] := re.MatchPos[0];
p := (Result[r] + o);
Inc(r);
end;
until not re.ExecPos(p);
re.Free;
SetLength(Result, r);
if ((r > 0) and (mmWholeWords in methods)) then
begin
s := (mmStrictWW in methods);
if not s then
c := ATIAMerge([TIAByRange(Ord('A'), Ord('Z')), TIAByRange(Ord('a'), Ord('z')), TIAByRange(Ord('0'), Ord('9'))]);
for x := (r - 1) downto 0 do
begin
sb := Behind(text, Result[x], 1);
sa := Ahead(text, (Result[x] + f), 1);
case s of
True:
begin
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: mb := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or ((sb = ' ') or (sb = '')));
False: mb := (((Result[x] - Result[(x - 1)]) <= f) or ((sb = ' ') or (sb = '')));
end;
False:
case ((r - 1) > x) of
True: mb := (((Result[(x + 1)] - Result[x]) <= f) or ((sb = ' ') or (sb = '')));
False: mb := ((sb = ' ') or (sb = ''));
end;
end;
False: mb := ((sb = ' ') or (sb = ''));
end;
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: ma := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or ((sa = ' ') or (sa = '')));
False: ma := (((Result[x] - Result[(x - 1)]) <= f) or ((sa = ' ') or (sa = '')));
end;
False:
case ((r - 1) > x) of
True: ma := (((Result[(x + 1)] - Result[x]) <= f) or ((sa = ' ') or (sa = '')));
False: ma := ((sa = ' ') or (sa = ''));
end;
end;
False: ma := ((sa = ' ') or (sa = ''));
end;
end;
False:
begin
case (sb <> '') of
True:
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: mb := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or not InIntArray(c, Ord(sb[1])));
False: mb := (((Result[x] - Result[(x - 1)]) <= f) or not InIntArray(c, Ord(sb[1])));
end;
False:
case ((r - 1) > x) of
True: mb := (((Result[(x + 1)] - Result[x]) <= f) or not InIntArray(c, Ord(sb[1])));
False: mb := not InIntArray(c, Ord(sb[1]));
end;
end;
False: mb := not InIntArray(c, Ord(sb[1]));
end;
False: mb := True;
end;
case (sa <> '') of
True:
case ol of
True:
case (x > 0) of
True:
case ((r - 1) > x) of
True: ma := ((((Result[(x + 1)] - Result[x]) <= f) or ((Result[x] - Result[(x - 1)]) <= f)) or not InIntArray(c, Ord(sa[1])));
False: ma := (((Result[x] - Result[(x - 1)]) <= f) or not InIntArray(c, Ord(sa[1])));
end;
False:
case ((r - 1) > x) of
True: ma := (((Result[(x + 1)] - Result[x]) <= f) or not InIntArray(c, Ord(sa[1])));
False: ma := not InIntArray(c, Ord(sa[1]));
end;
end;
False: ma := not InIntArray(c, Ord(sa[1]));
end;
False: ma := True;
end;
end;
end;
if not (mb and ma) then
begin
y := (r - 1);
for d := x to (y - 1) do
Result[d] := Result[(d + 1)];
SetLength(Result, y);
Dec(r);
end;
end;
end;
if (not a and (r > 0)) then
SetLength(Result, 1);
end else
SetLength(Result, 0);
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Without offset field.
[================================================== ============================}
function Find(text, findStr: string; methods: TMatchMethods): TIntegerArray;
begin
Result := FindEx(text, findStr, methods, 1);
end;

function CountString(s, str: string): Integer;
begin
Result := Length(Find(str, s, [mmAll, mmIgnoreCase, mmWholeWords]));
end;

(*
Auther: Officer Barbrady
*)
Procedure PrintReport;
Var
Points:Integer;
begin
Points := (HTTPthreats+WebThreats+BadCode+Fishy);
Writeln('==================Scan Results===================')
Writeln('HTTP threats:' + ToStr(HTTPThreats));
Writeln('Web threats:' + ToStr(WebThreats));
Writeln('Fishy code:' + ToStr(Fishy));
Writeln('Bad code:' + ToStr(BadCode));
Writeln('Overall threats:' + ToStr(Points))
case (threats) of
0: Writeln('Over Script Risk:None');
1..2: Writeln('Over Script Risk:Low');
3: Writeln('Over Script Risk:Meduim');
4..8: Writeln('Over Script Risk:High');
end;
Writeln('Thank you for using, always visit thread for updates')
end;
(*
Auther: Officer Barbrady
*)
Procedure FindBadCode;
begin
Writeln('=========Looking for bad code =========')
if FindTextC(lowercase('mmouse(x, y, 1, 1)')) or
FindTextC('mouse(x, y, 1, 1)')then
begin
Writeln('found "mmouse(x, y, 1, 1) " [Risk level: Meduim], potential ban.');
inc(BadCode);
threats := threats+1;
end;
if not FindTextC(lowercase('random')) then
begin
Writeln('found no randomness in script [Risk level: Meduim], potential ban.');
inc(BadCode)
threats := threats+1;
end;
Writeln('=======================================')
end;
(*
Auther: Officer Barbrady
*)
Procedure FindAbnormalCode;
begin
Writeln('=========Looking for Abnormal code =========')
if (CountString('user', script_text)>1) then
begin
Writeln('The variable "User" is used more then once, [risk level Meduim]')
Fishy := Fishy +1;
threats := threats+1;
end;
if (CountString('name', script_text)>1) then
begin
Writeln('The variable "Name" is used more then once, [risk level Meduim]')
Fishy := Fishy +1;
threats := threats+1;
end;
if (CountString('pass', script_text)>1) then
begin
Writeln('The variable "Pass" is used more then once, [risk level Meduim]')
Fishy := Fishy +1;
threats := threats+1;
end;
if (CountString('pin', script_text)>1) then
begin
Writeln('The variable "pin" is used more then once, [risk level Meduim]')
Fishy := Fishy +1;
threats := threats+1;
end;
Writeln('========================================= ==')
end;
(*
Auther: Officer Barbrady
*)

procedure FindHTTPThreats;
begin
Writeln('=========Looking for HTTP threats=========');
if FindTextC(lowercase('addpost')) then
begin
Writeln('found "addpost" [Risk level: HIGH]');
inc(HTTPThreats);
threats := threats + 4
end;
if FindTextC(lowercase('GetPage')) then
begin
Writeln('found "GetPage" [Risk level: HIGH]');
inc(HTTPThreats);
threats := threats + 4
end;
if FindTextC(lowercase('posthttppage')) then
begin
Writeln('found "posthttppage" [Risk level: HIGH]');
inc(HTTPThreats);
threats := threats + 4;
end;
if FindTextC(lowercase('posthttppageex')) then
begin
Writeln('found "posthttppageexe" [Risk level: HIGH]');
inc(HTTPThreats);
threats := threats + 4
end;
if FindTextC(lowercase('openwebpage')) then
begin
Writeln('Found attempt to open webpage [Risk level: Meduim]');
if FindTextMultiC(['meatspin', 'porn', 'xxx', '18', 'sunny']) then
begin
Writeln('Found adult content attempting to be opened via openpage [Risk level: Meduim-high]');
inc(WebThreats);
threats := threats + 3 exit;
end;
end;
end;
(*
Auther: Officer Barbrady
*)
Procedure Scan;
begin
wait(500);
FindHTTPThreats;
wait(1500);
FindAbnormalCode;
wait(1500);
FindBadCode;
wait(1500);
PrintReport;
end;
(*
Auther: Officer Barbrady
*)
procedure OpenThread(Sender: TObject);
begin
OpenWebPage('http://villavu.com/forum/showthread.php?t=103408');
end;
(*
Auther: Officer Barbrady
*)
procedure SaveFormInfo(Sender: TObject);
begin
DsgnForm.ModalResult := mrOk;
Script_text := ScriptEdit.TEXT;
pressed := true;
DsgnForm.CLOSE;
end;
(*
Auther: Officer Barbrady
*)
procedure InitForm;
begin
DsgnForm:=TForm.Create(nil);
with DsgnForm do
begin
Caption:='Simba script scanner';
Left:=377;
Top:=380;
Width:=750;
Height:=460;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=0;
end;
ScriptEdit := TMemo.Create(DsgnForm);
with ScriptEdit do
begin
Parent := DsgnForm;
Left := 120;
Top := 80;
Width := 481;
Height := 177;
Font.Name := default;
with ScriptEdit.Lines do Add('Paste script into this box, it will look for suspicious lines of code');
ScrollBars := ssBoth;
TabOrder := 0;
end;
TitleLabel:=TLabel.Create(DsgnForm);
with TitleLabel do
begin
Parent:=DsgnForm;
Caption:='Script scanner version 1.3';
Left:=225;
Top:=20;
Width:=43;
Height:=14;
Font.Name:=default;
Font.Color:=clDefault;
Font.Size:=17;
end;
ScanButton:=TButton.Create(DsgnForm);
with ScanButton do
begin
Parent:=DsgnForm;
Caption:='Scan';
Left:=175;
Top:=300;
Width:=150;
Height:=25;
Font.Size:=12;
OnClick:=@SaveFormInfo
end;
UpdateButton:=TButton.Create(DsgnForm);
with UpdateButton do
begin
Parent:=DsgnForm;
Caption:='Update';
Left:=400;
Top:=300;
Width:=150;
Height:=25;
Font.Size:=12;
OnClick:=@OpenThread
end;
end;
procedure SafeInitForm;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('InitForm', v);
end;


procedure ShowFormModal;
begin
DsgnForm.ShowModal;
end;


procedure SafeShowFormModal;
var
v: TVariantArray;
begin
SetArrayLength(V, 0);
ThreadSafeCall('ShowFormModal', v);
end;

begin
SafeInitForm;
SafeShowFormModal;
if (pressed=true) then Scan;
end.

Let me know if it works better than earlier? It should at least pick up a little less false positives, but we will see, of course... :)

-Jani

Kevin
05-26-2013, 04:01 AM
Already did, it used addpostvar, not sure how I will be able to avoid false positives with shatters hams scripts though

Mine didn't involve addpostvar at all. It used PostHTTPPage.
I have also since found far more danger in the command [unspecified - pm me and I'll discuss a way to add a search for it in your code without making it an obvious technique for someone to use.]. Like full computer access and loss of far more than just runescape info.

rj
05-26-2013, 01:52 PM
Mine didn't involve addpostvar at all. It used PostHTTPPage.
I have also since found far more danger in the command [unspecified - pm me and I'll discuss a way to add a search for it in your code without making it an obvious technique for someone to use.]. Like full computer access and loss of far more than just runescape info.
Sure - this project is kind of open source you guys may as anything you like, and yes I think it finds posthttp ill update when I get home Monday night

Double post - I am trying to get this into a extension so it can be accessed via simba menu

Peanuts
05-31-2013, 04:08 PM
Wow, this is really interesting.. You are a smart guy.

I'll try to use it and see if i ever get something pop up..

StickToTheScript
05-31-2013, 04:13 PM
Very interesting.... Its funny how much free time you have. You are coming out with scripts like nobodies business!

rj
06-01-2013, 12:51 AM
Very interesting.... Its funny how much free time you have. You are coming out with scripts like nobodies business!

Haha thanks, But must of the smart stuff is by the people i mentioned, won't be able to work on your for, this week since I won't be at a computer

Flight
06-01-2013, 01:56 AM
=========Looking for HTTP threats=========
Found attempt to open webpage [Risk level: Meduim]
Found adult content attempting to be opened via openpage [Risk level: Meduim-high]
=========Looking for Abnormal code =========
The variable "Name" is used more then once, [risk level Meduim]
The variable "Pass" is used more then once, [risk level Meduim]
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats:0
Web threats:1
Fishy code:2
Bad code:0
Overall threats:3
Over Script Risk:High
Thank you for using, always visit thread for updates
Successfully executed.


^ Scanned Monkfishies. Now I understand the "Web threats" of using my CheckDirectories procedure which checks if SRL-OSR is installed, if not it asks the user if they wish to open the installation page. But the "User" and "Pass" being used twice is the beginning of the script where the user may enter their SRLStats name & pass; later these are used to actually setup SRLStats thus these two strings are used exactly twice in the script. And I couldn't help from laughing when the report said it found adult content. :S I can only think of it recognizing "18" somewhere in there.

Neato utility though, just needs a few tweaks obviously. ;)

Ian
06-01-2013, 02:03 AM
=========Looking for HTTP threats=========
Found attempt to open webpage [Risk level: Meduim]
Found adult content attempting to be opened via openpage [Risk level: Meduim-high]
=========Looking for Abnormal code =========
The variable "Name" is used more then once, [risk level Meduim]
The variable "Pass" is used more then once, [risk level Meduim]
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats:0
Web threats:1
Fishy code:2
Bad code:0
Overall threats:3
Over Script Risk:High
Thank you for using, always visit thread for updates
Successfully executed.


^ Scanned Monkfishies. Now I understand the "Web threats" of using my CheckDirectories procedure which checks if SRL-OSR is installed, if not it asks the user if they wish to open the installation page. But the "User" and "Pass" being used twice is the beginning of the script where the user may enter their SRLStats name & pass; later these are used to actually setup SRLStats thus these two strings are used exactly twice in the script. And I couldn't help from laughing when the report said it found adult content. :S I can only think of it recognizing "18" somewhere in there.

Neato utility though, just needs a few tweaks obviously. ;)

Haha nice adult content you have there ;)

I'm going to scan one of mine, wonder how that's going to go...

Here's the scan of my booter:


Compiled successfully in 1466 ms.
=========Looking for HTTP threats=========
=========Looking for Abnormal code =========
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats:0
Web threats:0
Fishy code:0
Bad code:0
Overall threats:0
Over Script Risk:None
Thank you for using, always visit thread for updates
Successfully executed.


Also scanned the script scanner itself, results:


Compiled successfully in 1684 ms.
=========Looking for HTTP threats=========
found "addpost" [Risk level: HIGH]
found "GetPage" [Risk level: HIGH]
found "posthttppage" [Risk level: HIGH]
found "posthttppageexe" [Risk level: HIGH]
Found attempt to open webpage [Risk level: Meduim]
Found adult content attempting to be opened via openpage [Risk level: Meduim-high]
=========Looking for Abnormal code =========
The variable "pin" is used more then once, [risk level Meduim]
===========================================
=========Looking for bad code =========
found "mmouse(x, y, 1, 1) " [Risk level: Meduim], potential ban.
=======================================
==================Scan Results===================
HTTP threats:4
Web threats:1
Fishy code:1
Bad code:1
Overall threats:7
Thank you for using, always visit thread for updates
Successfully executed.

Chris!
06-01-2013, 02:19 AM
Haha nice adult content you have there ;)

I'm going to scan one of mine, wonder how that's going to go...

Here's the scan of my booter:


Compiled successfully in 1466 ms.
=========Looking for HTTP threats=========
=========Looking for Abnormal code =========
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats:0
Web threats:0
Fishy code:0
Bad code:0
Overall threats:0
Over Script Risk:None
Thank you for using, always visit thread for updates
Successfully executed.


Also scanned the script scanner itself, results:


Compiled successfully in 1684 ms.
=========Looking for HTTP threats=========
found "addpost" [Risk level: HIGH]
found "GetPage" [Risk level: HIGH]
found "posthttppage" [Risk level: HIGH]
found "posthttppageexe" [Risk level: HIGH]
Found attempt to open webpage [Risk level: Meduim]
Found adult content attempting to be opened via openpage [Risk level: Meduim-high]
=========Looking for Abnormal code =========
The variable "pin" is used more then once, [risk level Meduim]
===========================================
=========Looking for bad code =========
found "mmouse(x, y, 1, 1) " [Risk level: Meduim], potential ban.
=======================================
==================Scan Results===================
HTTP threats:4
Web threats:1
Fishy code:1
Bad code:1
Overall threats:7
Thank you for using, always visit thread for updates
Successfully executed.


Hmm, that script scanner seems to be unsafe! Hahaha, that's cool...

My results:

=========Looking for HTTP threats=========
found "GetPage" [Risk level: HIGH]
=========Looking for Abnormal code =========
The variable "User" is used more then once, [risk level Meduim]
The variable "Name" is used more then once, [risk level Meduim]
The variable "Pass" is used more then once, [risk level Meduim]
The variable "pin" is used more then once, [risk level Meduim]
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats:1
Web threats:0
Fishy code:4
Bad code:0
Overall threats:5
Over Script Risk:High
Thank you for using, always visit thread for updates

Damn you SRL Stats for making my script unsafe!

rj
06-01-2013, 02:20 AM
=========Looking for HTTP threats=========
Found attempt to open webpage [Risk level: Meduim]
Found adult content attempting to be opened via openpage [Risk level: Meduim-high]
=========Looking for Abnormal code =========
The variable "Name" is used more then once, [risk level Meduim]
The variable "Pass" is used more then once, [risk level Meduim]
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats:0
Web threats:1
Fishy code:2
Bad code:0
Overall threats:3
Over Script Risk:High
Thank you for using, always visit thread for updates
Successfully executed.


^ Scanned Monkfishies. Now I understand the "Web threats" of using my CheckDirectories procedure which checks if SRL-OSR is installed, if not it asks the user if they wish to open the installation page. But the "User" and "Pass" being used twice is the beginning of the script where the user may enter their SRLStats name & pass; later these are used to actually setup SRLStats thus these two strings are used exactly twice in the script. And I couldn't help from laughing when the report said it found adult content. :S I can only think of it recognizing "18" somewhere in there.

Neato utility though, just needs a few tweaks obviously. ;)

Yea, going to release massive overhaul next week, check the keywords for we page threat sits prob"sunny" that set it off, janibo has been helping me with a lot of string functions so big credits to him!

Ill be getting rid of the Grading system instead it will just print out things that could be unsafe

Ashaman88
06-02-2013, 01:00 PM
I always knew Flight was a Pw stealing kind of guy.... ;)

Seems nice I'm sure some will find it handy

Rotcrack
06-03-2013, 06:40 PM
THanks for this, lets me rest easy. I scan all scripts I download now! :D

Janilabo
06-04-2013, 12:15 PM
Hey Officer!

I got this script to pick up A LOT less false positives using some brave new tricks. :)
Also, FindEx() now detects overlapping strings correctly.

Attached "unofficial" version 1.31 - so, give it a try!

Of course there is still many ways how this script could be improved even more, but everything in time...

Sure hope you'll like how well this unofficial version works now!

BTW, that FindEx function is pretty badass now (well, compared to the last version!), here is a little example from String Handling Commands (http://villavu.com/forum/showthread.php?t=82205) topic (I named it as "Find" there):


const
TEXT = 'TestesTESTTestest test testest1 2testest test3 TEST Test Test.' + #13#10 + 'TEST!' + #13#10 + 'TeSt';
FIND_STR = 'test';

{================================================= =============================]
Explanation: Important types for Find() function! Contains the string matching methods.
[================================================== ============================}
type
TMatchMethod = (mmAll, mmIgnoreCase, mmOverlap, mmWholeWords, mmStrictWW);
TMatchMethods = set of TMatchMethod;

var
methods: array of TMatchMethods;

procedure SetupMethods;
begin
SetLength(methods, 6);
methods[0] := [];
methods[1] := [mmIgnoreCase];
methods[2] := [mmIgnoreCase, mmAll];
methods[3] := [mmIgnoreCase, mmAll, mmOverlap];
methods[4] := [mmIgnoreCase, mmAll, mmOverlap, mmWholeWords];
methods[5] := [mmIgnoreCase, mmAll, mmOverlap, mmWholeWords, mmStrictWW];
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Contains field for offset.
[================================================== ============================}
function Find(text, findStr: string; methods: TMatchMethods; offset: Integer): TIntegerArray;
var
sb, sa: string;
r, l, f, o, p, d, x, y, abL, abR, abX, abP, spA, spB, spH, spL, spI, spR, spD: Integer;
re: TRegExp;
ma, mb, a, s, ol: Boolean;
c: TIntegerArray;
t: T2DIntegerArray;
begin
l := Length(text);
f := Length(findStr);
if ((l > 0) and (f > 0) and (offset <= (l - f))) then
begin
if (offset < 1) then
offset := 1;
SetLength(Result, l);
re := TRegExp.Create;
re.InputString := text;
re.Expression := findStr;
if (mmIgnoreCase in methods) then
re.ModifierI := True;
a := (mmAll in methods);
case a of
False: re.ModifierG := True;
True: re.ModifierG := False;
end;
re.ModifierM := True;
ol := (mmOverlap in methods);
if not ol then
o := (Length(findStr) - 1);
Inc(o);
p := Offset;
if re.ExecPos(p) then
repeat
if (re.Match[0] <> '') then
begin
Result[r] := re.MatchPos[0];
p := (Result[r] + o);
Inc(r);
end;
until not re.ExecPos(p);
re.Free;
SetLength(Result, r);
if ((r > 0) and (mmWholeWords in methods)) then
begin
s := (mmStrictWW in methods);
if not s then
c := [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, // A-Z
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, // a-z
48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; // 0-9
case ol of
True:
begin
spH := High(Result);
if (spH > -1) then
begin
SetLength(t, (spH + 1));
t[0] := [Integer(Result[0])];
if (spH > 0) then
begin
spR := 1;
for spI := 1 to spH do
begin
for spA := 0 to (spR - 1) do
begin
spL := Length(t[spA]);
for spB := 0 to (spL - 1) do
begin
spD := IAbs(Result[spI] - t[spA][spB]);
if (spD <= f) then
begin
SetLength(t[spA], (spL + 1));
t[spA][spL] := Integer(Result[spI]);
Break;
end;
end;
if (spB < spL) then
Break;
end;
if (spA >= spR) then
begin
t[spR] := [Integer(Result[spI])];
Inc(spR);
end;
end;
end;
SetLength(t, spR);
spH := High(t);
for spI := spH downto 0 do
begin
spB := Low(t[spI]);
spA := High(t[spI]);
abX := 1;
abP := t[spI][spB];
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (t[spI][spA] + f);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = ' ') or (sb = '') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = ' ') or (sa = '') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
for spD := spI to (spH - 1) do
t[spD] := t[(spD + 1)];
SetLength(t, spH);
Dec(spH);
end;
end;
spH := High(t);
if (spH > -1) then
begin
for spI := 0 to spH do
IncEx(spR, (High(t[spI]) + 1));
SetLength(Result, spR);
spR := 0;
for spI := 0 to spH do
begin
spL := High(t[spI]);
for spA := 0 to spL do
begin
Result[spR] := Integer(t[spI][spA]);
Inc(spR);
end;
end;
SetLength(Result, spR);
end else
SetLength(Result, 0);
end else
r := 0;
end;
False:
begin
for x := (r - 1) downto 0 do
begin
abX := 1;
abP := Result[x];
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (Result[x] + f);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = ' ') or (sb = '') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = ' ') or (sa = '') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
y := (r - 1);
for d := x to (y - 1) do
Result[d] := Result[(d + 1)];
SetLength(Result, y);
Dec(r);
end;
end;
end;
end;
end;
if (not a and (r > 0)) then
SetLength(Result, 1);
end else
SetLength(Result, 0);
end;

var
h, i: Integer;

begin
ClearDebug;
SetupMethods;
h := High(methods);
for i := 0 to h do
WriteLn('Matching positions of FIND_STR found in TEXT using methods[' + IntToStr(i) + ']: ' + ToStr(Find(TEXT, FIND_STR, methods[i], 1)));
end.

Must say, I am very happy with the outcome.
..although, it is still not even nearly as good as the SCAR Divi version, but it does work pretty damn well anyways!

-Jani

rj
06-04-2013, 12:19 PM
Janilabo on vacation won't be able to update until Sunday

Janilabo
06-04-2013, 12:35 PM
Yeah don't worry buddy! Enjoy the holidays. ;)

Sidenote: I scanned that Flight's "Monkfishies" script using this unofficial version 1.31, the results are below..

V1.15_B:

=========Looking for HTTP threats=========
Found attempt to OpenWebpage [Risk level: MEDIUM]
=========Looking for Abnormal code =========
The variable "Pin" is used more then once [Risk level: MEDIUM]
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats: 0
Web threats: 1
Fishy code: 1
Bad code: 0
Overall threats: 2
Over Script Risk: High
Thank you for using, always visit thread for updates
Successfully executed.

V1.5:

=========Looking for HTTP threats=========
Found attempt to OpenWebpage [Risk level: MEDIUM]
=========Looking for Abnormal code =========
The variable "Pass" is used more then once [Risk level: MEDIUM]
The variable "Pin" is used more then once [Risk level: MEDIUM]
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats: 0
Web threats: 1
Fishy code: 2
Bad code: 0
Overall threats: 3
Over Script Risk: High
Thank you for using, always visit thread for updates
Successfully executed.

Looks like it's not at least picking up any "adult content attempts" anymore.. :D

EngageTheRage
06-04-2013, 12:57 PM
scanned my fighter with Janilabo's unofficial 1.31 and got this



=========Looking for HTTP threats=========
=========Looking for Abnormal code =========
The variable "Name" is used more then once [Risk level: MEDIUM]
The variable "Pass" is used more then once [Risk level: MEDIUM]
===========================================
=========Looking for bad code =========
=======================================
==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 2
Bad code: 0
Overall threats: 2
Over Script Risk: Low
Thank you for using, always visit thread for updates
Successfully executed.


looking nice guys :D

rj
06-04-2013, 01:03 PM
When I get back ill merge Jan's with my unreleased one at home that has a cleaner form and a couple more options

Flight
06-04-2013, 01:58 PM
Looks like it's not at least picking up any "adult content attempts" anymore.. :D

Yeah I removed the part in my script that opens up runescapexxx.com; people started complaining about the excessive pixel nudity and all ya know...

Kevin
06-04-2013, 02:43 PM
Yeah I removed the part in my script that opens up runescapexxx.com; people started complaining about the excessive pixel nudity and all ya know...

I see a tan colored pixel! That's obviously a nipple! or a finger... Either way, I'm offended!

Janilabo
06-06-2013, 09:07 AM
EDIT: Damn tag system, UGH! Added attachment to script and its available @pastebin (http://pastebin.com/raw.php?i=jArA7En6) aswell.

Officer Barbrady
I have been working for comment filtering, I got it working pretty smoothly. :)

With it we will be able to ignore false positives that are inside comments or strings (things that shouldn't be picked up)

Take a look at it guys.
Run it to see those effects, the results are printed to debug box (str before and after)..
NOTE: Those *13*10's (*=#) in str are new lines - just like scripts have em running "behind the scenes".

-Jani

Laimonas171
06-06-2013, 09:49 AM
typo: Over Script Risk:Meduim

I'm sure I have made sth like that few years ago with VB6 http://cool-smileys.com/images/skype-emoticon0138-thinking.gif

Janilabo
06-06-2013, 09:53 AM
typo: Over Script Risk:Meduim

I'm sure I have made sth like that few years ago with VB6 http://cool-smileys.com/images/skype-emoticon0138-thinking.gifCheck out this (http://villavu.com/forum/showthread.php?t=103408&page=2&p=1246116#post1246116) unofficial version, that OB will be merging soon together with hes official version, it has typos fixed aswell. :)
(Script is attached to that post, "v1.31")

As a sidenote, I added in a lot better example for that comment and/or string filtering script. It also supports now custom scripts, via ClipBoard data (this way you can see exactly what it filters out from the scripts)

Laimonas171
06-06-2013, 09:54 AM
Check out this (http://villavu.com/forum/showthread.php?t=103408&page=2&p=1246116#post1246116) unofficial version (that OB will be merging soon together with hes official version, it has typos fixed aswell. :)

As a sidenote, I added in a lot better example for that comment and/or string filtering script. It also supports now custom scripts, via ClipBoard data (this way you can see exactly what it filters out from the scripts)

very nice, man! :)

edit: ^Comma can make difference.

rj
06-06-2013, 12:49 PM
Check out this (http://villavu.com/forum/showthread.php?t=103408&page=2&p=1246116#post1246116) unofficial version, that OB will be merging soon together with hes official version, it has typos fixed aswell. :)
(Script is attached to that post, "v1.31")

As a sidenote, I added in a lot better example for that comment and/or string filtering script. It also supports now custom scripts, via ClipBoard data (this way you can see exactly what it filters out from the scripts)

Ill be getting home Sunday and will merge Monday

Janilabo
06-06-2013, 03:22 PM
Ill be getting home Sunday and will merge MondayAlright. ;)

I have got a surprise for you - I planted in the new comment and string filtering options!
These options, by this filtering feature, decreases the amount of false positives greatly.

EDIT2: 1.34... :D
EDIT: Added in "1.33", removed functions that weren't needed anymore (the new comment filtering feature made em useless)
Attached unofficial script version "1.32" to this post!
I think you might want to merge the new form features (and other things) to this version instead, because 1.31 had buggy comment filtering AND string filtering didn't even exist.

If you are worried about string filtering, you don't need to worry, because it doesn't filter out any variables, constants or types, only the stuff inside the string markers.

..and small example:

WriteLn('*STUFF INSIDE HERE WILL GET FILTERED*'*STUFF OUTSIDE HERE WONT*);

Also, I used the original script text for OpenWebPage() scan part - that means, it still catches those sneaky naughty adult content pages! ;)
Other parts are based on filtered script text.

You can obviously disable both of the filters when/if you want.

For example, scans for EngageTheRage's smexy Fighter v1.4 script:

WITHOUT comment filtering:

============Looking for HTTP threats=============
=================================================

============Looking for Abnormal code============
The variable "Name" is used more then once [Risk level: MEDIUM]
The variable "Pass" is used more then once [Risk level: MEDIUM]
=================================================

==============Looking for bad code===============
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 2
Bad code: 0
Overall threats: 2
Over Script Risk: Low
Thank you for using, always visit thread for updates
=================================================

..and then WITH comment filtering:


============Looking for HTTP threats=============
=================================================

============Looking for Abnormal code============
=================================================

==============Looking for bad code===============
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 0
Bad code: 0
Overall threats: 0
Over Script Risk: None
Thank you for using, always visit thread for updates
=================================================

Scan for Scanner itself below (comment and string filtering enabled)...


============Looking for HTTP threats=============
Found attempt to OpenWebpage [Risk level: MEDIUM]
=================================================

============Looking for Abnormal code============
The variable "Name" is used more then once [Risk level: MEDIUM]
=================================================

==============Looking for bad code===============
Found no randomness in script [Risk level: MEDIUM], potential ban.
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 1
Fishy code: 1
Bad code: 1
Overall threats: 3
Over Script Risk: High
Thank you for using, always visit thread for updates
=================================================

Regards,
-Jani

rj
06-06-2013, 05:01 PM
Alright. ;)

I have got a surprise for you - I planted in the new comment and string filtering options!
These options, by this filtering feature, decreases the amount of false positives greatly.

EDIT2: 1.34... :D
EDIT: Added in "1.33", removed functions that weren't needed anymore (the new comment filtering feature made em useless)
Attached unofficial script version "1.32" to this post!
I think you might want to merge the new form features (and other things) to this version instead, because 1.31 had buggy comment filtering AND string filtering didn't even exist.

If you are worried about string filtering, you don't need to worry, because it doesn't filter out any variables, constants or types, only the stuff inside the string markers.

..and small example:

WriteLn('*STUFF INSIDE HERE WILL GET FILTERED*'*STUFF OUTSIDE HERE WONT*);

Also, I used the original script text for OpenWebPage() scan part - that means, it still catches those sneaky naughty adult content pages! ;)
Other parts are based on filtered script text.

You can obviously disable both of the filters when/if you want.

For example, scans for EngageTheRage's smexy Fighter v1.4 script:

WITHOUT comment filtering:

============Looking for HTTP threats=============
=================================================

============Looking for Abnormal code============
The variable "Name" is used more then once [Risk level: MEDIUM]
The variable "Pass" is used more then once [Risk level: MEDIUM]
=================================================

==============Looking for bad code===============
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 2
Bad code: 0
Overall threats: 2
Over Script Risk: Low
Thank you for using, always visit thread for updates
=================================================

..and then WITH comment filtering:


============Looking for HTTP threats=============
=================================================

============Looking for Abnormal code============
=================================================

==============Looking for bad code===============
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 0
Bad code: 0
Overall threats: 0
Over Script Risk: None
Thank you for using, always visit thread for updates
=================================================

Scan for Scanner itself below (comment and string filtering enabled)...


============Looking for HTTP threats=============
Found attempt to OpenWebpage [Risk level: MEDIUM]
=================================================

============Looking for Abnormal code============
The variable "Name" is used more then once [Risk level: MEDIUM]
=================================================

==============Looking for bad code===============
Found no randomness in script [Risk level: MEDIUM], potential ban.
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 1
Fishy code: 1
Bad code: 1
Overall threats: 3
Over Script Risk: High
Thank you for using, always visit thread for updates
=================================================

Regards,
-Jani

On wow that's nice I wish I could view them lol

Janilabo
06-06-2013, 05:38 PM
On wow that's nice I wish I could view them lolIf you want to view the source codes of em online, then here is links to pastebin:

Version 1.31 (http://pastebin.com/raw.php?i=sXXN0UGq)

Version 1.32 (http://pastebin.com/raw.php?i=6dLjcaWz)

Version 1.33 (http://pastebin.com/raw.php?i=QKD9AmEF)

Version 1.34 (http://pastebin.com/raw.php?i=9eZDbEMi)

-Jani

rj
06-06-2013, 05:47 PM
I'm gong to try to add a little debug box and text on the form, but m not sure how to do that just yet

Janilabo
06-06-2013, 06:24 PM
I'm gong to try to add a little debug box and text on the form, but m not sure how to do that just yetTake a look at this awesome forms tutorial by Daniel (it's .PDF, so you might be able to read it with your mobile phone/tablet - at least I can read it with my Samsung Galaxy S [Android]): Simba Forms Tutorial (http://mayazcherquoi.com/Simba%20Forms%20Tutorial.pdf)

You may want to look at page 29 in it, where it contains information about TMemo's (multi-line textbox)!
..although, I recommend you'll read it fully through, at least if you are interested of GUI development now and in the future. :)

It's very nice source of information for GUI stuff.

I know you can't do any scripting for a few days, but sometimes even reading these things can help a lot - at least you'll learn some new tricks AND you might get some great ideas for what to do when you get back home.

P.S. When you get back home, you could try out this great utility by CynicRus: Form Designer for Simba (http://villavu.com/forum/showthread.php?t=86117) (this will be built-in to Simba v1.0!)
You may find it helpful aswell.

rj
06-06-2013, 06:29 PM
Take a look at this awesome forms tutorial by Daniel (it's .PDF, so you might be able to read it with your mobile phone/tablet - at least I can read it with my Samsung Galaxy S [Android]): Simba Forms Tutorial (http://mayazcherquoi.com/Simba%20Forms%20Tutorial.pdf)

You may want to look at page 29 in it, where it contains information about TMemo's (multi-line textbox)!
..although, I recommend you'll read it fully through, at least if you are interested of GUI development now and in the future. :)

It's very nice source of information for GUI stuff.

I know you can't do any scripting for a few days, but sometimes even reading these things can help a lot - at least you'll learn some new tricks AND you might get some great ideas for what to do when you get back home.

P.S. When you get back home, you could try out this great utility by CynicRus: Form Designer for Simba (http://villavu.com/forum/showthread.php?t=86117) (this will be built-in to Simba v1.0!)
You may find it helpful aswell.

Yea I use the form designer for a base then I compact it myself, I doubt this iPad can read PDFs (I know my crappy android reader the it was 2 years old with 150mv of rs, can) but ill try

Janilabo
06-06-2013, 06:42 PM
Yea I use the form designer for a base then I compact it myself, I doubt this iPad can read PDFs (I know my crappy android reader the it was 2 years old with 150mv of rs, can) but ill tryYou should be able to read PDF's with iPad.

Google search for "iPad + PDF" came up with...
Adobe Reader for mobile [iPhone/iPad & Android] (FREE): http://www.adobe.com/products/reader-mobile.html

rj
06-06-2013, 06:45 PM
You should be able to read PDF's with iPad.

Google search for "iPad + PDF" came up with...
Adobe Reader for mobile [iPhone/iPad & Android] (FREE): http://www.adobe.com/fi/products/reader-mobile.html

Yea it worked :p

I was looking at the ttimer part, and people told me I couldn't do this, but it looks like I could use a ttimer to execute a procedure every 1000 ms if I wanted it too, couldn't this be used as bootleg muiltithreading( I know it could be done with scar) for stuff like progress reports?

Janilabo
06-08-2013, 02:54 PM
Here you go, Officer Barbrady!

EDIT: Attached unofficial version 1.36, removed Find() from the script, because it's just like FindEx() without "regex: Boolean" variable part. So, those Find() parts are now based on FindEx() instead. This change doesn't have any effect on the way script works, just cuts out some unneeded lines.
Unofficial version 1.35 is now attached to this post. :) Script source code online: @pastebin (http://pastebin.com/raw.php?i=mcdPXv9A)

Changelog:

-Small logical fix for Find()
-Added in FindEx() for smarter (regex-based) string counting
-Once again, decreased the amount of false positives with several smart tweaks! Mostly with FindEx()

Scan for the script itself now:


=================Filtered Script=================
*SNIP*
=================================================

============Looking for HTTP threats=============
Found attempt to OpenWebpage [Risk level: MEDIUM]
=================================================

============Looking for Abnormal code============
=================================================

==============Looking for bad code===============
Found no randomness in script [Risk level: MEDIUM], potential ban.
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 1
Fishy code: 0
Bad code: 1
Overall threats: 2
Over Script Risk: High
Thank you for using, always visit thread for updates
=================================================

I'd say false positives are getting really close to minimal now. :)

rj
06-08-2013, 02:57 PM
Very nice, do you mind posting it here in Simba tags? When I view the attachment it overlaps :s

I might be able to merge it Sunday night

Rich
06-08-2013, 03:16 PM
Wow, this has seriously progressed in a matter of a few days. Got to say, nice job guys. This should definitely be brought to the attention of the guys who look at no section other than scripts.

Janilabo
06-08-2013, 03:21 PM
Very nice, do you mind posting it here in Simba tags? When I view the attachment it overlaps :s

I might be able to merge it Sunday nightSource code @pastebin: http://pastebin.com/raw.php?i=mcdPXv9A

EDIT: Attached unofficial version 1.36, removed Find() from the script, because it's just like FindEx() without "regex: Boolean" variable part. So, those Find() parts are now based on FindEx() instead. This change doesn't have any effect on the way script works, just cuts out some unneeded lines.
..and source for v1.36: http://pastebin.com/raw.php?i=81b5UDJN

By the way! With FindEx()-based counting I got this script to detect some sneaky password stealing attempts, good example below (something that none of the older versions could catch):

The stealing script example:

// {sc} = SNEAKY COMMENT!
// (*sc*) = SNEAKY COMMENT!

type // This is here for only this example.
TPlayer = record
Name, Pass, Nick: string;
end;

var
Players: array[0..0] of TPlayer;
un, pw: string;

procedure DeclarePlayers;
begin
Players[0].Name := 'StealMyGeepeesPlease!';
Players[0].Pass := 'MySimplePassword1234';
Players[0].Nick := 'eepees';
end;

begin
ClearDebug;
DeclarePlayers;
un := PLAYERS {sc} [ (*sc*) 0 {sc} ] (*sc*) .NAME {sc}; // It will catch this attempt.
pw := PlAyErs (*sc*) [ {sc} 0 {sc} ] {sc} . (*sc*) PaSs (*sc*); // It will catch this attempt.
WriteLn('USERNAME: "' + un + '"');
WriteLn('PASSWORD: "' + pw + '"');
end.

Scan results for that little example script:


=================Filtered Script=================
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@

type @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
TPlayer = record
Name, Pass, Nick: string;
end;

var
Players: array[0..0] of TPlayer;
un, pw: string;

procedure DeclarePlayers;
begin
Players[0].Name := %%%%%%%%%%%%%%%%%%%%%%%;
Players[0].Pass := %%%%%%%%%%%%%%%%%%%%%%;
Players[0].Nick := %%%%%%%%;
end;

begin
ClearDebug;
DeclarePlayers;
un := PLAYERS @@@@ [ @@@@@@ 0 @@@@ ] @@@@@@ .NAME @@@@; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
pw := PlAyErs @@@@@@ [ @@@@ 0 @@@@ ] @@@@ . @@@@@@ PaSs @@@@@@; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
WriteLn(%%%%%%%%%%%%% + un + %%%);
WriteLn(%%%%%%%%%%%%% + pw + %%%);
end.
=================================================

============Looking for HTTP threats=============
=================================================

============Looking for Abnormal code============
The variable "Name" is used more then once [Risk level: MEDIUM]
The variable "Pass" is used more then once [Risk level: MEDIUM]
=================================================

==============Looking for bad code===============
Found no randomness in script [Risk level: MEDIUM], potential ban.
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 2
Bad code: 1
Overall threats: 3
Over Script Risk: Medium
Thank you for using, always visit thread for updates
=================================================

Also, notice that the scan doesn't look for only NAME/PASS/PIN anymore, it actually requires that there are those "Players ." (*=ID) things attached to em. ;) That means, it wont pick up simple "Pass", "Name" or "Pin" words from script, ONLY if those words are attached to players variable[s] aswell.

It also ignores the comments and spaces, as you can see with the example I added there, so you really cant fool or cheat it with any sneaky attempts like that! :p
I tweaked those HTTP threat scans with similar ways, too.

rj
06-08-2013, 03:43 PM
Source code @pastebin: http://pastebin.com/raw.php?i=mcdPXv9A

EDIT: Attached unofficial version 1.36, removed Find() from the script, because it's just like FindEx() without "regex: Boolean" variable part. So, those Find() parts are now based on FindEx() instead. This change doesn't have any effect on the way script works, just cuts out some unneeded lines.
..and source for v1.36: http://pastebin.com/raw.php?i=81b5UDJN

By the way! With FindEx()-based counting I got this script to detect some sneaky password stealing attempts, good example below (something that none of the older versions could catch):

The stealing script example:

// {sc} = SNEAKY COMMENT!
// (*sc*) = SNEAKY COMMENT!

type // This is here for only this example.
TPlayer = record
Name, Pass, Nick: string;
end;

var
Players: array[0..0] of TPlayer;
un, pw: string;

procedure DeclarePlayers;
begin
Players[0].Name := 'StealMyGeepeesPlease!';
Players[0].Pass := 'MySimplePassword1234';
Players[0].Nick := 'eepees';
end;

begin
ClearDebug;
DeclarePlayers;
un := PLAYERS {sc} [ (*sc*) 0 {sc} ] (*sc*) .NAME {sc}; // It will catch this attempt.
pw := PlAyErs (*sc*) [ {sc} 0 {sc} ] {sc} . (*sc*) PaSs (*sc*); // It will catch this attempt.
WriteLn('USERNAME: "' + un + '"');
WriteLn('PASSWORD: "' + pw + '"');
end.

Scan results for that little example script:


=================Filtered Script=================
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@

type @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
TPlayer = record
Name, Pass, Nick: string;
end;

var
Players: array[0..0] of TPlayer;
un, pw: string;

procedure DeclarePlayers;
begin
Players[0].Name := %%%%%%%%%%%%%%%%%%%%%%%;
Players[0].Pass := %%%%%%%%%%%%%%%%%%%%%%;
Players[0].Nick := %%%%%%%%;
end;

begin
ClearDebug;
DeclarePlayers;
un := PLAYERS @@@@ [ @@@@@@ 0 @@@@ ] @@@@@@ .NAME @@@@;
pw := PlAyErs @@@@@@ [ @@@@ 0 @@@@ ] @@@@ . @@@@@@ PaSs @@@@@@;
WriteLn(%%%%%%%%%%%%% + un + %%%);
WriteLn(%%%%%%%%%%%%% + pw + %%%);
end.
=================================================

============Looking for HTTP threats=============
=================================================

============Looking for Abnormal code============
The variable "Name" is used more then once [Risk level: MEDIUM]
The variable "Pass" is used more then once [Risk level: MEDIUM]
=================================================

==============Looking for bad code===============
Found no randomness in script [Risk level: MEDIUM], potential ban.
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 2
Bad code: 1
Overall threats: 3
Over Script Risk: Medium
Thank you for using, always visit thread for updates
=================================================

Also, notice that the scan doesn't look for only NAME/PASS/PIN anymore, it actually requires that there are those "Players ." (*=ID) things attached to em. ;) That means, it wont pick up simple "Pass", "Name" or "Pin" words from script, ONLY if those words are attached to players variable[s] aswell.

It also ignores the comments and spaces, as you can see with the example I added there, so you really cant fool or cheat it with any sneaky attempts like that! :p
I tweaked those HTTP threat scans with similar ways, too.

Very nice, should I add option for it to save filtered script to a .txt file for review?

Janilabo
06-08-2013, 03:49 PM
Very nice, should I add option for it to save filtered script to a .txt file for review?If you want to mate. :p

Do note that, script sees all those STRING_FILTER's (%) and COMMENT_FILTER's (@) as " " (empty char), this is 1 way to detect spaced texts using regex matching.
Those filter characters I used only to display those parts it will pick up as comments/strings - mainly to see that it detects every comment and string correctly, which it indeed does.

But yeah, feel free to do just any changes you need/want to!

-Jani

Janilabo
06-09-2013, 10:15 AM
Bumping this topic up with a good reason: Version 1.40 is OUT!

Changelog:

-Fixed FindHTTPThreats (it detected threats only if there were 2 or more of certain HTTP-threat, whereas now it starts picking up from the very first one, just like it should be)
-Detects now players with ANY ID, even if someone tries to trick the system by using custom integer variable[s] (so it doesn't scan for digits only, like it used to)
-Detects attempts of using ToStr() with Players variable, this could be used for sending player data to variable (*=any ID)
Improved the detection a lot. :)

Small example below, about password stealing attempt using sneaky tricks, that this script WILL pick up:

// {sc} = SNEAKY COMMENT!
// (*sc*) = SNEAKY COMMENT!

type // This is here for only this example.
TPlayer = record
Name, Pass, Nick, Pin: string;
end;

var
ID: Integer;
Players: array[0..0] of TPlayer;
pn, un, pw: string;

procedure DeclarePlayers;
begin
Players[0].Name := 'StealMyGeepeesPlease!';
Players[0].Pass := 'MySimplePassword1234';
Players[0].Nick := 'eepees';
Players[0].Pin := '1234';
end;

begin
ClearDebug;
DeclarePlayers;
un := PLAYERS {sc} [ (*sc*) 0 {sc} ] (*sc*) .NAME {sc}; // It will catch this attempt.
pw := PlAyErs (*sc*) [ {sc} StrToInt(#48) {sc} ] {sc} . (*sc*) PaSs (*sc*); // It will catch this attempt.
ID := 0;
pn := players[ID].Pin;
WriteLn('USERNAME: "' + un + '"');
WriteLn('PASSWORD: "' + pw + '"');
WriteLn('PIN: "' + pn + '"');
WriteLn(ToStr(Players[0]));
end.

..and scan results:


=================Filtered Script=================
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@

type @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
TPlayer = record
Name, Pass, Nick, Pin: string;
end;

var
ID: Integer;
Players: array[0..0] of TPlayer;
pn, un, pw: string;

procedure DeclarePlayers;
begin
Players[0].Name := %%%%%%%%%%%%%%%%%%%%%%%;
Players[0].Pass := %%%%%%%%%%%%%%%%%%%%%%;
Players[0].Nick := %%%%%%%%;
Players[0].Pin := %%%%%%;
end;

begin
ClearDebug;
DeclarePlayers;
un := PLAYERS @@@@ [ @@@@@@ 0 @@@@ ] @@@@@@ .NAME @@@@; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
pw := PlAyErs @@@@@@ [ @@@@ StrToInt(#48) @@@@ ] @@@@ . @@@@@@ PaSs @@@@@@; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ID := 0;
pn := players[ID].Pin;
WriteLn(%%%%%%%%%%%%% + un + %%%);
WriteLn(%%%%%%%%%%%%% + pw + %%%);
WriteLn(%%%%%%%% + pn + %%%);
WriteLn(ToStr(Players[0]));
end.
=================================================

============Looking for HTTP threats=============
=================================================

============Looking for Abnormal code============
The variable "Name" is used more then once [Risk level: MEDIUM]
The variable "Pass" is used more then once [Risk level: MEDIUM]
The variable "Pin" is used more then once [Risk level: MEDIUM]
Player data sent to ToStr() [Risk level: MEDIUM]
=================================================

==============Looking for bad code===============
Found no randomness in script [Risk level: MEDIUM], potential ban.
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 4
Bad code: 1
Overall threats: 5
Over Script Risk: High
Thank you for using, always visit thread for updates
=================================================

rj
06-09-2013, 01:47 PM
Bumping this topic up with a good reason: Version 1.40 is OUT!

Changelog:

-Fixed FindHTTPThreats (it detected threats only if there were 2 or more of certain HTTP-threat, whereas now it starts picking up from the very first one, just like it should be)
-Detects now players with ANY ID, even if someone tries to trick the system by using custom integer variable[s] (so it doesn't scan for digits only, like it used to)
-Detects attempts of using ToStr() with Players variable, this could be used for sending player data to variable (*=any ID)
Improved the detection a lot. :)

Small example below, about password stealing attempt using sneaky tricks, that this script WILL pick up:

// {sc} = SNEAKY COMMENT!
// (*sc*) = SNEAKY COMMENT!

type // This is here for only this example.
TPlayer = record
Name, Pass, Nick, Pin: string;
end;

var
ID: Integer;
Players: array[0..0] of TPlayer;
pn, un, pw: string;

procedure DeclarePlayers;
begin
Players[0].Name := 'StealMyGeepeesPlease!';
Players[0].Pass := 'MySimplePassword1234';
Players[0].Nick := 'eepees';
Players[0].Pin := '1234';
end;

begin
ClearDebug;
DeclarePlayers;
un := PLAYERS {sc} [ (*sc*) 0 {sc} ] (*sc*) .NAME {sc}; // It will catch this attempt.
pw := PlAyErs (*sc*) [ {sc} StrToInt(#48) {sc} ] {sc} . (*sc*) PaSs (*sc*); // It will catch this attempt.
ID := 0;
pn := players[ID].Pin;
WriteLn('USERNAME: "' + un + '"');
WriteLn('PASSWORD: "' + pw + '"');
WriteLn('PIN: "' + pn + '"');
WriteLn(ToStr(Players[0]));
end.

..and scan results:


=================Filtered Script=================
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@

type @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
TPlayer = record
Name, Pass, Nick, Pin: string;
end;

var
ID: Integer;
Players: array[0..0] of TPlayer;
pn, un, pw: string;

procedure DeclarePlayers;
begin
Players[0].Name := %%%%%%%%%%%%%%%%%%%%%%%;
Players[0].Pass := %%%%%%%%%%%%%%%%%%%%%%;
Players[0].Nick := %%%%%%%%;
Players[0].Pin := %%%%%%;
end;

begin
ClearDebug;
DeclarePlayers;
un := PLAYERS @@@@ [ @@@@@@ 0 @@@@ ] @@@@@@ .NAME @@@@; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
pw := PlAyErs @@@@@@ [ @@@@ StrToInt(#48) @@@@ ] @@@@ . @@@@@@ PaSs @@@@@@; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ID := 0;
pn := players[ID].Pin;
WriteLn(%%%%%%%%%%%%% + un + %%%);
WriteLn(%%%%%%%%%%%%% + pw + %%%);
WriteLn(%%%%%%%% + pn + %%%);
WriteLn(ToStr(Players[0]));
end.
=================================================

============Looking for HTTP threats=============
=================================================

============Looking for Abnormal code============
The variable "Name" is used more then once [Risk level: MEDIUM]
The variable "Pass" is used more then once [Risk level: MEDIUM]
The variable "Pin" is used more then once [Risk level: MEDIUM]
Player data sent to ToStr() [Risk level: MEDIUM]
=================================================

==============Looking for bad code===============
Found no randomness in script [Risk level: MEDIUM], potential ban.
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 0
Fishy code: 4
Bad code: 1
Overall threats: 5
Over Script Risk: High
Thank you for using, always visit thread for updates
=================================================

I think I'll be ale to merge this in about 12 hours!

Janilabo
06-09-2013, 02:37 PM
I think I'll be ale to merge this in about 12 hours!That's grrrreat, OB!
Can't wait to see those GUI improvements/tweaks you have been talking about.. :p

By the way, I am still going... Here is v1.41:

{================================================= ======================================]
| |
| _____ _ _ _____ _ _ _____ |
| | __|_|_____| |_ ___ | __|___ ___|_|___| |_ | __|___ ___ ___ ___ ___ ___ |
| |__ | | | . | .'| |__ | _| _| | . | _| |__ | _| .'| | | -_| _| |
| |_____|_|_|_|_|___|__,| |_____|___|_| |_| _|_| |_____|___|__,|_|_|_|_|___|_| |
| |_| |
| |
[================================================== =====================================}

{$i SRL/SRL.simba}

const
VERSION = '1.41'; // Don't touch... Script version.
FILTER_COMMENTS = True; // Doesn't pay attention to stuff inside comments
// Recommended to keep this feature enabled, a lot less false positives!
COMMENT_FILTER = '@'; // CHAR, NOT STRING! Used in debug box for displaying the filtered comments (doesn't effect scan, as these will be empty chars in filteredScriptText for scan).
FILTER_STRINGS = True; // Doesn't pay attention to stuff INSIDE string signs.
// So, this feature still detects stuff that falls outside those '' signs! :)
STRING_FILTER = '%'; // CHAR, NOT STRING! Used in debug box for displaying the filtered strings (doesn't effect scan, these will be empty chars in filteredScriptText for scan).
DEBUG_FILTERED_SCRIPT = True; // Debug the script, that was filtered (used for most script parts), before scan statistics (displays empty chars with COMMENT_FILTER & STRING_FILTER).
DEFAULT = 'Times New Roman';

type
TMatchMethod = (mmAll, mmIgnoreCase, mmOverlap, mmWholeWords, mmStrictWW);
TMatchMethods = set of TMatchMethod;
TRegexMatch = record
position, size: Integer;
text: string;
end;
TRegexMatchArray = array of TRegexMatch;
T2DRegexMatchArray = array of TRegexMatchArray;
TRange = record
minimum, maximum: Integer;
end;
TRangeArray = array of TRange;

var
DsgnForm: TForm;
ScriptEdit: TMemo;
TitleLabel: TLabel;
ScanButton, UpdateButton: TButton;
originalScriptText, filteredScriptText, displayScriptText: string;
HTTPThreats, WebThreats, BadCode, threats, Fishy: Integer;
pressed: Boolean;

(*
Auther: Officer Barbrady
*)
procedure PrintReport;
var
Points:Integer;
begin
Points := (HTTPthreats + WebThreats + BadCode + Fishy);
WriteLn('');
WriteLn('==================Scan Results===================');
WriteLn('HTTP threats: ' + ToStr(HTTPThreats));
WriteLn('Web threats: ' + ToStr(WebThreats));
WriteLn('Fishy code: ' + ToStr(Fishy));
WriteLn('Bad code: ' + ToStr(BadCode));
WriteLn('Overall threats: ' + ToStr(Points))
case threats of
0: WriteLn('Over Script Risk: None');
1..2: WriteLn('Over Script Risk: Low');
3: WriteLn('Over Script Risk: Medium');
4..8: WriteLn('Over Script Risk: High');
end;
WriteLn('Thank you for using, always visit thread for updates');
WriteLn('========================================= ========');
end;

{================================================= =============================]
Explanation: Finds position from s items in str. Stores the ID of the found s item to index variable.
The importance order for d items is from left to right (=>).
So place the important ones first and then less important after those.
Contains field for offset.
[================================================== ============================}
function PosMultiIDEx(s: TStringArray; str: string; var index: Integer; offset: Integer): Integer;
var
h, i, p, t: Integer;
begin
if (offset < 1) then
offset := 1;
Result := -1;
index := -1;
h := High(s);
if ((h > -1) and (str <> '')) then
begin
t := (Length(str) + 1);
Result := t;
for i := 0 to h do
begin
p := PosEx(s[i], str, offset);
if ((p > 0) and (p < Result)) then
begin
Result := p;
index := i;
end;
end;
if (Result = t) then
Result := 0;
end;
end;

function ToRange(minimum, maximum: Integer): TRange;
begin
Result.minimum := Integer(minimum);
Result.maximum := Integer(maximum);
end;

procedure TRAAppend(var TRA: TRangeArray; x: TRange);
var
aL: Integer;
begin
aL := (Length(TRA) + 1);
SetLength(TRA, aL);
TRA[(aL - 1)] := TRange(x);
end;

function TrackCaS(str: string; var comments, strings: TRangeArray): Boolean;
var
s, i, o, e, x, l, a, ls: Integer;
t: TStringArray;
begin
Result := False;
SetLength(comments, 0);
SetLength(strings, 0);
l := Length(str);
ls := -1;
if (l > 0) then
begin
o := 1;
t := ['//', '(*', '{', ''''];
repeat
s := PosMultiIDEx(t, str, i, o);
case (s <= ls) of
True: Exit;
False: ls := s;
end;
if (s > 0) then
begin
o := (s + 1);
a := 0;
case i of
0, 1, 2:
begin
case i of
0:
begin
e := PosMultiIDEx([#13#10, #13, #10], str, x, o);
if (x = 0) then
a := 1;
if (e = 0) then
e := l;
TRAAppend(comments, ToRange(s, e));
end;
1, 2:
begin
case i of
1:
begin
e := PosEx('*)', str, o);
a := 1;
end;
2: e := PosEx('}', str, o);
end;
if (e = 0) then
e := l;
TRAAppend(comments, ToRange(s, (e + a)));
end;
end;
end;
3:
begin
e := PosMultiIDEx([#13#10, #13, #10, ''''], str, x, o);
if (x = 0) then
a := 1;
case (e = 0) of
True:
begin
e := l;
TRAAppend(strings, ToRange(s, e));
end;
False:
case x of
0, 1, 2: TRAAppend(strings, ToRange(s, e));
3: TRAAppend(strings, ToRange(s, (e + a)));
end;
end;
end;
end;
o := ((e + 1) + a);
end;
until ((s = 0) or (x = -1) or (o > l));
end;
end;

{================================================= =============================]
Explanation: Returns all the positions by items from s array in str. Place s items in importance order (=>)
If overlap is set to true, strings can overlap.
(['aa'], 'baaaah', False) => [2,3,4]
(['aa'], 'baaaah', True) => [2,4]
[================================================== ============================}
function PosAllMulti(s: TStringArray; str: string; overlap: Boolean): TIntegerArray;
var
h, l, p, o, x, i, t, r, y, d: Integer;
begin
h := High(s);
y := Length(str);
if ((y > 0) and (h > -1)) then
begin
SetLength(Result, y);
o := 1;
repeat
p := 0;
for x := 0 to h do
begin
t := PosEx(s[x], str, (l + o));
case (t < 1) of
True:
begin
for d := x to (h - 1) do
s[d] := s[(d + 1)];
SetLength(s, h);
Dec(x);
Dec(h);
end;
False:
if ((p = 0) or (t < p)) then
begin
p := t;
i := x;
end;
end;
end;
if (p > 0) then
begin
Result[r] := p;
Inc(r);
l := p;
if not overlap then
o := Length(s[i]);
end;
until (p <= 0);
end;
SetLength(Result, r);
end;

procedure FillStrRangeEx(var str: string; fillWith: Char; range: TRange; exceptions: TIntegerArray);
var
i, l, c: Integer;
begin
l := Length(str);
if ((l > 0) and not (range.minimum > range.maximum)) then
begin
if (range.minimum < 1) then
range.minimum := 1;
if (range.maximum > l) then
range.maximum := l;
if (range.minimum > l) then
Exit;
c := iAbs(range.maximum - range.minimum);
for i := range.minimum to range.maximum do
if not InIntArray(exceptions, i) then
str[i] := fillWith;
end;
end;

{================================================= =============================]
Explanation: Function for tracing findStr's from data. Stores matched items and positions to 'items' and 'positions' variables.
Contains also custom fields for regexTags and regexStrs;
each tag performs a regex action, that is set to regexStrs, during the search.
If cs variable is set as true, then the search will be case-sensitive.
[================================================== ============================}
function TraceStrsEx(findStr: string; regexTags: array of Char; regexStrs: TStringArray; data: string; cs: Boolean; var items: TStringArray; var positions: TIntegerArray): Boolean;
var
re: TRegExp;
p, l, r, s, c, h, t: Integer;
q: string;
begin
l := Length(data);
s := Length(findStr);
if ((l > 0) and (s > 0)) then
begin
h := High(regexTags);
if (High(regexStrs) < h) then
SetLength(regexStrs, (h + 1));
SetLength(items, l);
SetLength(positions, l);
q := '.\+*?[^]$(){}=!<>|:-';
for c := h downto 0 do
begin
t := Pos(q, regexTags[c]);
if (t > 0) then
Delete(q, t, 1);
end;
for c := s downto 1 do
if (Pos(findStr[c], q) > 0) then
Insert('\', findStr, c);
for t := 0 to h do
findStr := ReplaceWrap(findStr, regexTags[t], regexStrs[t], [rfReplaceAll]);
re := TRegExp.Create;
re.ModifierI := not cs;
re.ModifierG := False;
re.Expression := findStr;
re.InputString := data;
p := 1;
if re.ExecPos(p) then
repeat
if (re.Match[0] <> '') then
begin
p := (re.MatchPos[0] + 1);
positions[r] := re.MatchPos[0];
items[r] := Copy(data, re.MatchPos[0], re.MatchLen[0]);
Inc(r);
end;
until not re.ExecPos(p);
re.Free;
end else
Result := False;
Result := (r > 0);
SetLength(positions, r);
SetLength(items, r);
end;

{================================================= =============================]
Explanation: Function for tracing findStr's from data.
Contains also custom fields for regexTag and regexStr;
tag performs a regex action, that is set to regexStr, during the search.
If cs variable is set as true, then the search will be case-sensitive.
[================================================== ============================}
function TraceStrPositions(findStr: string; regexTag: Char; regexStr, data: string; cs: Boolean): TIntegerArray;
var
tmp: TStringArray;
begin
TraceStrsEx(findStr, [regexTag], [regexStr], data, cs, tmp, Result);
SetLength(tmp, 0);
end;

{================================================= =============================]
Explanation: Function for tracing findStr's from data.
Contains also custom fields for regexTag and regexStr;
tag performs a regex action, that is set to regexStr, during the search.
If cs variable is set as true, then the search will be case-sensitive.
[================================================== ============================}
function TraceStrItems(findStr: string; regexTag: Char; regexStr, data: string; cs: Boolean): TStringArray;
var
tmp: TIntegerArray;
begin
TraceStrsEx(findStr, [regexTag], [regexStr], data, cs, Result, tmp);
SetLength(tmp, 0);
end;

function SpacedTextCount(findStr: string; spaceTag: Char; data: string): Integer;
begin
Result := Length(TraceStrPositions(findStr, spaceTag, '(\s)*', data, False));
end;

function DetectSpacedText(findStr: string; spaceTag: Char; data: string): Boolean;
begin
Result := (SpacedTextCount(findStr, spaceTag, data) > 0);
end;

function FilterScriptData(data: string): string;
var
h, i, l: Integer;
newLines: TIntegerArray;
comments, strings: TRangeArray;
begin
Result := string(data);
displayScriptText := string(Result);
l := Length(Result);
if ((Result <> '') and (FILTER_STRINGS or FILTER_COMMENTS)) then
begin
newLines := PosAllMulti([#13, #10], Result, False);
TrackCaS(data, comments, strings);
h := High(comments);
if FILTER_COMMENTS then
for i := 0 to h do
begin
FillStrRangeEx(Result, ' ', comments[i], newLines);
FillStrRangeEx(displayScriptText, COMMENT_FILTER, comments[i], newLines);
end;
h := High(strings);
if FILTER_COMMENTS then
for i := 0 to h do
begin
FillStrRangeEx(Result, ' ', strings[i], newLines);
FillStrRangeEx(displayScriptText, STRING_FILTER, strings[i], newLines);
end;
end;
SetLength(newLines, 0);
SetLength(comments, 0);
SetLength(strings, 0);
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Contains field for offset.
If regex field is set as true, then this function searches for the regex you use.
[================================================== ============================}
function FindEx(text, findStr: string; methods: TMatchMethods; offset: Integer; regex: Boolean): TIntegerArray;
var
rmArr: TRegexMatchArray;
rmArr2D: T2DRegexMatchArray;
sb, sa: string;
r, i, l, f, p, d, o, x, y, abL, abR, abX, abP, spA, spB, spH, spL, spI, spR, spD: Integer;
re: TRegExp;
ma, mb, a, s, ol: Boolean;
c: TIntegerArray;
t: T2DIntegerArray;
begin
l := Length(text);
f := Length(findStr);
if ((l > 0) and (f > 0) and (offset <= (l - f))) then
begin
if (offset < 1) then
offset := 1;
if not regex then
begin
for i := f downto 1 do
if (Pos(findStr[i], '.\+*?[^]$(){}=!<>|:-') > 0) then
Insert('\', findStr, i);
SetLength(Result, l);
re := TRegExp.Create;
re.InputString := text;
re.Expression := findStr;
if (mmIgnoreCase in methods) then
re.ModifierI := True;
a := (mmAll in methods);
case a of
False: re.ModifierG := True;
True: re.ModifierG := False;
end;
re.ModifierM := True;
ol := (mmOverlap in methods);
if not ol then
o := (Length(findStr) - 1);
Inc(o);
p := offset;
while re.ExecPos(p) do
begin
Result[r] := re.MatchPos[0];
p := (Result[r] + o);
Inc(r);
end;
p := Offset;
re.Free;
SetLength(Result, r);
if ((r > 0) and (mmWholeWords in methods)) then
begin
s := (mmStrictWW in methods);
if not s then
c := [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, // A-Z
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, // a-z
48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; // 0-9
case ol of
True:
begin
spH := High(Result);
if (spH > -1) then
begin
SetLength(t, (spH + 1));
t[0] := [Integer(Result[0])];
if (spH > 0) then
begin
spR := 1;
for spI := 1 to spH do
begin
for spA := 0 to (spR - 1) do
begin
spL := Length(t[spA]);
for spB := 0 to (spL - 1) do
begin
spD := IAbs(Result[spI] - t[spA][spB]);
if (spD <= f) then
begin
SetLength(t[spA], (spL + 1));
t[spA][spL] := Integer(Result[spI]);
Break;
end;
end;
if (spB < spL) then
Break;
end;
if (spA >= spR) then
begin
t[spR] := [Integer(Result[spI])];
Inc(spR);
end;
end;
end;
SetLength(t, spR);
spH := High(t);
for spI := spH downto 0 do
begin
spB := Low(t[spI]);
spA := High(t[spI]);
abX := 1;
abP := t[spI][spB];
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (t[spI][spA] + f);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = '') or (sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = '') or (sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
for spD := spI to (spH - 1) do
t[spD] := t[(spD + 1)];
SetLength(t, spH);
Dec(spH);
end;
end;
spH := High(t);
if (spH > -1) then
begin
for spI := 0 to spH do
IncEx(spR, (High(t[spI]) + 1));
SetLength(Result, spR);
spR := 0;
for spI := 0 to spH do
begin
spL := High(t[spI]);
for spA := 0 to spL do
begin
Result[spR] := Integer(t[spI][spA]);
Inc(spR);
end;
end;
SetLength(Result, spR);
end else
SetLength(Result, 0);
end else
r := 0;
end;
False:
begin
for x := (r - 1) downto 0 do
begin
abX := 1;
abP := Result[x];
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (Result[x] + f);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = '') or (sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = '') or (sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
y := (r - 1);
for d := x to (y - 1) do
Result[d] := Result[(d + 1)];
SetLength(Result, y);
Dec(r);
end;
end;
end;
end;
end;
if (not a and (r > 0)) then
SetLength(Result, 1);
end else
begin
SetLength(rmArr, l);
re := TRegExp.Create;
re.InputString := text;
re.Expression := findStr;
if (mmIgnoreCase in methods) then
re.ModifierI := True;
a := (mmAll in methods);
case a of
False: re.ModifierG := True;
True: re.ModifierG := False;
end;
re.ModifierM := True;
ol := (mmOverlap in methods);
p := offset;
while re.ExecPos(p) do
begin
rmArr[r].position := re.MatchPos[0];
rmArr[r].text := re.Match[0];
rmArr[r].size := re.MatchLen[0];
if ol then
p := (rmArr[r].position + 1)
else
p := (rmArr[r].position + rmArr[r].size);
Inc(r);
end;
p := Offset;
re.Free;
SetLength(rmArr, r);
if ((r > 0) and (mmWholeWords in methods)) then
begin
s := (mmStrictWW in methods);
if not s then
c := [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, // A-Z
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, // a-z
48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; // 0-9
case ol of
True:
begin
spH := High(rmArr);
if (spH > -1) then
begin
SetLength(rmArr2D, (spH + 1));
rmArr2D[0] := [TRegexMatch(rmArr[0])];
if (spH > 0) then
begin
spR := 1;
for spI := 1 to spH do
begin
for spA := 0 to (spR - 1) do
begin
spL := Length(rmArr2D[spA]);
for spB := 0 to (spL - 1) do
begin
spD := IAbs(rmArr[spI].position - rmArr2D[spA][spB].position);
if (spD <= rmArr2D[spA][spB].size) then
begin
SetLength(rmArr2D[spA], (spL + 1));
rmArr2D[spA][spL] := TRegexMatch(rmArr[spI]);
Break;
end;
end;
if (spB < spL) then
Break;
end;
if (spA >= spR) then
begin
rmArr2D[spR] := [TRegexMatch(rmArr[spI])];
Inc(spR);
end;
end;
end;
SetLength(rmArr2D, spR);
spH := High(rmArr2D);
for spI := spH downto 0 do
begin
spB := Low(rmArr2D[spI]);
spA := High(rmArr2D[spI]);
abX := 1;
abP := rmArr2D[spI][spB].position;
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (rmArr2D[spI][spA].position + rmArr2D[spI][spA].size);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = '') or (sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = '') or (sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
for spD := spI to (spH - 1) do
rmArr2D[spD] := rmArr2D[(spD + 1)];
SetLength(rmArr2D, spH);
Dec(spH);
end;
end;
spH := High(rmArr2D);
if (spH > -1) then
begin
for spI := 0 to spH do
IncEx(spR, (High(rmArr2D[spI]) + 1));
SetLength(rmArr, spR);
spR := 0;
for spI := 0 to spH do
begin
spL := High(rmArr2D[spI]);
for spA := 0 to spL do
begin
rmArr[spR] := TRegexMatch(rmArr2D[spI][spA]);
Inc(spR);
end;
end;
SetLength(rmArr, spR);
r := spR;
end else
SetLength(rmArr, 0);
end else
r := 0;
end;
False:
begin
for x := (r - 1) downto 0 do
begin
abX := 1;
abP := rmArr[x].position;
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (rmArr[x].position + rmArr[x].size);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = '') or (sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = '') or (sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
y := (r - 1);
for d := x to (y - 1) do
rmArr[d] := rmArr[(d + 1)];
SetLength(rmArr, y);
Dec(r);
end;
end;
end;
end;
end;
case (r > 0) of
True:
begin
if not a then
r := 1;
SetLength(Result, r);
for i := 0 to (r - 1) do
Result[i] := rmArr[i].position;
end;
False: SetLength(Result, 0);
end;
end;
end else
SetLength(Result, 0);
end;

function CountString(s, str: string): Integer;
begin
Result := Length(FindEx(str, s, [mmAll, mmIgnoreCase, mmWholeWords], 1, False));
end;

function CountStringEx(s, str: string; regex: Boolean): Integer;
begin
Result := Length(FindEx(str, s, [mmAll, mmIgnoreCase, mmWholeWords], 1, regex));
end;

function CountStringMulti(s: TStringArray; str: string): Integer;
var
tmp, all: TIntegerArray;
h, i, l, f, a: Integer;
begin
h := High(s);
if ((str <> '') and (h > -1)) then
begin
for i := 0 to h do
begin
tmp := FindEx(str, s[i], [mmAll, mmIgnoreCase, mmWholeWords], 1, False);
f := High(tmp);
if (h > -1) then
begin
l := Length(all);
SetLength(all, (l + (f + 1)));
for a := 0 to f do
all[(a + l)] := Integer(tmp[a]);
SetLength(tmp, 0);
end;
end;
ClearSameIntegers(all);
Result := Length(all);
SetLength(all, 0);
end;
end;

function CountStringMultiEx(s: TStringArray; str: string; regex: Boolean): Integer;
var
tmp, all: TIntegerArray;
h, i, l, f, a: Integer;
begin
h := High(s);
if ((str <> '') and (h > -1)) then
begin
for i := 0 to h do
begin
tmp := FindEx(str, s[i], [mmAll, mmIgnoreCase, mmWholeWords], 1, regex);
f := High(tmp);
if (h > -1) then
begin
l := Length(all);
SetLength(all, (l + (f + 1)));
for a := 0 to f do
all[(a + l)] := Integer(tmp[a]);
SetLength(tmp, 0);
end;
end;
ClearSameIntegers(all);
Result := Length(all);
SetLength(all, 0);
end;
end;

(*
Auther: Officer Barbrady
*)
procedure FindBadCode;
begin
WriteLn('');
WriteLn('==============Looking for bad code===============');
if DetectSpacedText('mouse ( x , y , 1 , 1 )', ' ', filteredScriptText) then
begin
WriteLn('Found "(M)Mouse(x, y, 1, 1) " [Risk level: MEDIUM], potential ban.');
Inc(BadCode);
threats := (threats + 1);
end;
if not DetectSpacedText('random (', ' ', filteredScriptText) then
begin
WriteLn('Found no randomness in script [Risk level: MEDIUM], potential ban.');
Inc(BadCode)
threats := (threats + 1);
end;
WriteLn('========================================= ========');
end;

(*
Auther: Officer Barbrady
*)
procedure FindAbnormalCode;
var
ac: TStringArray;
i: Integer;
begin
WriteLn('');
WriteLn('============Looking for Abnormal code============');
ac := ['Name', 'Pass', 'Pin'];
for i := 0 to 2 do
if (CountStringEx(ReplaceWrap(('players (\[) (.*) (\]) (\.) ' + Lowercase(ac[i])), ' ', '(\s*)', [rfReplaceAll]), filteredScriptText, True) > 1) then
begin
WriteLn('The variable "' + ac[i] + '" is used more then once [Risk level: MEDIUM]');
Fishy := (Fishy + 1);
threats := (threats + 1);
end;
if (CountStringEx(ReplaceWrap('ToStr (\() players (\[) (.*) (\]) (\))', ' ', '(\s*)', [rfReplaceAll]), filteredScriptText, True) > 0) then
begin
WriteLn('Player data sent to ToStr() [Risk level: MEDIUM]');
Fishy := (Fishy + 1);
threats := (threats + 1);
end;
WriteLn('========================================= ========');
SetLength(ac, 0);
end;

(*
Auther: Officer Barbrady
*)
procedure FindHTTPThreats;
var
tmp: TIntegerArray;
matches, ht: TStringArray;
h, i: Integer;
begin
WriteLn('');
WriteLn('============Looking for HTTP threats=============');
ht := ['AddPostVariable', 'GetPage', 'PostHTTPPage', 'PostHTTPPageEx'];
for i := 0 to 3 do
if (CountStringEx((Lowercase(ht[i]) + ReplaceWrap(' (\()(.*)(\))', ' ', '(\s*)', [rfReplaceAll])), filteredScriptText, True) > 0) then
begin
WriteLn('Found "' + ht[i] + '" [Risk level: HIGH]');
Inc(HTTPThreats);
threats := (threats + 4);
end;
SetLength(ht, 0);
if TraceStrsEx(ReplaceWrap('openwebpage#(%)', '#', ' ', [rfReplaceAll]), [' ', '%'], ['(\s*)', '(.*)'], originalScriptText, False, matches, tmp) then
begin
h := High(matches);
WriteLn('Found attempt to OpenWebpage [Risk level: MEDIUM]');
for i := 0 to h do
if (CountStringMulti(['meatspin', 'porn', 'xxx', '18', 'sunny'], matches[i]) > 0) then
begin
WriteLn('Found adult content attempting to be opened via OpenWebpage [Risk level: MEDIUM-HIGH]');
Break;
end;
Inc(WebThreats);
threats := (threats + 4);
SetLength(tmp, 0);
SetLength(matches, 0);
end;
WriteLn('========================================= ========');
end;

(*
Auther: Officer Barbrady
*)
procedure Scan;
begin
WriteLn('=================Filtered Script=================');
if DEBUG_FILTERED_SCRIPT then
WriteLn(displayScriptText);
WriteLn('========================================= ========');
FindHTTPThreats;
FindAbnormalCode;
FindBadCode;
PrintReport;
end;

(*
Auther: Officer Barbrady
*)
procedure OpenThread(Sender: TObject);
begin
OpenWebPage('http://villavu.com/forum/showthread.php?t=103408');
end;

(*
Auther: Officer Barbrady
*)
procedure SaveFormInfo(Sender: TObject);
begin
DsgnForm.ModalResult := mrOk;
originalScriptText := ScriptEdit.Text;
filteredScriptText := FilterScriptData(originalScriptText);
pressed := True;
DsgnForm.Close;
end;

(*
Auther: Officer Barbrady
*)
procedure InitForm;
begin
DsgnForm := TForm.Create(nil);
with DsgnForm do
begin
Caption := ('Simba Script Scanner v' + VERSION);
Left := 377;
Top := 380;
Width := 750;
Height := 460;
Font.Name := default;
Font.Color := clDefault;
Font.Size := 0;
end;
ScriptEdit := TMemo.Create(DsgnForm);
with ScriptEdit do
begin
Parent := DsgnForm;
Left := 120;
Top := 80;
Width := 481;
Height := 177;
Font.Name := default;
with ScriptEdit.Lines do
Add('Paste script into this box, it will look for suspicious lines of code!');
ScrollBars := ssBoth;
TabOrder := 0;
end;
TitleLabel := TLabel.Create(DsgnForm);
with TitleLabel do
begin
Parent := DsgnForm;
Caption := ('Simba Script Scanner v' + VERSION);
Left := 225;
Top := 20;
Width := 43;
Height := 14;
Font.Name := default;
Font.Color := clDefault;
Font.Size := 17;
end;
ScanButton := TButton.Create(DsgnForm);
with ScanButton do
begin
Parent := DsgnForm;
Caption := 'Scan';
Left := 175;
Top := 300;
Width := 150;
Height := 25;
Font.Size := 12;
OnClick := @SaveFormInfo;
end;
UpdateButton := TButton.Create(DsgnForm);
with UpdateButton do
begin
Parent := DsgnForm;
Caption := 'Update';
Left := 400;
Top := 300;
Width := 150;
Height := 25;
Font.Size := 12;
OnClick := @OpenThread;
end;
end;

procedure SafeInitForm;
var
v: TVariantArray;
begin
SetLength(V, 0);
ThreadSafeCall('InitForm', v);
end;

procedure ShowFormModal;
begin
DsgnForm.ShowModal;
end;

procedure SafeShowFormModal;
var
v: TVariantArray;
begin
SetLength(V, 0);
ThreadSafeCall('ShowFormModal', v);
end;

begin
ClearDebug;
SafeInitForm;
SafeShowFormModal;
if pressed then
Scan;
end.

Optimized the regular expression's a little bit...
..and also some small changes here and there.

-Jani

Janilabo
06-10-2013, 10:08 AM
EDIT: 1.53:

-Removed some unneeded lines - by replacing functions that weren't really needed anymore
-Added a little bit more eye-candy in (should be enough now!)
-Tweaks here and there

MAD PROGRESS!

Doing another bump here now (sorry!), because I think these improvements, that I added in today, definitely deserves/requires some extra attention.. :p

So, I am releasing unofficial version "1.50"! Contains line-based scanning - debugs the malicious/bad lines including their kind (HTTP, Web, Fishy, Bad) and the threat-"message" itself.

Scanning works still the same way as earlier, so its still based on the same regexes, that means any multiline tricks/attempts will be detected just like they have been in the last 3-6 releases (can't remember exactly for which version I added in the regex-based scanning + I am too lazy to check, haha).

NOTE: Those debugged threats will be reported from the line where each threat start from (so its always debugging the starting position for em).

Scan example for the script itself (ScannerV1.53):

*************************************************
* _ _ _ _ _ _ _ _ __ *
* /_`/ `/_//|/ /_//_`/_// //_// *
* ._//_,/ // | / \/_,/ /_// \/ *
* *
*************************************************

=================Filtered Script=================
*SNIP*
=================================================

============Looking for HTTP Threats=============
=================================================

=============Looking for Web Threats=============
Found "OpenWebPage" [Risk level: HIGH]
=================================================

==============Looking for Fishy Code=============
=================================================

==============Looking for Bad Code===============
Found no randomness in script [Risk level: MEDIUM], potential ban.
=================================================

===============Lines with Threats================
LINE | KIND | THREAT
-------------------------------------------------
1236 | Web Threat | OpenWebPage(*)
=================================================

==================Scan Results===================
HTTP threats: 0
Web threats: 1
Fishy code: 0
Bad code: 1
Overall threats: 2
Over Script Risk: High
=================================================

=====================FINISHED====================
Remember to visit the thread for latest updates.
Thank you for using!
=================================================

..and the source code for 1.53:

{================================================= ======================================]
| |
| _____ _ _ _____ _ _ _____ |
| | __|_|_____| |_ ___ | __|___ ___|_|___| |_ | __|___ ___ ___ ___ ___ ___ |
| |__ | | | . | .'| |__ | _| _| | . | _| |__ | _| .'| | | -_| _| |
| |_____|_|_|_|_|___|__,| |_____|___|_| |_| _|_| |_____|___|__,|_|_|_|_|___|_| |
| |_| |
| |
[================================================== =====================================}

{$i SRL/SRL.simba}

const
VERSION = '1.53'; // Don't touch... Script version.
FILTER_COMMENTS = True; // Doesn't pay attention to stuff inside comments
// Recommended to keep this feature enabled, a lot less false positives!
COMMENT_FILTER = '@'; // CHAR, NOT STRING! Used in debug box for displaying the filtered comments (doesn't effect scan, as these will be empty chars in filteredScriptText for scan).
FILTER_STRINGS = True; // Doesn't pay attention to stuff INSIDE string signs.
// So, this feature still detects stuff that falls outside those '' signs! :)
STRING_FILTER = '%'; // CHAR, NOT STRING! Used in debug box for displaying the filtered strings (doesn't effect scan, these will be empty chars in filteredScriptText for scan).
DEBUG_FILTERED_SCRIPT = True; // Debug the script, that was filtered (used for most script parts), before scan statistics (displays empty chars with COMMENT_FILTER & STRING_FILTER).
DEFAULT = 'Times New Roman';

type
TMatchMethod = (mmAll, mmIgnoreCase, mmOverlap, mmWholeWords, mmStrictWW);
TMatchMethods = set of TMatchMethod;
TRegexMatch = record
position, size: Integer;
text: string;
end;
TRegexMatchArray = array of TRegexMatch;
T2DRegexMatchArray = array of TRegexMatchArray;
TRange = record
minimum, maximum: Integer;
end;
TRangeArray = array of TRange;
TThreat = record
line: Integer;
threat: string;
kind: (tk_HTTP, tk_Web, tk_Fishy, tk_Bad);
end;
TThreatArray = array of TThreat;

var
DsgnForm: TForm;
ScriptEdit: TMemo;
TitleLabel: TLabel;
ScanButton, UpdateButton: TButton;
originalScriptText, filteredScriptText, displayScriptText: string;
HTTPThreats, WebThreats, BadCode, threats, FishyCode: Integer;
msgHTTP, msgWeb, msgBad, msgFishy: string;
pressed: Boolean;
_threats: TThreatArray;
linePositions: TIntegerArray;

(*
Auther: Officer Barbrady
*)
procedure PrintReport;
var
Points: Integer;
h, i: Integer;
li, th, kd: string;
begin
WriteLn('***************************************** ********');
WriteLn('* _ _ _ _ _ _ _ _ __ *');
WriteLn('* /_`/ `/_//|/ /_//_`/_// //_// *');
WriteLn('* ._//_,/ // | / \/_,/ /_// \/ *');
WriteLn('* *');
WriteLn('***************************************** ********');
WriteLn(' ');
WriteLn('=================Filtered Script=================');
if DEBUG_FILTERED_SCRIPT then
WriteLn(displayScriptText);
WriteLn('========================================= ========');
WriteLn(' ');
WriteLn('============Looking for HTTP Threats=============');
if (msgHTTP <> '') then
WriteLn(msgHTTP);
WriteLn('========================================= ========');
WriteLn(' ');
WriteLn('=============Looking for Web Threats=============');
if (msgWeb <> '') then
WriteLn(msgWeb);
WriteLn('========================================= ========');
WriteLn(' ');
WriteLn('==============Looking for Fishy Code=============');
if (msgFishy <> '') then
WriteLn(msgFishy);
WriteLn('========================================= ========');
WriteLn(' ');
WriteLn('==============Looking for Bad Code===============');
if (msgBad <> '') then
WriteLn(msgBad);
WriteLn('========================================= ========');
WriteLn(' ');
WriteLn('===============Lines with Threats================');
h := High(_threats);
if (h > -1) then
begin
WriteLn(' LINE | KIND | THREAT ');
WriteLn('-------------------------------------------------');
for i := 0 to h do
begin
li := IntToStr(_threats[i].line);
case _threats[i].kind of
tk_Bad: kd := 'Bad Code';
tk_Fishy: kd := 'Fishy Code';
tk_HTTP: kd := 'HTTP Threat';
tk_Web: kd := 'Web Threat';
end;
th := _threats[i].threat;
WriteLn(' ' + (li + Padr(' ', (Length(' LINE |') - Length(li)) - 2)) + '| ' + (kd + Padr(' ', (Length(' KIND |') - Length(kd)) - 2)) + '| ' + th);
end;
end;
Points := (HTTPthreats + WebThreats + BadCode + FishyCode);
WriteLn('========================================= ========');
WriteLn(' ');
WriteLn('==================Scan Results===================');
WriteLn('HTTP threats: ' + ToStr(HTTPThreats));
WriteLn('Web threats: ' + ToStr(WebThreats));
WriteLn('Fishy code: ' + ToStr(FishyCode));
WriteLn('Bad code: ' + ToStr(BadCode));
WriteLn('Overall threats: ' + ToStr(Points))
case threats of
0: WriteLn('Over Script Risk: None');
1..2: WriteLn('Over Script Risk: Low');
3: WriteLn('Over Script Risk: Medium');
4..8: WriteLn('Over Script Risk: High');
end;
WriteLn('========================================= ========');
WriteLn(' ');
WriteLn('=====================FINISHED============ ========');
WriteLn(' Remember to visit the thread for latest updates.');
WriteLn(' Thank you for using! ');
WriteLn('========================================= ========');
end;

procedure NewThreat(var TTA: TThreatArray; line: Integer; threat: string; kind: (tk_HTTP, tk_Web, tk_Fishy, tk_Bad));
var
index, i, l: Integer;
begin
l := Length(TTA);
while (index < l) do
begin
if (line < TTA[index].line) then
Break;
Inc(index);
end;
SetLength(TTA, (l + 1));
if (l > index) then
for i := (l - 1) downto index do
TTA[(i + 1)] := TTA[i];
TTA[index].line := line;
TTA[index].threat := threat;
TTA[index].kind := kind;
end;

procedure TIAInsert(var TIA: TIntegerArray; index: Integer; int: Integer);
var
i, l: Integer;
begin
l := Length(TIA);
SetLength(TIA, (l + 1));
if (index < 0) then
index := 0;
if (index > l) then
index := l;
if (l > index) then
for i := (l - 1) downto index do
TIA[(i + 1)] := Integer(TIA[i]);
TIA[index] := Integer(int);
end;

{================================================= =============================]
Explanation: Returns string of all TSA items binded together. Places glue between the indexes.
[================================================== ============================}
function TSAConcatEx(TSA: TStringArray; glue: string): string;
var
h, i: Integer;
begin
Result := '';
h := High(TSA);
if (h > -1) then
begin
for i := 0 to (h - 1) do
Result := (Result + string(TSA[i]) + string(glue));
Result := (Result + string(TSA[i]));
end;
end;

{================================================= =============================]
Explanation: Explodes str with multiple separators/delimiters (d).
The importance order for d items is from left to right (=>).
So place the important ones first and then less important after those.
[================================================== ============================}
function ExplodeMulti(d: TStringArray; str: string): TStringArray;
var
p, h, i, x, o, m, l, y, z: Integer;
begin
h := High(d);
if ((h > -1) and (str <> '')) then
begin
o := 1;
SetLength(Result, Length(str));
repeat
l := 0;
for x := 0 to h do
begin
p := Pos(d[x], str);
case (p < 1) of
True:
begin
z := High(d);
if ((x <= z) and (x > -1)) then
begin
for y := x to (z - 1) do
d[y] := d[(y + 1)];
SetLength(d, z);
end;
Dec(x);
Dec(h);
end;
False:
if ((l = 0) or (p < l)) then
begin
m := x;
l := p;
end;
end;
end;
if (l > 0) then
begin
Result[i] := Copy(str, 1, (l - 1));
Delete(str, 1, ((l + Length(d[m])) - 1));
Inc(i);
end else
Result[i] := Copy(str, 1, Length(str));
until (l = 0);
SetLength(Result, (i + 1));
end else
Result := [string(str)];
end;

{================================================= =============================]
Explanation: Finds position from s items in str. Stores the ID of the found s item to index variable.
The importance order for d items is from left to right (=>).
So place the important ones first and then less important after those.
Contains field for offset.
[================================================== ============================}
function PosMultiIDEx(s: TStringArray; str: string; var index: Integer; offset: Integer): Integer;
var
h, i, p, t: Integer;
begin
if (offset < 1) then
offset := 1;
Result := -1;
index := -1;
h := High(s);
if ((h > -1) and (str <> '')) then
begin
t := (Length(str) + 1);
Result := t;
for i := 0 to h do
begin
p := PosEx(s[i], str, offset);
if ((p > 0) and (p < Result)) then
begin
Result := p;
index := i;
end;
end;
if (Result = t) then
Result := 0;
end;
end;

function PosAll(s, str: string): TIntegerArray;
var
sL, strL, o, p, r: Integer;
begin
sL := Length(s);
strL := Length(str);
if (sL <= strL) then
begin
SetLength(Result, strL);
repeat
p := PosEx(s, str, (o + 1));
if (p > 0) then
begin
Result[r] := p;
o := p;
Inc(r);
end;
until (p <= 0);
end;
SetLength(Result, r);
end;

function ToRange(minimum, maximum: Integer): TRange;
begin
Result.minimum := Integer(minimum);
Result.maximum := Integer(maximum);
end;

procedure TRAAppend(var TRA: TRangeArray; x: TRange);
var
aL: Integer;
begin
aL := (Length(TRA) + 1);
SetLength(TRA, aL);
TRA[(aL - 1)] := TRange(x);
end;

function TrackCaS(str: string; var comments, strings: TRangeArray): Boolean;
var
s, i, o, e, x, l, a, ls: Integer;
t: TStringArray;
begin
Result := False;
SetLength(comments, 0);
SetLength(strings, 0);
l := Length(str);
ls := -1;
if (l > 0) then
begin
o := 1;
t := ['//', '(*', '{', ''''];
repeat
s := PosMultiIDEx(t, str, i, o);
case (s <= ls) of
True: Exit;
False: ls := s;
end;
if (s > 0) then
begin
o := (s + 1);
a := 0;
case i of
0, 1, 2:
begin
case i of
0:
begin
e := PosMultiIDEx([#13#10, #13, #10], str, x, o);
if (x = 0) then
a := 1;
if (e = 0) then
e := l;
TRAAppend(comments, ToRange(s, e));
end;
1, 2:
begin
case i of
1:
begin
e := PosEx('*)', str, o);
a := 1;
end;
2: e := PosEx('}', str, o);
end;
if (e = 0) then
e := l;
TRAAppend(comments, ToRange(s, (e + a)));
end;
end;
end;
3:
begin
e := PosMultiIDEx([#13#10, #13, #10, ''''], str, x, o);
if (x = 0) then
a := 1;
case (e = 0) of
True:
begin
e := l;
TRAAppend(strings, ToRange(s, e));
end;
False:
case x of
0, 1, 2: TRAAppend(strings, ToRange(s, e));
3: TRAAppend(strings, ToRange(s, (e + a)));
end;
end;
end;
end;
o := ((e + 1) + a);
end;
until ((s = 0) or (x = -1) or (o > l));
end;
end;

{================================================= =============================]
Explanation: Trims all TSA items.
[================================================== ============================}
procedure TSATrim(var TSA: TStringArray);
var
h, i: Integer;
begin
h := High(TSA);
for i := 0 to h do
TSA[i] := Trim(TSA[i]);
end;

{================================================= =============================]
Explanation: Returns all the positions by items from s array in str. Place s items in importance order (=>)
If overlap is set to true, strings can overlap.
(['aa'], 'baaaah', False) => [2,3,4]
(['aa'], 'baaaah', True) => [2,4]
[================================================== ============================}
function PosAllMulti(s: TStringArray; str: string; overlap: Boolean): TIntegerArray;
var
h, l, p, o, x, i, t, r, y, d: Integer;
begin
h := High(s);
y := Length(str);
if ((y > 0) and (h > -1)) then
begin
SetLength(Result, y);
o := 1;
repeat
p := 0;
for x := 0 to h do
begin
t := PosEx(s[x], str, (l + o));
case (t < 1) of
True:
begin
for d := x to (h - 1) do
s[d] := s[(d + 1)];
SetLength(s, h);
Dec(x);
Dec(h);
end;
False:
if ((p = 0) or (t < p)) then
begin
p := t;
i := x;
end;
end;
end;
if (p > 0) then
begin
Result[r] := p;
Inc(r);
l := p;
if not overlap then
o := Length(s[i]);
end;
until (p <= 0);
end;
SetLength(Result, r);
end;

procedure FillStrRangeEx(var str: string; fillWith: Char; range: TRange; exceptions: TIntegerArray);
var
i, l, c: Integer;
begin
l := Length(str);
if ((l > 0) and not (range.minimum > range.maximum)) then
begin
if (range.minimum < 1) then
range.minimum := 1;
if (range.maximum > l) then
range.maximum := l;
if (range.minimum > l) then
Exit;
c := iAbs(range.maximum - range.minimum);
for i := range.minimum to range.maximum do
if not InIntArray(exceptions, i) then
str[i] := fillWith;
end;
end;

function FilterScriptData(data: string): string;
var
h, i, l: Integer;
newLines: TIntegerArray;
comments, strings: TRangeArray;
tmp: TStringArray;
begin
Result := string(data);
displayScriptText := string(Result);
l := Length(Result);
if (Result <> '') then
begin
if (FILTER_STRINGS or FILTER_COMMENTS) then
begin
newLines := PosAllMulti([#13, #10], Result, False);
TrackCaS(data, comments, strings);
h := High(comments);
if FILTER_COMMENTS then
for i := 0 to h do
begin
FillStrRangeEx(Result, '!', comments[i], newLines);
FillStrRangeEx(displayScriptText, COMMENT_FILTER, comments[i], newLines);
end;
h := High(strings);
if FILTER_COMMENTS then
for i := 0 to h do
begin
FillStrRangeEx(Result, '!', strings[i], newLines);
FillStrRangeEx(displayScriptText, STRING_FILTER, strings[i], newLines);
end;
SetLength(newLines, 0);
SetLength(comments, 0);
SetLength(strings, 0);
Result := ReplaceWrap(Result, '!', '', [rfReplaceAll]);
end;
tmp := ExplodeMulti([#13#10, #13, #10], Result);
TSATrim(tmp);
Result := TSAConcatEx(tmp, #13#10);
SetLength(tmp, 0);
end;
end;

{================================================= =============================]
Explanation: Returns all the positions of found/matching strings (findStr) in text.
Uses a set of TMatchMethod (methods) for string matching.
Contains field for offset.
If regex field is set as true, then this function searches for the regex you use.
[================================================== ============================}
function FindEx(text, findStr: string; methods: TMatchMethods; offset: Integer; regex: Boolean): TIntegerArray;
var
rmArr: TRegexMatchArray;
rmArr2D: T2DRegexMatchArray;
sb, sa: string;
r, i, l, f, p, d, o, x, y, abL, abR, abX, abP, spA, spB, spH, spL, spI, spR, spD: Integer;
re: TRegExp;
ma, mb, a, s, ol: Boolean;
c: TIntegerArray;
t: T2DIntegerArray;
begin
l := Length(text);
f := Length(findStr);
if ((l > 0) and (f > 0) and (offset <= (l - f))) then
begin
if (offset < 1) then
offset := 1;
if not regex then
begin
for i := f downto 1 do
if (Pos(findStr[i], '.\+*?[^]$(){}=!<>|:-') > 0) then
Insert('\', findStr, i);
SetLength(Result, l);
re := TRegExp.Create;
re.InputString := text;
re.Expression := findStr;
if (mmIgnoreCase in methods) then
re.ModifierI := True;
a := (mmAll in methods);
case a of
False: re.ModifierG := True;
True: re.ModifierG := False;
end;
re.ModifierM := True;
ol := (mmOverlap in methods);
if not ol then
o := (Length(findStr) - 1);
Inc(o);
p := offset;
while re.ExecPos(p) do
begin
Result[r] := re.MatchPos[0];
p := (Result[r] + o);
Inc(r);
end;
p := Offset;
re.Free;
SetLength(Result, r);
if ((r > 0) and (mmWholeWords in methods)) then
begin
s := (mmStrictWW in methods);
if not s then
c := [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, // A-Z
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, // a-z
48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; // 0-9
case ol of
True:
begin
spH := High(Result);
if (spH > -1) then
begin
SetLength(t, (spH + 1));
t[0] := [Integer(Result[0])];
if (spH > 0) then
begin
spR := 1;
for spI := 1 to spH do
begin
for spA := 0 to (spR - 1) do
begin
spL := Length(t[spA]);
for spB := 0 to (spL - 1) do
begin
spD := IAbs(Result[spI] - t[spA][spB]);
if (spD <= f) then
begin
SetLength(t[spA], (spL + 1));
t[spA][spL] := Integer(Result[spI]);
Break;
end;
end;
if (spB < spL) then
Break;
end;
if (spA >= spR) then
begin
t[spR] := [Integer(Result[spI])];
Inc(spR);
end;
end;
end;
SetLength(t, spR);
spH := High(t);
for spI := spH downto 0 do
begin
spB := Low(t[spI]);
spA := High(t[spI]);
abX := 1;
abP := t[spI][spB];
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (t[spI][spA] + f);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = '') or (sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = '') or (sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
for spD := spI to (spH - 1) do
t[spD] := t[(spD + 1)];
SetLength(t, spH);
Dec(spH);
end;
end;
spH := High(t);
if (spH > -1) then
begin
for spI := 0 to spH do
IncEx(spR, (High(t[spI]) + 1));
SetLength(Result, spR);
spR := 0;
for spI := 0 to spH do
begin
spL := High(t[spI]);
for spA := 0 to spL do
begin
Result[spR] := Integer(t[spI][spA]);
Inc(spR);
end;
end;
SetLength(Result, spR);
end else
SetLength(Result, 0);
end else
r := 0;
end;
False:
begin
for x := (r - 1) downto 0 do
begin
abX := 1;
abP := Result[x];
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (Result[x] + f);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = '') or (sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = '') or (sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
y := (r - 1);
for d := x to (y - 1) do
Result[d] := Result[(d + 1)];
SetLength(Result, y);
Dec(r);
end;
end;
end;
end;
end;
if (not a and (r > 0)) then
SetLength(Result, 1);
end else
begin
SetLength(rmArr, l);
re := TRegExp.Create;
re.InputString := text;
re.Expression := findStr;
if (mmIgnoreCase in methods) then
re.ModifierI := True;
a := (mmAll in methods);
case a of
False: re.ModifierG := True;
True: re.ModifierG := False;
end;
re.ModifierM := True;
ol := (mmOverlap in methods);
p := offset;
while re.ExecPos(p) do
begin
rmArr[r].position := re.MatchPos[0];
rmArr[r].text := re.Match[0];
rmArr[r].size := re.MatchLen[0];
if ol then
p := (rmArr[r].position + 1)
else
p := (rmArr[r].position + rmArr[r].size);
Inc(r);
end;
p := Offset;
re.Free;
SetLength(rmArr, r);
if ((r > 0) and (mmWholeWords in methods)) then
begin
s := (mmStrictWW in methods);
if not s then
c := [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, // A-Z
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, // a-z
48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; // 0-9
case ol of
True:
begin
spH := High(rmArr);
if (spH > -1) then
begin
SetLength(rmArr2D, (spH + 1));
rmArr2D[0] := [TRegexMatch(rmArr[0])];
if (spH > 0) then
begin
spR := 1;
for spI := 1 to spH do
begin
for spA := 0 to (spR - 1) do
begin
spL := Length(rmArr2D[spA]);
for spB := 0 to (spL - 1) do
begin
spD := IAbs(rmArr[spI].position - rmArr2D[spA][spB].position);
if (spD <= rmArr2D[spA][spB].size) then
begin
SetLength(rmArr2D[spA], (spL + 1));
rmArr2D[spA][spL] := TRegexMatch(rmArr[spI]);
Break;
end;
end;
if (spB < spL) then
Break;
end;
if (spA >= spR) then
begin
rmArr2D[spR] := [TRegexMatch(rmArr[spI])];
Inc(spR);
end;
end;
end;
SetLength(rmArr2D, spR);
spH := High(rmArr2D);
for spI := spH downto 0 do
begin
spB := Low(rmArr2D[spI]);
spA := High(rmArr2D[spI]);
abX := 1;
abP := rmArr2D[spI][spB].position;
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (rmArr2D[spI][spA].position + rmArr2D[spI][spA].size);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = '') or (sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = '') or (sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
for spD := spI to (spH - 1) do
rmArr2D[spD] := rmArr2D[(spD + 1)];
SetLength(rmArr2D, spH);
Dec(spH);
end;
end;
spH := High(rmArr2D);
if (spH > -1) then
begin
for spI := 0 to spH do
IncEx(spR, (High(rmArr2D[spI]) + 1));
SetLength(rmArr, spR);
spR := 0;
for spI := 0 to spH do
begin
spL := High(rmArr2D[spI]);
for spA := 0 to spL do
begin
rmArr[spR] := TRegexMatch(rmArr2D[spI][spA]);
Inc(spR);
end;
end;
SetLength(rmArr, spR);
r := spR;
end else
SetLength(rmArr, 0);
end else
r := 0;
end;
False:
begin
for x := (r - 1) downto 0 do
begin
abX := 1;
abP := rmArr[x].position;
abL := Length(text);
case ((abL > 0) and (abP > 1)) of
True:
begin
if ((abP - abX) < 1) then
abX := ((abP - abX) + (abX - 1));
if (abP > (abL + 1)) then
begin
abR := ((abP - abL) - 1);
abX := (abX - abR);
end;
sb := Copy(text, ((abP - abX) - abR), abX);
end;
False: sb := '';
end;
abX := 1;
abP := (rmArr[x].position + rmArr[x].size);
abL := Length(text);
case ((abL > 0) and (abP <= abL)) of
True:
begin
if (abP < 1) then
begin
abX := (abX - iAbs(abP - 1));
abP := 1;
end;
if ((abX > 0) and ((abP + abX) > abL)) then
abX := (abX - (((abP + abX) - abL) - 1));
sa := Copy(text, abP, abX);
end;
False: sa := '';
end;
case s of
True:
begin
mb := ((sb = '') or (sb = ' ') or (sb = #13#10) or (sb = #13) or (sb = #10));
ma := ((sa = '') or (sa = ' ') or (sa = #13#10) or (sa = #13) or (sa = #10));
end;
False:
begin
mb := ((sb = '') or not InIntArray(c, Ord(sb[1])));
ma := ((sa = '') or not InIntArray(c, Ord(sa[1])));
end;
end;
if not (mb and ma) then
begin
y := (r - 1);
for d := x to (y - 1) do
rmArr[d] := rmArr[(d + 1)];
SetLength(rmArr, y);
Dec(r);
end;
end;
end;
end;
end;
case (r > 0) of
True:
begin
if not a then
r := 1;
SetLength(Result, r);
for i := 0 to (r - 1) do
Result[i] := rmArr[i].position;
end;
False: SetLength(Result, 0);
end;
end;
end else
SetLength(Result, 0);
end;

function CountString(s, str: string): Integer;
begin
Result := Length(FindEx(str, s, [mmAll, mmIgnoreCase, mmWholeWords], 1, False));
end;

function CountStringEx(s, str: string; regex: Boolean): Integer;
begin
Result := Length(FindEx(str, s, [mmAll, mmIgnoreCase, mmWholeWords], 1, regex));
end;

function CountStringMulti(s: TStringArray; str: string): Integer;
var
tmp, all: TIntegerArray;
h, i, l, f, a: Integer;
begin
h := High(s);
if ((str <> '') and (h > -1)) then
begin
for i := 0 to h do
begin
tmp := FindEx(str, s[i], [mmAll, mmIgnoreCase, mmWholeWords], 1, False);
f := High(tmp);
if (h > -1) then
begin
l := Length(all);
SetLength(all, (l + (f + 1)));
for a := 0 to f do
all[(a + l)] := Integer(tmp[a]);
SetLength(tmp, 0);
end;
end;
ClearSameIntegers(all);
Result := Length(all);
SetLength(all, 0);
end;
end;

function CountStringMultiEx(s: TStringArray; str: string; regex: Boolean): Integer;
var
tmp, all: TIntegerArray;
h, i, l, f, a: Integer;
begin
h := High(s);
if ((str <> '') and (h > -1)) then
begin
for i := 0 to h do
begin
tmp := FindEx(str, s[i], [mmAll, mmIgnoreCase, mmWholeWords], 1, regex);
f := High(tmp);
if (h > -1) then
begin
l := Length(all);
SetLength(all, (l + (f + 1)));
for a := 0 to f do
all[(a + l)] := Integer(tmp[a]);
SetLength(tmp, 0);
end;
end;
ClearSameIntegers(all);
Result := Length(all);
SetLength(all, 0);
end;
end;

function PositionToLine(position: Integer): Integer;
var
h: Integer;
begin
Result := 1;
h := High(linePositions);
if (h > -1) then
case (h > 0) of
True:
for Result := 1 to (h + 1) do
if (position < linePositions[(Result - 1)]) then
Break;
False:
if (position >= linePositions[0]) then
Result := 2;
end;
Dec(Result);
end;

procedure AddMessage(var msgs: string; msg: string);
begin
case (msgs <> '') of
True: msgs := (msgs + #13#10 + msg);
False: msgs := msg;
end;
end;

(*
Auther: Officer Barbrady
*)
procedure FindBadCode;
var
h, i, x: Integer;
bc: TStringArray;
tmp: TIntegerArray;
s: string;
begin
msgBad := '';
bc := ['mmouse (\() x , y , 1 , 1 (\))', 'mouse (\() x , y , 1 , 1 ,(.*)(\))'];
for x := 0 to 1 do
begin
tmp := FindEx(filteredScriptText, ReplaceWrap(bc[x], ' ', '(\s*)', [rfReplaceAll]), [mmAll, mmIgnoreCase, mmWholeWords], 1, True);
h := High(tmp);
if (h > -1) then
begin
case x of
0: s := 'MMouse(x, y, 1, 1)';
1: s := 'Mouse(x, y, 1, 1, *)';
end;
for i := 0 to h do
NewThreat(_threats, PositionToLine(tmp[i]), s, tk_Bad);
AddMessage(msgBad, 'Found "' + s + '" [Risk level: MEDIUM], potential ban.');
Inc(BadCode);
threats := (threats + 1);
SetLength(tmp, 0);
end;
end;
SetLength(bc, 0);
tmp := FindEx(filteredScriptText, ReplaceWrap('(random (\()(.*)(\))|randomrange (\()(.*)(\)))', ' ', '(\s*)', [rfReplaceAll]), [mmAll, mmIgnoreCase, mmWholeWords], 1, True);
h := High(tmp);
case (h = -1) of
True:
begin
AddMessage(msgBad, 'Found no randomness in script [Risk level: MEDIUM], potential ban.');
Inc(BadCode)
Inc(threats);
end;
False: SetLength(tmp, 0);
end;
end;

(*
Auther: Officer Barbrady
*)
procedure FindFishyCode;
var
ac: TStringArray;
h, i, x: Integer;
tmp: TIntegerArray;
begin
msgFishy := '';
ac := ['Name', 'Pass', 'Pin'];
for x := 0 to 2 do
begin
tmp := FindEx(filteredScriptText, ReplaceWrap(('players (\[) (.*) (\]) (\.) ' + Lowercase(ac[x])), ' ', '(\s*)', [rfReplaceAll]), [mmAll, mmIgnoreCase, mmWholeWords], 1, True);
h := High(tmp);
if (h > 0) then
begin
for i := 0 to h do
NewThreat(_threats, PositionToLine(tmp[i]), ('Players .' + ac[x]), tk_Fishy);
IncEx(FishyCode, (h + 1));
AddMessage(msgFishy, 'The variable "' + ac[x] + '" is used more then once [Risk level: MEDIUM]');
Inc(threats);
end;
SetLength(tmp, 0);
end;
tmp := FindEx(filteredScriptText, ReplaceWrap('ToStr (\() players (\[) (.*) (\]) (\))', ' ', '(\s*)', [rfReplaceAll]), [mmAll, mmIgnoreCase, mmWholeWords], 1, True);
h := High(tmp);
if (h > -1) then
begin
for i := 0 to h do
NewThreat(_threats, PositionToLine(tmp[i]), 'ToStr(Players )', tk_Fishy);
IncEx(FishyCode, (h + 1));
AddMessage(msgFishy, 'Player data sent to ToStr() [Risk level: MEDIUM]');
Inc(threats);
SetLength(tmp, 0);
end;
SetLength(ac, 0);
end;

(*
Auther: Officer Barbrady
*)
procedure FindHTTPThreats;
var
ht: TStringArray;
h, i, x: Integer;
tmp: TIntegerArray;
begin
msgHTTP := '';
ht := ['AddPostVariable', 'GetPage', 'PostHTTPPage', 'PostHTTPPageEx'];
for x := 0 to 3 do
begin
tmp := FindEx(filteredScriptText, (Lowercase(ht[x]) + ReplaceWrap(' (\()(.*)(\))', ' ', '(\s*)', [rfReplaceAll])), [mmAll, mmIgnoreCase, mmWholeWords], 1, True);
h := High(tmp);
if (h > -1) then
begin
for i := 0 to h do
NewThreat(_threats, PositionToLine(tmp[i]), (ht[x] + '(*)'), tk_HTTP);
IncEx(HTTPThreats, (h + 1));
AddMessage(msgHTTP, 'Found "' + ht[x] + '" [Risk level: HIGH]');
IncEx(threats, 4);
end;
SetLength(tmp, 0);
end;
SetLength(ht, 0);
end;

(*
Auther: Officer Barbrady
*)
procedure FindWebThreats;
var
h, i: Integer;
tmp: TIntegerArray;
begin
msgWeb := '';
tmp := FindEx(filteredScriptText, ('openwebpage' + ReplaceWrap(' (\()(.*)(\))', ' ', '(\s*)', [rfReplaceAll])), [mmAll, mmIgnoreCase, mmWholeWords], 1, True);
h := High(tmp);
if (h > -1) then
begin
for i := 0 to h do
NewThreat(_threats, PositionToLine(tmp[i]), 'OpenWebPage(*)', tk_Web);
IncEx(WebThreats, (h + 1));
AddMessage(msgWeb, 'Found "OpenWebPage" [Risk level: HIGH]');
IncEx(threats, 4);
SetLength(tmp, 0);
end;
end;

(*
Auther: Officer Barbrady
*)
procedure Scan;
begin
FindHTTPThreats;
FindWebThreats;
FindFishyCode;
FindBadCode;
PrintReport;
end;

(*
Auther: Officer Barbrady
*)
procedure OpenThread(Sender: TObject);
begin
OpenWebPage('http://villavu.com/forum/showthread.php?t=103408');
end;

(*
Auther: Officer Barbrady
*)
procedure SaveFormInfo(Sender: TObject);
var
tmp: TStringArray;
begin
DsgnForm.ModalResult := mrOk;
tmp := ExplodeMulti([#13#10, #13, #10], ScriptEdit.Text);
originalScriptText := TSAConcatEx(tmp, #13#10);
SetLength(tmp, 0);
filteredScriptText := FilterScriptData(originalScriptText);
linePositions := PosAll(#13#10, filteredScriptText);
TIAInsert(linePositions, 0, 1);
pressed := True;
DsgnForm.Close;
end;

(*
Auther: Officer Barbrady
*)
procedure InitForm;
begin
DsgnForm := TForm.Create(nil);
with DsgnForm do
begin
Caption := ('Simba Script Scanner v' + VERSION);
Left := 377;
Top := 380;
Width := 750;
Height := 460;
Font.Name := default;
Font.Color := clDefault;
Font.Size := 0;
end;
ScriptEdit := TMemo.Create(DsgnForm);
with ScriptEdit do
begin
Parent := DsgnForm;
Left := 120;
Top := 80;
Width := 481;
Height := 177;
Font.Name := default;
with ScriptEdit.Lines do
Add('Paste script into this box, it will look for suspicious lines of code!');
ScrollBars := ssBoth;
TabOrder := 0;
end;
TitleLabel := TLabel.Create(DsgnForm);
with TitleLabel do
begin
Parent := DsgnForm;
Caption := ('Simba Script Scanner v' + VERSION);
Left := 225;
Top := 20;
Width := 43;
Height := 14;
Font.Name := default;
Font.Color := clDefault;
Font.Size := 17;
end;
ScanButton := TButton.Create(DsgnForm);
with ScanButton do
begin
Parent := DsgnForm;
Caption := 'Scan';
Left := 175;
Top := 300;
Width := 150;
Height := 25;
Font.Size := 12;
OnClick := @SaveFormInfo;
end;
UpdateButton := TButton.Create(DsgnForm);
with UpdateButton do
begin
Parent := DsgnForm;
Caption := 'Update';
Left := 400;
Top := 300;
Width := 150;
Height := 25;
Font.Size := 12;
OnClick := @OpenThread;
end;
end;

procedure SafeInitForm;
var
v: TVariantArray;
begin
SetLength(V, 0);
ThreadSafeCall('InitForm', v);
end;

procedure ShowFormModal;
begin
DsgnForm.ShowModal;
end;

procedure SafeShowFormModal;
var
v: TVariantArray;
begin
SetLength(V, 0);
ThreadSafeCall('ShowFormModal', v);
end;

begin
ClearDebug;
SafeInitForm;
SafeShowFormModal;
if pressed then
Scan;
originalScriptText := '';
filteredScriptText := '';
displayScriptText := '';
end.

Officer Barbrady
I wonder, if this unofficial 1.42 should be official version "1.50" (when you'll do some merging with your latest form improvements first) and then this new unofficial 1.50 could be the official version "2.00" (with those same form improvements for GUI part)
Because, this version 1.50 doesn't have adult content detection anymore...
Also, these both have PRO's and CON's (1.42 is probably a lot faster, whereas 1.50 is a little more advanced with its features and that way slower)
So, I'd say they are both pretty good.. With different kind of structures, of course. :)

Script is attached!

Regards,
-Jani

rj
06-10-2013, 03:14 PM
updated, working on making into an extension

Janilabo
06-10-2013, 10:29 PM
updated, working on making into an extensionYay, thanks!

Really like the extension version. :)

However, there's some problems with it, that doesn't exist in script (form) version:
-When you scan more than 1 time, the results keep growing - for some reason, extension version doesn't reset variables... I wonder why?
-Sometimes it debugs the original script when it should debug the filtered script - this doesn't make any sense, but it could be again something to do with extension behaviour (storing settings behind the scenes or so)
-Buggy, ignores those checkbox checked states sometimes..
-ClearDebug not supported
-Status() not supported

So, at this point, script version is a lot more reliable, but hopefully extension version will catch up, because this utility is a lot more useful as an extension than script (in my opinion).

Anyways, I attached latest extension [2.01] and latest script [1.54] to this post.

Enjoy!

Dgby714
06-10-2013, 11:49 PM
Extentions are ran at the start of Simba, and wont stop until you close Simba.

Janilabo
06-11-2013, 12:10 AM
Extentions are ran at the start of Simba, and wont stop until you close Simba.Thanks Dgby, that clears it up.

rj
06-11-2013, 12:14 AM
Extentions are ran at the start of Simba, and wont stop until you close Simba.

So theres not much I can do to fix the problem?

Dgby714
06-11-2013, 12:21 AM
So theres not much I can do to fix the problem?

Initialize your variables when you start the scan.

Dgby714
06-11-2013, 12:33 AM
Also, Just a note, You do know all your OnClick methods can be 1 method right?

Also, Your form should be created in the Init. Just hide it, and show when the button is clicked, OnShow, Clear it's data.

You should put it on GitHub, I'll send some pull request with fixes. =P

I feel like y'all need to understand how Extensions work internally, if you have any questions, join me on IRC in #Simba (http://villavu.com/forum/usertag.php?do=list&action=hash&hash=Simba) .

rj
06-12-2013, 12:45 AM
I'm going to be leaving tomorrow, ill be away until Sunday