Igobolondo lenuzi phezu kwe-ICMP

Igobolondo lenuzi phezu kwe-ICMP

TL; DR: Ngibhala imojula ye-kernel ezofunda imiyalo evela ku-ICMP payload futhi iyenze kuseva noma ngabe i-SSH yakho iphahlazeka. Kwabantula isineke kakhulu, yonke ikhodi ithi github.

Ukuqapha Abahleli bezinhlelo ze-C abanolwazi basengozini yokukhala izinyembezi zegazi! Kungenzeka ngibe nephutha kumagama, kodwa noma yikuphi ukugxeka kwamukelekile. Okuthunyelwe kuhloselwe labo abanombono onzima kakhulu we-C futhi abafuna ukubheka ngaphakathi kwe-Linux.

Emibhalweni yami yokuqala isihloko kukhulunywe ngeSoftEther VPN, engakwazi ukulingisa ezinye izivumelwano "ezivamile", ikakhulukazi i-HTTPS, i-ICMP kanye ne-DNS. Ngingacabanga nje eyokuqala yazo esebenzayo, njengoba ngijwayelene kakhulu ne-HTTP(S), futhi kwadingeka ngifunde ukushunela phezu kwe-ICMP ne-DNS.

Igobolondo lenuzi phezu kwe-ICMP

Yebo, ngo-2020 ngafunda ukuthi ungafaka umthwalo okhokhelwayo ngokungafanele kumaphakethe e-ICMP. Kodwa kungcono sekwephuzile kunanini ngaphambili! Futhi njengoba kukhona okungenziwa ngakho, kufanele kwenziwe. Njengoba empilweni yami yansuku zonke ngivame ukusebenzisa umugqa womyalo, kufaka phakathi nge-SSH, umqondo wegobolondo le-ICMP wafika engqondweni yami kuqala. Futhi ukuze ngihlanganise ibhingo eliphelele le-bullshield, nginqume ukuyibhala njengemojula ye-Linux ngolimi enginombono onzima ngalo. Igobolondo elinjalo ngeke libonakale ohlwini lwezinqubo, ungalilayisha ku-kernel futhi ngeke libe sesistimu yefayela, ngeke ubone noma yini esolisayo ohlwini lwamachweba okulalela. Ngokwamandla ayo, lena i-rootkit egcwele, kodwa ngithemba ukuyithuthukisa futhi ngiyisebenzise njengegobolondo lokugcina lapho Isilinganiso Somthwalo siphezulu kakhulu ukuthi ungangena nge-SSH futhi usebenzise okungenani. echo i > /proc/sysrq-triggerukubuyisela ukufinyelela ngaphandle kokuqalisa kabusha.

Sithatha umhleli wombhalo, amakhono ayisisekelo wokuhlela ku-Python no-C, i-Google kanye okubonakalayo okungenandaba nokukufaka ngaphansi kommese uma yonke into iphuka (kuyakhetheka - i-VirtualBox/KVM/etc yendawo) bese sihamba!

Ingxenye yeklayenti

Kimina kwabonakala sengathi ingxenye yeklayenti kuzofanele ngibhale umbhalo onemigqa engaba ngu-80, kodwa kwakukhona abantu abanomusa abangenzela kona. wonke umsebenzi. Ikhodi ivele yaba lula ngokungalindelekile, ingena emigqeni eyi-10 ebalulekile:

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

Umbhalo uthatha izimpikiswano ezimbili, ikheli kanye nomthwalo okhokhelwayo. Ngaphambi kokuthumela, umthwalo okhokhelwayo wandulelwa ukhiye run:, sizoyidinga ukuze singafaki amaphakheji anomthwalo okhokhelwayo ngokungahleliwe.

I-kernel idinga amalungelo okwenza amaphakheji, ngakho-ke iskripthi kuzodingeka sisetshenziswe njengomsebenzisi omkhulu. Ungakhohlwa ukunikeza izimvume zokusebenza futhi ufake i-scapy ngokwayo. I-Debian inephakheji ebizwa ngokuthi python3-scapy. Manje ungabheka ukuthi konke kusebenza kanjani.

