ʻO ka pūpū nuklea ma luna o ICMP

ʻO ka pūpū nuklea ma luna o ICMP

Aku; DR: Ke kākau nei au i kahi module kernel e heluhelu i nā kauoha mai ka ICMP payload a hoʻokō iā lākou ma ka kikowaena inā paha e hāʻule kāu SSH. No ka poʻe hoʻomanawanui ʻole, pau ke code github.

Polokalamu Hiki i ka poʻe polokalamu polokalamu C ʻike ke pohā i ka waimaka o ke koko! Ua hewa paha wau i ka ʻōlelo, akā ʻoluʻolu ʻia nā ʻōlelo hoʻohewa. Hoʻolālā ʻia ka pou no ka poʻe i manaʻo koʻikoʻi loa o ka papahana C a makemake e nānā i loko o ka Linux.

Ma nā manaʻo i kaʻu mea mua 'ōlelo i ʻōlelo ʻia ʻo SoftEther VPN, hiki ke hoʻohālikelike i kekahi mau protocols "maʻamau", ʻo ia hoʻi ʻo HTTPS, ICMP a me DNS. Hiki iaʻu ke noʻonoʻo i ka mea mua o lākou e hana nei, no ka mea ua kamaʻāina loa wau iā HTTP(S), a pono wau e aʻo i ka tunneling ma luna o ICMP a me DNS.

ʻO ka pūpū nuklea ma luna o ICMP

ʻAe, ma 2020 ua aʻo wau hiki iā ʻoe ke hoʻokomo i kahi uku uku i loko o nā ʻeke ICMP. Akā ʻoi aku ka maikaʻi o ka lohi ma mua o ka ʻole! A no ka mea hiki ke hana ʻia kekahi mea, a laila pono e hana ʻia. No ka mea i koʻu ola i kēlā me kēia lā, hoʻohana pinepine wau i ka laina kauoha, me ka SSH, ua hele mua ka manaʻo o kahi pūpū ICMP i koʻu manaʻo. A i mea e hōʻuluʻulu ai i kahi bingo bullshield piha, ua hoʻoholo wau e kākau iā ia ma ke ʻano he module Linux ma kahi ʻōlelo aʻu i manaʻo ʻino wale ai. ʻAʻole ʻike ʻia kēlā pūpū i ka papa inoa o nā kaʻina hana, hiki iā ʻoe ke hoʻouka iā ia i loko o ka kernel a ʻaʻole ia ma ka ʻōnaehana faila, ʻaʻole ʻoe e ʻike i kekahi mea kānalua i ka papa inoa o nā awa hoʻolohe. Ma ke ʻano o kona hiki, he rootkit piha kēia, akā ke manaʻo nei au e hoʻomaikaʻi a hoʻohana iā ia ma ke ʻano he pūpū o ka hopena hope loa ke kiʻekiʻe loa ka Load Average e komo ma o SSH a hoʻokō i ka liʻiliʻi. echo i > /proc/sysrq-triggere hoʻihoʻi hou i ke komo me ka hoʻomaka ʻole.

Lawe mākou i ka mea hoʻoponopono kikokikona, nā mākau hoʻolālā kumu ma Python a me C, Google a makamaka ʻaʻole ʻoe e noʻonoʻo e waiho i lalo o ka pahi inā haki nā mea āpau (koho - VirtualBox / KVM / etc.) a e hele kāua!

ʻaoʻao mea kūʻai aku

Me he mea lā iaʻu no ka ʻāpana o ka mea kūʻai e pono iaʻu e kākau i kahi palapala me kahi o 80 mau laina, akā aia kekahi poʻe lokomaikaʻi i hana mai iaʻu. ka hana a pau. Ua maʻalahi ke code, kūpono i nā laina koʻikoʻi 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()

Lawe ka palapala i ʻelua manaʻo, kahi helu a me kahi uku. Ma mua o ka hoʻouna ʻana, e kau ʻia ka uku me kahi kī run:, pono mākou e hoʻokaʻawale i nā pūʻolo me nā uku uku.

Pono ka kernel i nā pono no ka hana ʻana i nā pūʻolo, no laila pono e holo ka palapala ma ke ʻano he superuser. Mai poina e hāʻawi i nā ʻae hoʻokō a hoʻokomo iā scapy iā ia iho. Loaʻa iā Debian kahi pūʻolo i kapa ʻia python3-scapy. I kēia manawa hiki iā ʻoe ke nānā pehea e hana ai nā mea a pau.

Holo a hoʻopuka i ke kauoha
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!

