Ikarahun iparun lori ICMP

Ikarahun iparun lori ICMP

TL; DR: Mo n kọ module ekuro kan ti yoo ka awọn aṣẹ lati inu isanwo ICMP ati ṣiṣe wọn lori olupin paapaa ti SSH rẹ ba kọlu. Fun awọn julọ ikanju, gbogbo awọn koodu ti wa ni github.

Išọra! Awọn oluṣeto C ti o ni iriri ni ewu ti nwaye sinu omije ẹjẹ! Mo le paapaa jẹ aṣiṣe ninu ọrọ-ọrọ, ṣugbọn eyikeyi ibawi jẹ itẹwọgba. Ifiweranṣẹ naa jẹ ipinnu fun awọn ti o ni imọran ti o ni inira ti siseto C ati pe o fẹ lati wo inu inu Linux.

Ninu awọn asọye si akọkọ mi article mẹnuba SoftEther VPN, eyiti o le farawe diẹ ninu awọn ilana “deede”, ni pataki HTTPS, ICMP ati paapaa DNS. Mo le foju inu wo nikan ni akọkọ ti wọn n ṣiṣẹ, nitori Mo mọ HTTP (S) pupọ, ati pe Mo ni lati kọ ẹkọ tunneling lori ICMP ati DNS.

Ikarahun iparun lori ICMP

Bẹẹni, Mo kọ ẹkọ ni ọdun 2020 pe o le fi fifuye isanwo lainidii sinu awọn apo-iwe ICMP. Ṣugbọn dara pẹ ju lailai! Ati pe niwon ohun kan le ṣee ṣe nipa rẹ, lẹhinna o nilo lati ṣe. Niwọn bi ninu igbesi aye mi ojoojumọ Mo nigbagbogbo lo laini aṣẹ, pẹlu nipasẹ SSH, imọran ti ikarahun ICMP kan wa si ọkan mi ni akọkọ. Ati pe lati le ṣajọpọ bingo bullshield pipe, Mo pinnu lati kọ bi module Linux ni ede ti Mo ni imọran ti o ni inira ti. Iru ikarahun kan kii yoo han ninu atokọ awọn ilana, o le gbe e sinu ekuro ati kii yoo wa lori eto faili, iwọ kii yoo rii ohunkohun ifura ninu atokọ ti awọn ebute gbigbọ. Ni awọn ofin ti awọn agbara rẹ, eyi jẹ rootkit ti o ni kikun, ṣugbọn Mo nireti lati mu dara sii ki o lo bi ikarahun ti ibi-afẹde ti o kẹhin nigbati Apapọ fifuye ga ju lati wọle nipasẹ SSH ati ṣiṣe ni o kere ju. echo i > /proc/sysrq-triggerlati mu pada wiwọle lai atunbere.

A ya a ọrọ olootu, ipilẹ siseto ogbon ni Python ati C, Google ati foju eyiti o ko ni lokan fifi labẹ ọbẹ ti ohun gbogbo ba fọ (aṣayan - agbegbe VirtualBox / KVM / ati bẹbẹ lọ) ati jẹ ki a lọ!

Apa onibara

O dabi fun mi pe fun apakan alabara Emi yoo ni lati kọ iwe afọwọkọ kan pẹlu awọn laini 80, ṣugbọn awọn eniyan oninuure wa ti wọn ṣe fun mi. gbogbo ise. Koodu naa yipada lati rọrun lairotẹlẹ, ni ibamu si awọn laini pataki 10:

import sys
from scapy.all import sr1, IP, ICMP

if len(sys.argv) < 3:
    print('Usage: {} IP "command"'.format(sys.argv[0]))
    exit(0)

p = sr1(IP(dst=sys.argv[1])/ICMP()/"run:{}".format(sys.argv[2]))
if p:
    p.show()

Iwe afọwọkọ naa gba awọn ariyanjiyan meji, adirẹsi ati fifuye isanwo kan. Ṣaaju fifiranṣẹ, fifuye isanwo jẹ ṣaju nipasẹ bọtini kan run:, a yoo nilo rẹ lati yọkuro awọn idii pẹlu awọn ẹru isanwo laileto.