Ukuqalisa nokukhipha umyalo
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!

Lokhu kubonakala kumuntu ohogelayo
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

Umthwalo okhokhelwayo ephaketheni lokuphendula awushintshi.

Imojula ye-Kernel

Ukwakha emshinini we-Debian virtual uzodinga okungenani make ΠΈ linux-headers-amd64, okunye kuzofika ngendlela yokuncika. Ngeke nginikeze yonke ikhodi esihlokweni; ungayifaka ku-Github.

Ukusethwa kwehuku

Okokuqala, sidinga imisebenzi emibili ukuze silayishe imojuli futhi siyikhiphe. Umsebenzi wokukhipha awudingeki, kodwa-ke rmmod ngeke isebenze; ​​imojuli izothululwa kuphela uma icishiwe.

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

Kwenzekani lapha:

  1. Amafayela amabili anhlokweni ayadonselwa ukuze kusetshenziswe imojuli ngokwayo kanye nesihlungi se-net.
  2. Yonke imisebenzi ihamba ngesihlungi se-net, ungabeka izingwegwe kuso. Ukuze wenze lokhu, udinga ukumemezela isakhiwo lapho i-hook izolungiswa khona. Okubaluleke kakhulu ukucacisa umsebenzi ozokwenziwa njengehhuku: nfho.hook = icmp_cmd_executor; Ngizofika emsebenzini ngokwawo kamuva.
    Bese ngibeka isikhathi sokucubungula sephakheji: NF_INET_PRE_ROUTING icacisa ukucubungula iphakheji uma livela okokuqala ku-kernel. Ingasetshenziswa NF_INET_POST_ROUTING ukucubungula iphakethe njengoba liphuma ku-kernel.
    Ngisethe isihlungi ku-IPv4: nfho.pf = PF_INET;.
    Ngibeka ihuku lami phambili kakhulu: nfho.priority = NF_IP_PRI_FIRST;
    Futhi ngibhalisa ukwakheka kwedatha njengehhuku langempela: nf_register_net_hook(&init_net, &nfho);
  3. Umsebenzi wokugcina ususa ingwegwe.
  4. Ilayisensi ikhonjiswe ngokucacile ukuze umdidiyeli angakhonondi.
  5. Imisebenzi module_init() ΠΈ module_exit() setha eminye imisebenzi ukuze uqalise futhi unqamule imojuli.

Ukubuyisa umthwalo

Manje sidinga ukukhipha umthwalo okhokhelwayo, lokhu kube umsebenzi onzima kakhulu. I-kernel ayinayo imisebenzi eyakhelwe ngaphakathi yokusebenza ngokulayishwayo okukhokhelwayo; ungakwazi ukuhlaziya kuphela izihloko zamaphrothokholi asezingeni eliphezulu.

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