ʻO kēia ke ʻano o ka 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

ʻAʻole loli ka uku i loko o ka pūʻolo pane.

Kōmike kumu

No ke kūkulu ʻana i kahi mīkini virtual Debian pono ʻoe ma ka liʻiliʻi make и linux-headers-amd64, e hele mai ke koena ma ke ʻano o nā hilinaʻi. ʻAʻole wau e hāʻawi i ka code holoʻokoʻa i ka ʻatikala; hiki iā ʻoe ke clone ma Github.

Hoʻonohonoho Hook

No ka hoʻomaka ʻana, pono mākou i ʻelua mau hana no ka hoʻouka ʻana i ka module a me ka wehe ʻana iā ia. ʻAʻole koi ʻia ka hana no ka unloading, akā laila rmmod ʻAʻole ia e hana, e hoʻokuʻu wale ʻia ka module i ka wā e pio ai.

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

He aha ka hana ma ʻaneʻi:

  1. Ua huki ʻia ʻelua faila poʻomanaʻo e hoʻopololei i ka module ponoʻī a me ka netfilter.
  2. Hele nā ​​hana a pau ma kahi netfilter, hiki iā ʻoe ke kau i nā makau i loko. No ka hana ʻana i kēia, pono ʻoe e haʻi i ke ʻano e hoʻonohonoho ʻia ai ka makau. ʻO ka mea nui loa, ʻo ia ke kuhikuhi i ka hana e hoʻokō ʻia ma ke ʻano he makau: nfho.hook = icmp_cmd_executor; E hele au i ka hana pono'ī ma hope.
    A laila hoʻonoho wau i ka manawa hana no ka pūʻolo: NF_INET_PRE_ROUTING kuhikuhi i ka hana ʻana i ka pūʻolo i ka wā i ʻike mua ʻia ai i ka kernel. Hiki ke hoʻohana NF_INET_POST_ROUTING e hana i ka ʻeke i kona puka ʻana i ka kernel.
    Hoʻonoho au i ka kānana iā IPv4: nfho.pf = PF_INET;.
    Hāʻawi wau i kaʻu makau i ka mea nui loa: nfho.priority = NF_IP_PRI_FIRST;
    A hoʻopaʻa inoa wau i ka hoʻolālā ʻikepili e like me ka makau maoli: nf_register_net_hook(&init_net, &nfho);
  3. Hoʻopau ka hana hope i ka makau.
  4. Hōʻike maopopo ʻia ka laikini i ʻole e hoʻopiʻi ka mea hoʻopili.
  5. Nā hana module_init() и module_exit() hoʻonoho i nā hana ʻē aʻe e hoʻomaka a hoʻopau i ka module.

Ke kiʻi ʻana i ka ukana

I kēia manawa pono mākou e unuhi i ka uku, ua lilo kēia i mea paʻakikī loa. ʻAʻohe hana i kūkulu ʻia i loko o ka kernel no ka hana ʻana me nā uku; hiki iā ʻoe ke paʻi wale i nā poʻomanaʻo o nā protocol kiʻekiʻe.

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