Ekuro nilo awọn anfani si awọn idii iṣẹ ọwọ, nitorinaa iwe afọwọkọ yoo ni lati ṣiṣẹ bi superuser. Maṣe gbagbe lati fun awọn igbanilaaye ipaniyan ati fi sapy sori ẹrọ funrararẹ. Debian ni package ti a pe python3-scapy. Bayi o le ṣayẹwo bi gbogbo rẹ ṣe n ṣiṣẹ.

Ṣiṣe ati ṣiṣejade aṣẹ naa
morq@laptop:~/icmpshell$ sudo ./send.py 45.11.26.232 "Hello, world!"
Begin emission:
.Finished sending 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 45
id = 17218
flags =
frag = 0
ttl = 58
proto = icmp
chksum = 0x3403
src = 45.11.26.232
dst = 192.168.0.240
options
###[ ICMP ]###
type = echo-reply
code = 0
chksum = 0xde03
id = 0x0
seq = 0x0
###[ Raw ]###
load = 'run:Hello, world!

Eyi ni ohun ti o dabi ninu sniffer
morq@laptop:~/icmpshell$ sudo tshark -i wlp1s0 -O icmp -f "icmp and host 45.11.26.232"
Running as user "root" and group "root". This could be dangerous.
Capturing on 'wlp1s0'
Frame 1: 59 bytes on wire (472 bits), 59 bytes captured (472 bits) on interface wlp1s0, id 0
Internet Protocol Version 4, Src: 192.168.0.240, Dst: 45.11.26.232
Internet Control Message Protocol
Type: 8 (Echo (ping) request)
Code: 0
Checksum: 0xd603 [correct] [Checksum Status: Good] Identifier (BE): 0 (0x0000)
Identifier (LE): 0 (0x0000)
Sequence number (BE): 0 (0x0000)
Sequence number (LE): 0 (0x0000)
Data (17 bytes)

0000 72 75 6e 3a 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 run:Hello, world
0010 21 !
Data: 72756e3a48656c6c6f2c20776f726c6421
[Length: 17]

Frame 2: 59 bytes on wire (472 bits), 59 bytes captured (472 bits) on interface wlp1s0, id 0
Internet Protocol Version 4, Src: 45.11.26.232, Dst: 192.168.0.240
Internet Control Message Protocol
Type: 0 (Echo (ping) reply)
Code: 0
Checksum: 0xde03 [correct] [Checksum Status: Good] Identifier (BE): 0 (0x0000)
Identifier (LE): 0 (0x0000)
Sequence number (BE): 0 (0x0000)
Sequence number (LE): 0 (0x0000)
[Request frame: 1] [Response time: 19.094 ms] Data (17 bytes)

0000 72 75 6e 3a 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 run:Hello, world
0010 21 !
Data: 72756e3a48656c6c6f2c20776f726c6421
[Length: 17]

^C2 packets captured

Isanwo ti o wa ninu package idahun ko yipada.

Ekuro module

Lati kọ sinu ẹrọ foju Debian iwọ yoo nilo o kere ju make и linux-headers-amd64, awọn iyokù yoo wa ni awọn fọọmu ti dependencies. Emi kii yoo pese gbogbo koodu ninu nkan naa o le ṣe oniye lori Github.

Kio iṣeto ni

Lati bẹrẹ pẹlu, a nilo meji awọn iṣẹ ni ibere lati fifuye awọn module ati lati unload o. Awọn iṣẹ fun unloading ni ko ti beere, sugbon ki o si rmmod o yoo ko sise;

#include <linux/module.h>
#include <linux/netfilter_ipv4.h>

static struct nf_hook_ops nfho;

static int __init startup(void)
{
  nfho.hook = icmp_cmd_executor;
  nfho.hooknum = NF_INET_PRE_ROUTING;
  nfho.pf = PF_INET;
  nfho.priority = NF_IP_PRI_FIRST;
  nf_register_net_hook(&init_net, &nfho);
  return 0;
}

static void __exit cleanup(void)
{
  nf_unregister_net_hook(&init_net, &nfho);
}

MODULE_LICENSE("GPL");
module_init(startup);
module_exit(cleanup);

Kini n ṣẹlẹ nibi:

  1. Awọn faili akọsori meji ni a fa sinu lati ṣe afọwọyi module funrararẹ ati netfilter.
  2. Gbogbo awọn iṣẹ ṣiṣe lọ nipasẹ netfilter, o le ṣeto awọn kio ninu rẹ. Lati ṣe eyi, o nilo lati sọ eto ninu eyiti kio yoo wa ni tunto. Ohun pataki julọ ni lati pato iṣẹ ti yoo ṣe bi kio kan: nfho.hook = icmp_cmd_executor; Emi yoo gba iṣẹ naa funrararẹ nigbamii.
    Lẹhinna Mo ṣeto akoko sisẹ fun package: NF_INET_PRE_ROUTING ni pato lati ṣe ilana package nigbati akọkọ ba han ninu ekuro. Le ṣee lo NF_INET_POST_ROUTING lati ṣe ilana apo-iwe naa bi o ti jade kuro ninu ekuro.
    Mo ṣeto àlẹmọ si IPv4: nfho.pf = PF_INET;.
    Mo fun kio mi ni pataki julọ: nfho.priority = NF_IP_PRI_FIRST;
    Ati pe Mo forukọsilẹ eto data bi kio gangan: nf_register_net_hook(&init_net, &nfho);
  3. Ik iṣẹ yọ awọn kio.
  4. Iwe-aṣẹ naa jẹ itọkasi kedere ki olupilẹṣẹ ko ni kerora.
  5. Awọn iṣẹ module_init() и module_exit() ṣeto awọn iṣẹ miiran lati bẹrẹ ati fopin si module.

Gbigba owo sisan pada

Bayi a nilo lati yọ owo sisan kuro, eyi ti jade lati jẹ iṣẹ ti o nira julọ. Ekuro naa ko ni awọn iṣẹ ti a ṣe sinu rẹ fun ṣiṣẹ pẹlu awọn ẹru isanwo;

#include <linux/ip.h>
#include <linux/icmp.h>

#define MAX_CMD_LEN 1976

char cmd_string[MAX_CMD_LEN];

struct work_struct my_work;

DECLARE_WORK(my_work, work_handler);

static unsigned int icmp_cmd_executor(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
  struct iphdr *iph;
  struct icmphdr *icmph;

  unsigned char *user_data;
  unsigned char *tail;
  unsigned char *i;
  int j = 0;

  iph = ip_hdr(skb);
  icmph = icmp_hdr(skb);

  if (iph->protocol != IPPROTO_ICMP) {
    return NF_ACCEPT;
  }
  if (icmph->type != ICMP_ECHO) {
    return NF_ACCEPT;
  }

  user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
  tail = skb_tail_pointer(skb);

  j = 0;
  for (i = user_data; i != tail; ++i) {
    char c = *(char *)i;

    cmd_string[j] = c;

    j++;

    if (c == '')
      break;

    if (j == MAX_CMD_LEN) {
      cmd_string[j] = '';
      break;
    }

  }

  if (strncmp(cmd_string, "run:", 4) != 0) {
    return NF_ACCEPT;
  } else {
    for (j = 0; j <= sizeof(cmd_string)/sizeof(cmd_string[0])-4; j++) {
      cmd_string[j] = cmd_string[j+4];
      if (cmd_string[j] == '')
	break;
    }
  }

  schedule_work(&my_work);

  return NF_ACCEPT;
}

Kilo n ṣẹlẹ:

  1. Mo ni lati ni afikun awọn faili akọsori, ni akoko yii lati ṣe afọwọyi IP ati awọn akọle ICMP.
  2. Mo ṣeto ipari ila ti o pọju: #define MAX_CMD_LEN 1976. Kini idi gangan eyi? Nitori awọn alakojo kerora nipa o! Wọn ti daba fun mi tẹlẹ pe Mo nilo lati ni oye akopọ ati okiti, ni ọjọ kan Emi yoo dajudaju ṣe eyi ati boya paapaa ṣe atunṣe koodu naa. Mo ṣeto laini lẹsẹkẹsẹ ti yoo ni aṣẹ naa: char cmd_string[MAX_CMD_LEN];. O yẹ ki o han ni gbogbo awọn iṣẹ;
  3. Bayi a nilo lati bẹrẹ (struct work_struct my_work;) eto ati sopọ pẹlu iṣẹ miiran (DECLARE_WORK(my_work, work_handler);). Emi yoo tun sọrọ nipa idi ti eyi ṣe pataki ni paragirafi kẹsan.
  4. Bayi Mo kede iṣẹ kan, eyiti yoo jẹ kio kan. Iru ati awọn ariyanjiyan ti o gba ni aṣẹ nipasẹ netfilter, a nifẹ si nikan skb. Eyi jẹ ifipamọ iho, ipilẹ data ipilẹ ti o ni gbogbo alaye ti o wa nipa soso kan ninu.
  5. Fun iṣẹ naa lati ṣiṣẹ, iwọ yoo nilo awọn ẹya meji ati ọpọlọpọ awọn oniyipada, pẹlu awọn iterators meji.
      struct iphdr *iph;
      struct icmphdr *icmph;
    
      unsigned char *user_data;
      unsigned char *tail;
      unsigned char *i;
      int j = 0;
  6. A le bẹrẹ pẹlu ọgbọn. Fun module naa lati ṣiṣẹ, ko si awọn apo-iwe miiran ju ICMP Echo ni a nilo, nitorinaa a ṣe itupalẹ ifipamọ nipa lilo awọn iṣẹ ti a ṣe sinu ati jabọ gbogbo awọn apo-iwe ti kii ṣe ICMP ati ti kii-Echo. Pada NF_ACCEPT tumo si gbigba ti awọn package, sugbon o tun le ju silẹ jo nipa a pada NF_DROP.
      iph = ip_hdr(skb);
      icmph = icmp_hdr(skb);
    
      if (iph->protocol != IPPROTO_ICMP) {
        return NF_ACCEPT;
      }
      if (icmph->type != ICMP_ECHO) {
        return NF_ACCEPT;
      }

    Emi ko ṣe idanwo ohun ti yoo ṣẹlẹ laisi ṣayẹwo awọn akọle IP. Imọ kekere mi ti C sọ fun mi pe laisi awọn sọwedowo afikun, nkan ti o buruju yoo ṣẹlẹ. Inu mi yoo dun ti o ba yi mi pada si eyi!

  7. Bayi wipe package jẹ ti awọn gangan iru ti o nilo, o le jade awọn data. Laisi iṣẹ ti a ṣe sinu, o ni akọkọ lati gba itọka si ibẹrẹ ti fifuye isanwo naa. Eyi ni a ṣe ni aaye kan, o nilo lati mu itọka si ibẹrẹ ti akọsori ICMP ki o gbe lọ si iwọn ti akọsori yii. Ohun gbogbo nlo ilana icmph: user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
    Ipari akọsori gbọdọ baramu opin fifuye isanwo ni skb, nitorinaa a gba ni lilo awọn ọna iparun lati eto ti o baamu: tail = skb_tail_pointer(skb);.

    Ikarahun iparun lori ICMP

    A ti ji aworan naa lati ibi, o le ka diẹ ẹ sii nipa ifipamọ iho.

  8. Ni kete ti o ba ni awọn itọka si ibẹrẹ ati ipari, o le daakọ data naa sinu okun kan cmd_string, ṣayẹwo fun wiwa ìpele kan run: ati, boya danu package ti o ba ti sonu, tabi tun ila lẹẹkansi, yọ yi ìpele.
  9. Iyẹn ni, ni bayi o le pe olutọju miiran: schedule_work(&my_work);. Niwọn igba ti ko ṣee ṣe lati kọja paramita kan si iru ipe kan, laini pẹlu aṣẹ gbọdọ jẹ agbaye. schedule_work() yoo gbe iṣẹ ti o ni nkan ṣe pẹlu eto ti o kọja sinu isinyi gbogbogbo ti oluṣeto iṣẹ ati pari, gbigba ọ laaye lati ma duro fun aṣẹ lati pari. Eyi jẹ pataki nitori kio gbọdọ yara pupọ. Bibẹẹkọ, yiyan rẹ ni pe ko si ohun ti yoo bẹrẹ tabi iwọ yoo gba ijaaya kernel. Idaduro dabi iku!
  10. Iyẹn ni, o le gba package pẹlu ipadabọ ti o baamu.

Npe eto ni aaye olumulo

Iṣẹ yii jẹ oye julọ. Orukọ rẹ ni a fun ni DECLARE_WORK(), Iru ati awọn ariyanjiyan ti o gba ko ni igbadun. A gba ila pẹlu aṣẹ naa ki o kọja patapata si ikarahun naa. Jẹ ki o ṣe pẹlu sisọtọ, wiwa awọn alakomeji ati ohun gbogbo miiran.

static void work_handler(struct work_struct * work)
{
  static char *argv[] = {"/bin/sh", "-c", cmd_string, NULL};
  static char *envp[] = {"PATH=/bin:/sbin", NULL};

  call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
}

  1. Ṣeto awọn ariyanjiyan si akojọpọ awọn okun argv[]. Emi yoo ro pe gbogbo eniyan mọ pe awọn eto ni a ṣe ni ọna yii, kii ṣe bi laini ilọsiwaju pẹlu awọn aye.
  2. Ṣeto awọn oniyipada ayika. Mo fi sii PATH nikan pẹlu eto ti o kere ju ti awọn ọna, nireti pe gbogbo wọn ti ni idapo tẹlẹ /bin с /usr/bin и /sbin с /usr/sbin. Awọn ọna miiran kii ṣe pataki ni iṣe.
  3. Ti pari, jẹ ki a ṣe! Ekuro iṣẹ call_usermodehelper() gba titẹsi. ona si alakomeji, orun ti ariyanjiyan, orun ti ayika oniyipada. Nibi Mo tun ro pe gbogbo eniyan loye itumọ ti gbigbe ọna si faili ti o ṣiṣẹ bi ariyanjiyan lọtọ, ṣugbọn o le beere. Awọn ariyanjiyan ti o kẹhin sọ boya lati duro fun ilana lati pari (UMH_WAIT_PROCIbẹrẹ ilana (UMH_WAIT_EXEC) tabi ko duro rara (UMH_NO_WAIT). Njẹ diẹ sii wa UMH_KILLABLE, Emi ko wo inu rẹ.

Apejọ

Apejọ ti awọn modulu ekuro ni a ṣe nipasẹ ilana ṣiṣe-ekuro. Ti a npe ni make inu itọsọna pataki kan ti a so si ẹya ekuro (ti a ṣalaye nibi: KERNELDIR:=/lib/modules/$(shell uname -r)/build), ati awọn ipo ti awọn module ti wa ni koja si awọn oniyipada M ninu awọn ariyanjiyan. Awọn icmpshell.ko ati awọn ibi-afẹde mimọ lo ilana yii patapata. IN obj-m tọkasi faili ohun ti yoo yipada sinu module. Sintasi ti o tun ṣe main.o в icmpshell.o (icmpshell-objs = main.o) ko dabi ọgbọn pupọ si mi, ṣugbọn bẹ bẹ.

KERNELDIR:=/lib/modules/$(shell uname -r)/build

obj-m = icmpshell.o
icmpshell-objs = main.o

all: icmpshell.ko

icmpshell.ko: main.c
make -C $(KERNELDIR) M=$(PWD) modules

clean:
make -C $(KERNELDIR) M=$(PWD) clean

A gba: make. Nkojọpọ: insmod icmpshell.ko. Ti pari, o le ṣayẹwo: sudo ./send.py 45.11.26.232 "date > /tmp/test". Ti o ba ni faili lori ẹrọ rẹ /tmp/test ati pe o ni ọjọ ti o ti firanṣẹ ibeere naa, eyiti o tumọ si pe o ṣe ohun gbogbo ti o tọ ati pe Mo ṣe ohun gbogbo daradara.

ipari

Iriri akọkọ mi pẹlu idagbasoke iparun jẹ rọrun pupọ ju Mo nireti lọ. Paapaa laisi iriri ti o ndagbasoke ni C, ni idojukọ lori awọn imọran alakojọ ati awọn abajade Google, Mo ni anfani lati kọ module iṣẹ kan ati rilara bi agbonaeburuwole kernel, ati ni akoko kanna ọmọ iwe afọwọkọ kan. Ni afikun, Mo lọ si ikanni Kernel Newbies, nibiti a ti sọ fun mi lati lo schedule_work() dipo pipe call_usermodehelper() inu awọn kio ara ati itiju rẹ, ti tọ suspecting a itanjẹ. Awọn laini koodu ọgọọgọrun jẹ idiyele mi nipa ọsẹ kan ti idagbasoke ni akoko ọfẹ mi. Iriri aṣeyọri ti o pa arosọ ti ara ẹni jẹ nipa idiju nla ti idagbasoke eto.

Ti ẹnikan ba gba lati ṣe atunyẹwo koodu lori Github, Emi yoo dupẹ. Mo ni idaniloju pe Mo ṣe ọpọlọpọ awọn aṣiṣe aṣiwere, paapaa nigbati o ba n ṣiṣẹ pẹlu awọn okun.

Ikarahun iparun lori ICMP

orisun: www.habr.com

Fi ọrọìwòye kun