Kwenzakalani:

  1. Bekufanele ngifake amafayela esihloko engeziwe, kulokhu ukuze ngisebenzise izihloko ze-IP ne-ICMP.
  2. Ngisetha ubude bomugqa omkhulu: #define MAX_CMD_LEN 1976. Kungani ngempela lokhu? Ngoba umdidiyeli ukhononda ngakho! Sebevele baphakamise kimi ukuthi ngidinga ukuqonda isitaki nenqwaba, ngolunye usuku ngizokwenza lokhu futhi mhlawumbe ngilungise ikhodi. Ngokushesha ngisetha umugqa ozoqukatha umyalo: char cmd_string[MAX_CMD_LEN];. Kufanele ibonakale kuyo yonke imisebenzi; ngizokhuluma ngalokhu kabanzi esigabeni sesi-9.
  3. Manje sidinga ukuqalisa (struct work_struct my_work;) hlela bese uyixhuma nomunye umsebenzi (DECLARE_WORK(my_work, work_handler);). Ngizophinde ngikhulume ngokuthi kungani lokhu kudingekile endimeni yesishiyagalolunye.
  4. Manje ngimemezela umsebenzi, ozoba yihhuku. Uhlobo nezimpikiswano ezamukelwe zinqunywa isihlungi se-netfilter, esikuthakaselayo kuphela skb. Lesi isilondolozi sesokhethi, isakhiwo sedatha esiyisisekelo esiqukethe lonke ulwazi olutholakalayo mayelana nephakethe.
  5. Ukuze umsebenzi usebenze, uzodinga izakhiwo ezimbili neziguquguqukayo ezimbalwa, kuhlanganise neziphindaphinda ezimbili.
      struct iphdr *iph;
      struct icmphdr *icmph;
    
      unsigned char *user_data;
      unsigned char *tail;
      unsigned char *i;
      int j = 0;
  6. Singaqala nge-logic. Ukuze imojuli isebenze, awekho amaphakethe ngaphandle kwe-ICMP Echo adingekayo, ngakho-ke sihlaziya isigcinalwazi sisebenzisa imisebenzi eyakhelwe ngaphakathi bese silahla wonke amaphakethe angewona awe-ICMP nangewona awe-Echo. Buyela NF_ACCEPT kusho ukwamukelwa kwephakheji, kodwa ungakwazi futhi ukulahla amaphakheji 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;
      }

    Angikahloli ukuthi kuzokwenzekani ngaphandle kokuhlola izihloko ze-IP. Ulwazi lwami oluncane ngo-C lungitshela ukuthi ngaphandle kokuhlolwa okwengeziwe, into embi izokwenzeka. Ngingajabula uma ungangiyekisa kulokhu!

  7. Manje njengoba iphakheji iwuhlobo lwangempela oludingayo, ungakwazi ukukhipha idatha. Ngaphandle komsebenzi owakhelwe ngaphakathi, kufanele uqale uthole i-pointer ekuqaleni komthwalo wokukhokha. Lokhu kwenziwa endaweni eyodwa, udinga ukuthatha i-pointer ekuqaleni kwesihloko se-ICMP bese usihambisa kusayizi wale nhlokweni. Yonke into isebenzisa isakhiwo icmph: user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
    Isiphetho sikanhlokweni kufanele sifane nesiphetho somthwalo okhokhelwayo skb, ngakho-ke siyithola sisebenzisa izindlela zenuzi kusuka esakhiweni esihambisanayo: tail = skb_tail_pointer(skb);.

    Igobolondo lenuzi phezu kwe-ICMP

    Isithombe sebiwe kusuka lapha, ungafunda kabanzi mayelana nebhafa yesokhethi.

  8. Uma usunezinkomba eziya ekuqaleni nasekupheleni, ungakwazi ukukopisha idatha kuyunithi yezinhlamvu cmd_string, sihlole ukuthi sikhona yini isiqalo run: futhi, noma ulahle iphakheji uma lingekho, noma ubhale kabusha umugqa futhi, ukhiphe lesi siqalo.
  9. Yilokho, manje ungashayela esinye isibambi: schedule_work(&my_work);. Njengoba kungeke kwenzeke ukudlulisa ipharamitha ocingweni olunjalo, umugqa onomyalo kufanele ube omhlaba wonke. schedule_work() izobeka umsebenzi ohlotshaniswa nesakhiwo esidlulisiwe kumugqa ojwayelekile wesihleli somsebenzi bese iqedela, okukuvumela ukuthi ungalindi ukuthi umyalo uqedele. Lokhu kuyadingeka ngoba ihuku kufanele lisheshe kakhulu. Uma kungenjalo, ukukhetha kwakho ukuthi akukho lutho oluzoqala noma uzothola ukwethuka kwe-kernel. Ukubambezeleka kufana nokufa!
  10. Yilokho kuphela, ungamukela iphakheji ngembuyiselo ehambisanayo.

Ukushayela uhlelo endaweni yomsebenzisi