He aha ka mea e hana nei:

  1. Pono wau e hoʻokomo i nā faila poʻomanaʻo hou, i kēia manawa e hoʻopunipuni i nā poʻomanaʻo IP a me ICMP.
  2. Hoʻonoho au i ka lōʻihi o ka laina: #define MAX_CMD_LEN 1976. No ke aha kēia? No ka mea, ke hoʻopiʻi nei ka mea hoʻopili iā ia! Ua ʻōlelo mua lākou iaʻu e pono iaʻu e hoʻomaopopo i ka ʻōpala a me ka puʻu, i kekahi lā e hana maoli wau i kēia a hoʻoponopono paha i ke code. Hoʻonohonoho koke wau i ka laina e loaʻa ai ke kauoha: char cmd_string[MAX_CMD_LEN];. Pono e ʻike ʻia i nā hana āpau; E kamaʻilio wau e pili ana i kēia i nā kikoʻī hou aku ma ka paukū 9.
  3. I kēia manawa pono mākou e hoʻomaka (struct work_struct my_work;) hale a hoʻohui me kekahi hana ʻē aʻe (DECLARE_WORK(my_work, work_handler);). E kamaʻilio pū wau no ke kumu e pono ai kēia ma ka paukū ʻeiwa.
  4. I kēia manawa ke haʻi aku nei au i kahi hana, ʻo ia ka makau. ʻO ke ʻano a me nā hoʻopaʻapaʻa i ʻae ʻia e ka netfilter, makemake wale mākou skb. ʻO kēia kahi hoʻopaʻa kumu, kahi hoʻonohonoho ʻikepili kumu i loaʻa nā ʻike āpau e pili ana i kahi ʻeke.
  5. No ka hana ʻana o ka hana, pono ʻoe i ʻelua mau hale a me nā ʻano like ʻole, me ʻelua mau iterator.
      struct iphdr *iph;
      struct icmphdr *icmph;
    
      unsigned char *user_data;
      unsigned char *tail;
      unsigned char *i;
      int j = 0;
  6. Hiki iā mākou ke hoʻomaka me ka loiloi. No ka hana ʻana o ka module, ʻaʻohe packets ʻē aʻe ma mua o ICMP Echo e pono ai, no laila mākou e hoʻokaʻawale i ka buffer me ka hoʻohana ʻana i nā hana i kūkulu ʻia a hoʻolei aku i nā ʻeke non-ICMP a me nā non-Echo. Hoʻi NF_ACCEPT 'o ia ho'i ka 'ae 'ana i ka pū'olo, akā hiki iā 'oe ke hā'ule i nā pū'olo ma ka ho'iho'i 'ana mai 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;
      }

    ʻAʻole au i hoʻāʻo i ka mea e hiki mai ana me ka nānā ʻole ʻana i nā poʻomanaʻo IP. ʻO kaʻu ʻike liʻiliʻi o C e haʻi mai iaʻu me ka ʻole o nā loiloi hou aʻe, e hiki mai ana kekahi mea weliweli. E hauʻoli wau inā ʻoe e hōʻole iaʻu i kēia!

  7. I kēia manawa ʻo ka pūʻolo o ke ʻano pololei āu e pono ai, hiki iā ʻoe ke unuhi i ka ʻikepili. Me ka ʻole o kahi hana i kūkulu ʻia, pono ʻoe e kiʻi i kahi kuhikuhi i ka hoʻomaka o ka uku. Hanaʻia kēia ma kahi hoʻokahi, ponoʻoe e lawe i ka pointer i ka hoʻomaka o ke poʻo ICMP a neʻe i ka nui o kēia poʻo. Hoʻohana nā mea a pau i ke ʻano icmph: user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
    Pono ka hopena o ke poʻo i ka hopena o ka uku uku skb, no laila, loaʻa iā mākou me ka hoʻohana ʻana i nā ala nuklea mai ka hale pili: tail = skb_tail_pointer(skb);.

    ʻO ka pūpū nuklea ma luna o ICMP

    Ua ʻaihue ʻia ke kiʻi mai kēia wahi, hiki iā ʻoe ke heluhelu hou aʻe e pili ana i ke kumu pale.

  8. Ke loaʻa iā ʻoe nā kuhikuhi i ka hoʻomaka a me ka hopena, hiki iā ʻoe ke kope i ka ʻikepili i kahi kaula cmd_string, e nānā no ka loaʻa ʻana o kahi prefix run: a, e hoʻolei i ka pūʻolo inā nalo, a i ʻole e kākau hou i ka laina, me ka wehe ʻana i kēia prefix.
  9. ʻO ia, i kēia manawa hiki iā ʻoe ke kāhea i kahi mea lawelawe ʻē aʻe: schedule_work(&my_work);. No ka mea ʻaʻole hiki ke hāʻawi i kahi ʻāpana i kēlā kelepona, ʻo ka laina me ke kauoha he honua. schedule_work() e kau i ka hana e pili ana i ka hale i hala i loko o ka laina maʻamau o ka mea hoʻonohonoho hana a hoʻopau, ʻae ʻole ʻoe e kali i ke kauoha e hoʻopau. Pono kēia no ka mea wikiwiki loa ka makau. A i ʻole, ʻo kāu koho ʻaʻohe mea e hoʻomaka a i ʻole e loaʻa iā ʻoe kahi kernel panic. Ua like ka lohi me ka make!
  10. ʻO ia, hiki iā ʻoe ke ʻae i ka pūʻolo me kahi hoʻihoʻi kūpono.

Ke kāhea ʻana i kahi polokalamu ma ka mea hoʻohana

