Thursday, November 16, 2017

PHP Delphi RAT

https://github.com/davidtavarez/pinky

https://www.opensc.io/showthread.php?t=20902

http://deciphertech.sitey.me/rat-tools/


Nice advice:



PART 1 - EASY

A. Scramble the procedures

Play a lot. Exchange places of every procedure one by one. Turn your code upside down. If it works, good. If not, change the order again. In general this doesn't help very much to make the RAT undetected... yet.

B. Change the strings and the procedure names

Yeah, boring. But it's not a good idea if the RAT has the string 'You are connected to XYZ RAT! Welcome!', the AV companies just love that thing. Change it or remove it. Same with procedure names. Well, not exactly the same but whatever... It will help.

C. Change the image base value

What's that? Here goes an introduction: The $IMAGEBASE directive controls the default load address for an application or DLL. The use is {$IMAGEBASE number} and it must be placed on your project file ( .dpr ). The default number value is $00400000 and it can be almost any value from $00010000 to $7FFFFFFF. Why change it? Because changing this, it will change the entrypoint. What's entrypoint? Google is our best friend, remember? And it changes some other things too, but all you have to know is: this will help, specially on a DLL.


PART 2 - INTERMEDIATE

Keep in mind that these operations can slow down your program. Maybe a lot, maybe just some ms...

A. Change the IF...THEN...ELSE procedure order

Whenever possible, just put the THEN procedure on the ELSE place, and vice versa. Don't forget to change the IF statement, so the procedure works correctly.

B. Create dummy procedures

Create procedures that do nothing, or just return one char of the entire string, or something useless like this:

function DummyInteger(dummy: integer): integer;
begin
result := StrToInt(IntToStr(StrToInt(IntToStr(StrToInt(IntTo Str(StrToInt(IntToStr(dummy))))))));
end;

The main goal is to generate useless code inside procedures. An important thing to remember is: call these procedures

C. Insert NOPs

What is a NOP? NOP stands for "No OPeration". It's just a byte in the code that does nothing but slows down your program and increases its size. In case you want to insert a NOP inside the DummyInteger procedure, do this:

function DummyInteger(dummy: integer): integer;
begin
asm // here
nop // is
end; // our NOP
result := StrToInt(IntToStr(StrToInt(IntToStr(StrToInt(IntTo Str(StrToInt(IntToStr(dummy))))))));
end;

Is it hard do do this? No. So why is it in the intermediate section? Because you must use your brains to know where to insert it. Just do me a favor, don't insert NOPs inside a loop that catches the files inside folders...


PART 3 - ADVANCED ( really advanced, i'm not gonna explain anything from this section )

A. Using GetProcAddress to load DLL functions

Almost all the heuristics scanners read the IAT to see what the program can do. So if we don't leave any traces there they can't catch us! Easy, right? Well, not really... There's an example of how to use GetProcAddress on my Tiny Delphi Protected Storage Unit, available for download on the main site. See the initialization section. You have to call all external functions that way...

B. Using shitty ASM procedures

I should warn you that this operation will slow down your application. Probably a lot... First of all, completely turn off the compiler optimizations. Why? Because you're gonna insert lots of useless ASM operations and you don't want any of the optimizations performed by the compiler. What operations should you insert? If you're reading this you should know, but Google helps us a lot! I'm not an ASM-guru but we all should know something in assembler, it's very useful. I'll give only one example:

Instead of using the "clean" well-known GetWindowsDirectory function, you can use this:

function GetWindowsDirectory: string;
var
path : array [0..MAX_PATH] of char;
begin
asm
lea eax, path
test eax, eax
push eax
xor eax, eax
call GetWindowsDirectoryA
end;
result := string(path)+'\'
end;

This is not the easiest thing to understand, but be sure Delphi will NEVER compile anything like that. It works but it's ugly, slow and there are much better ways to do this... Believe me...
In some cases, you could turn optimizations off in the EASY part, after changing the image base value... Without optimizations the compiler generates more code and it can differ significantly from the original ( almost noone disables the compiler optimization ), so weak AV's can be easily bypassed this way... Well, a beginner reading this section has to get some kind of reward





PHP Lazarus kodiranje-dekodiranje

http://forum.lazarus.freepascal.org/index.php?topic=36618.0

As for proof ...

Pascal version:
Code: Pascal  [Select]
  1. program plip;
  2. {$MODE OBJFPC}{$H+}
  3. uses
  4.   SysUtils
  5.   DCPcrypt2, DCPrijndael, DCPbase64;
  6. function BinStr2Hex(S: AnsiString): AnsiString;
  7. var
  8.   i: integer;
  9. begin
  10.   Result := '';
  11.   for i := 1 to Length(S)
  12.     do Result := Result + LowerCase(HexStr(Byte(S[i]), 2));
  13. end;
  14. var
  15.   Cipher : TDCP_rijndael;
  16.   Key    : AnsiString;
  17.   IV     : AnsiString;
  18.   Data   : AnsiString;
  19.   CBC    : AnsiString;
  20.   ECB    : AnsiString;
  21.   Buffer : AnsiString;
  22. begin
  23.   Data := 'Hello World_____';
  24.   Key  := '1234567890______';
  25.   IV   := '______1234567890';
  26.   Cipher := TDCP_rijndael.Create(nil);
  27.   Cipher.Init(Key[1], 128, @IV[1]);
  28.   SetLength(Buffer, Length(Data));
  29.   Cipher.EncryptECB(Data[1], Buffer[1]);
  30.   Cipher.Free;
  31.   ECB := Buffer;  
  32.   Cipher := TDCP_rijndael.Create(nil);
  33.   Cipher.Init(Key[1], 128, @IV[1]);
  34.   SetLength(Buffer, Length(Data));
  35.   Cipher.EncryptCBC(Data[1], Buffer[1], Length(Data));
  36.   Cipher.Free;
  37.   CBC := Buffer;
  38.   WriteLn('KEY        : ', Key             , ' (', Length(Key) , ')');
  39.   WriteLn('IV         : ', IV              , ' (', Length(IV)  , ')');
  40.   WriteLn('DATA       : ', Data            , ' (', Length(Data), ')');
  41.   WriteLn;  
  42.   WriteLn('ECB        : ', BinStr2Hex(ECB) , ' (', Length(ECB) , ')');
  43.   WriteLn('CBC        : ', BinStr2Hex(CBC) , ' (', Length(CBC) , ')');
  44.   WriteLn;  
  45.   ECB := Base64EncodeStr(ECB);
  46.   WriteLn('ECB_BASE64 : ', ECB             , ' (', Length(ECB) , ')');
  47.   CBC := Base64EncodeStr(CBC);
  48.   WriteLn('CBC_BASE64 : ', CBC             , ' (', Length(CBC) , ')');
  49. end.


php version:
Code: PHP  [Select]
  1. <?php
  2.   $DATA = "Hello World_____";
  3.   $KEY  = "1234567890______";
  4.   $IV   = "______1234567890";
  5.   $ECB = mcrypt_ecb(MCRYPT_RIJNDAEL_128,$KEY,$DATA,MCRYPT_ENCRYPT,$IV);
  6.   $CBC = mcrypt_cbc(MCRYPT_RIJNDAEL_128,$KEY,$DATA,MCRYPT_ENCRYPT,$IV);
  7.   echo "KEY        : ".$KEY." (".strlen($KEY).")"."\n";
  8.   echo "IV         : ".$IV." (".strlen($IV).")"."\n";
  9.   echo "DATA       : ".$DATA." (".strlen($DATA).")"."\n";
  10.   echo "\n";
  11.   echo "ECB        : ".bin2hex($ECB)." (".strlen($ECB).")"."\n";
  12.   echo "CBC        : ".bin2hex($CBC)." (".strlen($CBC).")"."\n";
  13.   echo "\n";
  14.   $ECB = base64_encode($ECB);
  15.   echo "ECB_BASE64 : ".$ECB." (".strlen($ECB).")"."\n";
  16.   $CBC = base64_encode($CBC);
  17.   echo "CBC_BASE64 : ".$CBC." (".strlen($CBC).")"."\n";
  18. ?>


Pascal output
Code: [Select]
KEY        : 1234567890______ (16)
IV         : ______1234567890 (16)
DATA       : Hello World_____ (16)

ECB        : aeb97e57a968e70c22bdfc335591b9c6 (16)
CBC        : 8d0d7e91e4d0cdad7a77727c96a124f5 (16)

ECB_BASE64 : rrl+V6lo5wwivfwzVZG5xg== (24)
CBC_BASE64 : jQ1+keTQza16d3J8lqEk9Q== (24)

php output
Code: [Select]
KEY        : 1234567890______ (16)
IV         : ______1234567890 (16)
DATA       : Hello World_____ (16)

ECB        : aeb97e57a968e70c22bdfc335591b9c6 (16)
CBC        : 8d0d7e91e4d0cdad7a77727c96a124f5 (16)

ECB_BASE64 : rrl+V6lo5wwivfwzVZG5xg== (24)
CBC_BASE64 : jQ1+keTQza16d3J8lqEk9Q== (24)

So, once you have a solid base then you can start thinking about messing around with data that doesn't match up the requirements, therefor needs (zero-)padding, and requires fixing up the mess that base64_encode/decode functions made out of things.

And we haven't even started actually sending/receiving data over the interwebs or hashing a key... oh, you want to use ssl as well you said ? :D

Therefor it would be recommended to build on top of what you know is working and take small steps from there to see where things might go amiss. It might perhaps sound tedious to do but that is the only way you are able to figure out where exactly things go wrong (if they go wrong) and be able to 'fix' in  case it requires fixing.

edit: php code and output matching
« Last Edit: April 28, 2017, 03:32:16 pm by molly »