Lo msebenzi yiwo oqondakala kakhulu. Igama layo laqanjwa DECLARE_WORK(), uhlobo nezimpikiswano ezamukelekayo azithakazelisi. Sithatha umugqa ngomyalo futhi siwudlulisele ngokuphelele kugobolondo. Makabhekane nokwahlukanisa, ukucinga ama-binaries nakho konke okunye.

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. Setha ama-agumenti kuyunithi yezinhlamvu argv[]. Ngizothatha ngokuthi wonke umuntu uyazi ukuthi izinhlelo empeleni zenziwa ngale ndlela, hhayi njengomugqa oqhubekayo onezikhala.
  2. Setha okuguquguqukayo kwendawo. Ngifake i-PATH kuphela enesethi encane yezindlela, ngethemba ukuthi zonke zase zihlanganisiwe /bin с /usr/bin и /sbin с /usr/sbin. Ezinye izindlela azivamile ukuba nendaba ekusebenzeni.
  3. Kwenziwe, asikwenze! Umsebenzi we-Kernel call_usermodehelper() uyakwamukela ukungena. indlela eya kunambambili, uhlu lwama-agumenti, uhlu lwezinto eziguquguqukayo zendawo. Lapha futhi ngicabanga ukuthi wonke umuntu uyayiqonda incazelo yokudlulisa indlela eya efayeleni elisebenzisekayo njengengxabano ehlukile, kodwa ungabuza. I-agumenti yokugcina icacisa ukuthi kumele kulindwe yini ukuthi inqubo iphele (UMH_WAIT_PROC), ukuqala kwenqubo (UMH_WAIT_EXEC) noma ungalindi nhlobo (UMH_NO_WAIT). Ingabe kukhona okunye UMH_KILLABLE, angizange ngiyibheke.

Umhlangano

Ukuhlanganiswa kwamamojula we-kernel kwenziwa ngohlaka lwe-kernel make-framework. Ibiziwe make ngaphakathi kwenkomba ekhethekile eboshelwe enguqulweni ye-kernel (echazwe lapha: KERNELDIR:=/lib/modules/$(shell uname -r)/build), futhi indawo yemojuli idluliselwe kokuguquguqukayo M ezingxabanweni. I-icmpshell.ko nezinhloso ezihlanzekile zisebenzisa lolu hlaka ngokuphelele. IN obj-m ibonisa ifayela lento elizoguqulwa libe imojuli. I-syntax eyenza kabusha main.o Π² icmpshell.o (icmpshell-objs = main.o) akubukeki kunengqondo kakhulu kimi, 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

Siqoqa: make. Iyalayisha: insmod icmpshell.ko. Uqedile, ungabheka: sudo ./send.py 45.11.26.232 "date > /tmp/test". Uma unefayela emshinini wakho /tmp/test futhi iqukethe usuku isicelo esithunyelwe ngalo, okusho ukuthi wenze yonke into kahle futhi ngenze konke ngendlela efanele.

isiphetho

Okuhlangenwe nakho kwami ​​kokuqala ngentuthuko yenuzi kwaba lula kakhulu kunalokho engangikulindele. Ngisho nangaphandle kokuhlangenwe nakho okuthuthukayo ku-C, okugxile kumacebo omhlanganisi kanye nemiphumela ye-Google, ngakwazi ukubhala imodyuli yokusebenza futhi ngizizwe njenge-kernel hacker, futhi ngesikhathi esifanayo ingane yombhalo. Ngaphezu kwalokho, ngaya esiteshini se-Kernel Newbies, lapho ngatshelwa khona ukuthi ngisebenzise schedule_work() esikhundleni sokufona call_usermodehelper() ngaphakathi kwehhuku uqobo futhi wamphoxa, ngokufanelekile esola umkhonyovu. Imigqa eyikhulu yekhodi ingibize cishe iviki lokuthuthuka ngesikhathi sami samahhala. Okuhlangenwe nakho okuyimpumelelo okucekele phansi inganekwane yami yomuntu siqu mayelana nobunkimbinkimbi obumangalisayo bokuthuthukiswa kwesistimu.

Uma othile evuma ukwenza isibuyekezo sekhodi ku-Github, ngizobonga. Ngiqinisekile ukuthi ngenze amaphutha amaningi ayisiphukuphuku, ikakhulukazi lapho ngisebenza ngezintambo.

Igobolondo lenuzi phezu kwe-ICMP

Source: www.habr.com

Engeza amazwana