ʻO kēia hana ka mea maopopo loa. Hāʻawi ʻia kona inoa ma DECLARE_WORK(), ʻaʻole hoihoi ke ʻano a me nā manaʻo i ʻae ʻia. Lawe mākou i ka laina me ke kauoha a hāʻawi piha i ka pūpū. E hana ʻo ia i ka parsing, e ʻimi ana i nā binaries a me nā mea ʻē aʻe.

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. E hoʻonoho i nā manaʻo hoʻopaʻapaʻa i kahi laina o nā kaula argv[]. Manaʻo wau ua ʻike nā mea a pau e hoʻokō maoli ʻia nā papahana ma kēia ala, ʻaʻole ma ke ʻano he laina mau me nā hakahaka.
  2. E hoʻonoho i nā mea hoʻololi kaiapuni. Ua hoʻokomo wau iā PATH wale nō me ka liʻiliʻi o nā ala, me ka manaʻo ua hui pū ʻia lākou a pau /bin с /usr/bin и /sbin с /usr/sbin. He mea koʻikoʻi nā ala ʻē aʻe i ka hoʻomaʻamaʻa.
  3. Pau, e hana kāua! ʻO ka hana kernel call_usermodehelper() ʻae komo. ala i ka binary, array of arguments, array of environment variables. Maʻaneʻi ke manaʻo nei au ua hoʻomaopopo nā mea a pau i ke ʻano o ka hele ʻana i ke ala i ka faila hoʻokō ma ke ʻano he hoʻopaʻapaʻa ʻokoʻa, akā hiki iā ʻoe ke nīnau. ʻO ka manaʻo hoʻopaʻapaʻa hope e kuhikuhi inā e kali no ke kaʻina hana e hoʻopau (UMH_WAIT_PROC), hoʻomaka ka hana (UMH_WAIT_EXEC) a ʻaʻole paha e kali iki (UMH_NO_WAIT). Aia kekahi mau mea hou aku UMH_KILLABLE, ʻAʻole au i nānā.

Hōʻuluʻulu

Hana ʻia ka hui ʻana o nā modula kernel ma o ka kernel make-framework. Kāhea ʻia make i loko o kahi papa kuhikuhi kūikawā i hoʻopaʻa ʻia i ka mana kernel (i wehewehe ʻia ma aneʻi: KERNELDIR:=/lib/modules/$(shell uname -r)/build), a hāʻawi ʻia ka wahi o ka module i ka loli M ma na hoopaapaa. ʻO ka icmpshell.ko a me nā pahuhopu maʻemaʻe e hoʻohana holoʻokoʻa i kēia anga. IN obj-m hōʻike i ka waihona mea e hoʻololi ʻia i module. Syntax e hana hou ana main.o в icmpshell.o (icmpshell-objs = main.o) ʻaʻole i kūpono loa iaʻu, akā pēlā nō.

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

ʻOhi mākou: make. Ke hoʻouka nei: insmod icmpshell.ko. Pau, hiki iā ʻoe ke nānā: sudo ./send.py 45.11.26.232 "date > /tmp/test". Inā loaʻa iā ʻoe kahi faila ma kāu mīkini /tmp/test a aia i loko o ka lā i hoʻouna ʻia ai ke noi, ʻo ia hoʻi, ua hana ʻoe i nā mea āpau a ua hana pono wau i nā mea āpau.

hopena

ʻOi aku ka maʻalahi o kaʻu ʻike mua me ka hoʻomohala nuklea ma mua o kaʻu i manaʻo ai. ʻOiai me ka ʻike ʻole o ka hoʻomohala ʻana ma C, e kālele ana i nā hōʻailona compiler a me nā hopena Google, ua hiki iaʻu ke kākau i kahi module hana a manaʻo wau e like me ka mea hacker kernel, a ma ka manawa like he kiddie script. Eia hou, ua hele au i ke kahawai Kernel Newbies, kahi i ʻōlelo ʻia ai iaʻu e hoʻohana schedule_work() ma kahi o ke kahea ana call_usermodehelper() i loko o ka makau pono'ī a hoʻohilahila iā ia, me ka manaʻo pono he scam. Hoʻokahi haneli laina o ke code i uku iaʻu ma kahi o hoʻokahi pule o ka hoʻomohala ʻana i koʻu manawa kūʻokoʻa. He ʻike kūleʻa i hoʻopau i kaʻu moʻolelo pilikino e pili ana i ka paʻakikī paʻakikī o ka hoʻomohala ʻana i ka ʻōnaehana.

Inā ʻae kekahi e hana i kahi loiloi code ma Github, e mahalo wau. Ua maopopo iaʻu ua nui kaʻu mau hewa naʻaupō, ʻoi aku ka nui o ka hana ʻana me nā kaula.

ʻO ka pūpū nuklea ma luna o ICMP

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka