cangkang nuklir leuwih ICMP

cangkang nuklir leuwih ICMP

TL; DR: Kuring nulis modul kernel anu bakal maca paréntah ti payload ICMP sarta ngaéksekusi aranjeunna dina server sanajan SSH Anjeun ngadat. Pikeun paling teu sabar, sadaya kode téh github.

Awas Pangalaman C programmer résiko bursting kana cimata getih! Kuring malah bisa jadi salah dina terminologi, tapi kritik sagala wilujeng sumping. Pos ieu dimaksudkeun pikeun jalma anu gaduh ide anu kasar ngeunaan pemrograman C sareng hoyong ningali ka jero Linux.

Dina komentar ka kuring munggaran artikel disebutkeun SoftEther VPN, nu bisa meniru sababaraha protokol "biasa", hususna HTTPS, ICMP komo DNS. Abdi tiasa ngabayangkeun ngan kahiji maranéhanana digawé, saprak Kami pisan wawuh jeung HTTP (S), sarta kuring kungsi diajar tunneling leuwih ICMP na DNS.

cangkang nuklir leuwih ICMP

Leres, dina taun 2020 kuring diajar yén anjeun tiasa ngalebetkeun payload sawenang-wenang kana pakét ICMP. Tapi hadé telat ti pernah! Sareng kumargi aya anu tiasa dilakukeun ngeunaan éta, maka éta kedah dilakukeun. Kusabab dina kahirupan sapopoe kuring paling sering nganggo garis paréntah, kalebet ngalangkungan SSH, ideu cangkang ICMP mimiti aya dina pikiran kuring. Sarta dina raraga ngumpul a bingo bullshield lengkep, Kuring mutuskeun nulis salaku modul Linux Ubuntu dina basa nu kuring ukur boga gagasan kasar. Cangkang sapertos kitu moal katingali dina daptar prosés, anjeun tiasa ngamuat kana kernel sareng éta moal aya dina sistem file, anjeun moal ningali anu curiga dina daptar palabuhan ngadangukeun. Dina watesan kamampuhan na, ieu téh rootkit full-fledged, tapi kuring miharep pikeun ngaronjatkeun eta sarta ngagunakeun eta salaku cangkang tina Resort panungtungan nalika beban Rata-rata teuing tinggi pikeun log in via SSH tur ngaéksekusi sahenteuna. echo i > /proc/sysrq-triggerpikeun mulangkeun aksés tanpa rebooting.

Simkuring nyandak redaktur téks, kaahlian programming dasar dina Python jeung C, Google jeung maya nu teu kapikiran nempatkeun dina péso lamun sagalana megatkeun (opsional - lokal VirtualBox / KVM / jsb) jeung hayu urang balik!

bagian klien

Sigana mah pikeun bagian klien kuring kedah nyerat naskah kalayan sakitar 80 garis, tapi aya jalma anu bageur anu ngalakukeun éta pikeun kuring. sagala karya. Kodeu tétéla basajan teu disangka-sangka, pas kana 10 garis anu penting:

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

Skrip nyandak dua argumen, alamat sareng muatan. Saméméh ngirim, payload dimimitian ku konci run:, urang bakal butuh eta ngaluarkeun bungkusan kalawan payloads acak.

Kernel meryogikeun hak istimewa pikeun ngadamel bungkusan, janten naskah kedah dijalankeun salaku superuser. Tong hilap masihan idin palaksanaan sareng pasang scapy nyalira. Debian ngagaduhan pakét anu disebut python3-scapy. Ayeuna anjeun tiasa pariksa kumaha éta sadayana jalan.

Ngajalankeun sareng ngaluarkeun paréntah
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!

Ieu naon kasampak kawas dina sniffer nu
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

Payload dina pakét respon teu robah.

modul kernel

Pikeun ngawangun dina mesin virtual Debian anjeun peryogi sahenteuna make и linux-headers-amd64, sésana bakal datangna dina bentuk kagumantungan. Kuring moal nyadiakeun sakabéh kode dina artikel; Anjeun tiasa clone on Github.

Setélan hook

Pikeun mimitian, urang peryogi dua fungsi pikeun ngamuat modul sareng ngabongkar muatanana. Fungsi pikeun unloading henteu diperlukeun, tapi lajeng rmmod éta moal jalan; modul ngan bakal dibongkar nalika dipareuman.

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

Naon anu lumangsung di dieu:

  1. Dua file header ditarik pikeun ngamanipulasi modul sorangan sareng netfilter.
  2. Sadaya operasi ngalangkungan netfilter, anjeun tiasa nyetél kait di jerona. Jang ngalampahkeun ieu, anjeun kudu ngadéklarasikeun struktur nu hook bakal ngonpigurasi. Hal pangpentingna nyaéta nangtukeun fungsi anu bakal dieksekusi salaku hook a: nfho.hook = icmp_cmd_executor; Kuring gé meunang ka fungsi sorangan engké.
    Teras kuring nyetél waktos ngolah pakét: NF_INET_PRE_ROUTING nangtukeun pikeun ngolah pakét nalika mimiti muncul dina kernel. Bisa dipaké NF_INET_POST_ROUTING pikeun ngolah pakét nalika kaluar tina kernel.
    Kuring nyetél saringan ka IPv4: nfho.pf = PF_INET;.
    Kuring masihan hook abdi prioritas pangluhurna: nfho.priority = NF_IP_PRI_FIRST;
    Sareng kuring ngadaptarkeun struktur data salaku pancing anu saleresna: nf_register_net_hook(&init_net, &nfho);
  3. Fungsi ahir ngaluarkeun hook.
  4. Lisensina jelas dituduhkeun supados kompiler henteu ngawadul.
  5. fungsi module_init() и module_exit() set fungsi séjén pikeun initialize sarta nungtungan modul.

Retrieving payload

Ayeuna urang kedah nimba payload, ieu tétéla janten tugas paling hese. Kernel teu gaduh fungsi anu diwangun pikeun damel sareng muatan; anjeun ngan ukur tiasa nga-parse header tina protokol tingkat luhur.

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

Aya naon:

  1. Kuring kedah ngalebetkeun file header tambahan, waktos ieu pikeun ngamanipulasi header IP sareng ICMP.
  2. Kuring nyetel panjang garis maksimum: #define MAX_CMD_LEN 1976. Naha persis ieu? Kusabab compiler complains ngeunaan eta! Aranjeunna geus ngusulkeun ka kuring yén kuring kudu ngarti tumpukan jeung numpuk, someday kuring pasti bakal ngalakukeun ieu malah meureun ngabenerkeun kode. Kuring langsung nyetél garis anu bakal ngandung paréntah: char cmd_string[MAX_CMD_LEN];. Éta kedah katingali dina sadaya fungsi; Kuring bakal nyarioskeun ieu langkung rinci dina paragraf 9.
  3. Ayeuna urang kedah ngamimitian (struct work_struct my_work;) struktur sarta sambungkeun kana fungsi séjén (DECLARE_WORK(my_work, work_handler);). Kuring ogé bakal ngobrol ngeunaan naha ieu diperlukeun dina paragraf kasalapan.
  4. Ayeuna kuring dibewarakeun fungsi, nu bakal hook a. Jenis sareng argumen anu ditampi didikte ku netfilter, kami ngan ukur resep skb. Ieu mangrupikeun panyangga stop kontak, struktur data dasar anu ngandung sadaya inpormasi anu aya ngeunaan pakét.
  5. Pikeun fungsina tiasa dianggo, anjeun peryogi dua struktur sareng sababaraha variabel, kalebet dua iterator.
      struct iphdr *iph;
      struct icmphdr *icmph;
    
      unsigned char *user_data;
      unsigned char *tail;
      unsigned char *i;
      int j = 0;
  6. Urang bisa mimitian ku logika. Pikeun modul nu dianggo, euweuh pakét lian ti ICMP Echo diperlukeun, sangkan parse panyangga ngagunakeun diwangun-di fungsi jeung buang kaluar kabeh non-ICMP na non-Echo pakét. Balik deui NF_ACCEPT hartina narima pakét, tapi anjeun oge bisa leupaskeun bungkusan ku mulang 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;
      }

    Kuring henteu acan nguji naon anu bakal kajadian tanpa mariksa header IP. Pangaweruh minimal kuring ngeunaan C nyarioskeun ka kuring yén tanpa cék tambahan, hal anu dahsyat pasti bakal kajadian. Kuring bakal bungah lamun dissuade kuring ieu!

  7. Ayeuna yén pakét mangrupikeun jinis anu anjeun peryogikeun, anjeun tiasa nimba data. Tanpa fungsi diwangun-di, Anjeun mimitina kudu meunang pointer ka awal payload nu. Hal ieu dilakukeun dina hiji tempat, anjeun kedah nyandak pointer ka awal ICMP lulugu sarta mindahkeun kana ukuran lulugu ieu. Sadayana nganggo struktur icmph: user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
    Ahir lulugu kudu cocog tungtung payload di skb, ku kituna urang meunangkeun eta ngagunakeun sarana nuklir tina struktur pakait: tail = skb_tail_pointer(skb);.

    cangkang nuklir leuwih ICMP

    Gambarna dipaling di dieu, Anjeun bisa maca leuwih lengkep tentang panyangga stop kontak.

  8. Sakali anjeun gaduh pointers ka awal jeung ahir, anjeun tiasa nyalin data kana string a cmd_string, pariksa ayana prefiks a run: jeung, boh Piceun pakét lamun leungit, atawa nulis balik garis deui, nyoplokkeun awalan ieu.
  9. Éta éta, ayeuna anjeun tiasa nyauran pawang anu sanés: schedule_work(&my_work);. Kusabab éta moal mungkin pikeun ngirimkeun parameter kana telepon sapertos kitu, jalur sareng paréntahna kedah global. schedule_work() bakal nempatkeun fungsi pakait sareng struktur diliwatan kana antrian umum tugas scheduler tur lengkep, sahingga anjeun teu ngadagoan paréntah pikeun ngalengkepan. Ieu diperlukeun sabab hook kudu pisan gancang. Upami teu kitu, pilihan anjeun henteu aya anu bakal ngamimitian atanapi anjeun bakal nampi panik kernel. Tunda téh kawas maot!
  10. Éta éta, anjeun tiasa nampi pakét sareng mulang anu saluyu.

Nyauran program dina ruang pangguna

Fungsi ieu anu paling kaharti. Ngaranna dibéré dina DECLARE_WORK(), jenis jeung argumen ditarima teu metot. Urang nyokot garis kalawan paréntah jeung lulus eta sagemblengna ka cangkang. Hayu anjeunna nungkulan parsing, milarian binér sareng anu sanésna.

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. Atur argumen kana hiji Asép Sunandar Sunarya string argv[]. Kuring bakal nganggap yén sadayana terang yén program saleresna dieksekusi ku cara ieu, sareng sanés salaku garis anu kontinyu sareng spasi.
  2. Atur variabel lingkungan. Kuring diselapkeun ukur PATH kalawan set minimum jalur, hoping yén maranéhanana kabéh geus digabungkeun /bin с /usr/bin и /sbin с /usr/sbin. jalur séjén jarang masalah dina prakna.
  3. Réngsé, hayu urang laksanakeun! Fungsi kernel call_usermodehelper() narima asupna. jalur ka binér, Asép Sunandar Sunarya argumen, Asép Sunandar Sunarya variabel lingkungan. Di dieu kuring ogé nganggap yén dulur understands harti ngalirkeun jalur ka file laksana salaku argumen misah, tapi anjeun bisa nanya. Argumen panungtungan nangtukeun naha kudu ngadagoan prosés pikeun réngsé (UMH_WAIT_PROC), prosés ngamimitian (UMH_WAIT_EXEC) atanapi henteu ngantosan pisan (UMH_NO_WAIT). Naha aya deui UMH_KILLABLE, Abdi henteu ningali kana éta.

Majelis

Majelis modul kernel dilaksanakeun ngaliwatan kernel make-framework. Ditelepon make di jero diréktori khusus anu dihijikeun kana versi kernel (ditetepkeun di dieu: KERNELDIR:=/lib/modules/$(shell uname -r)/build), sareng lokasi modul disalurkeun ka variabel M dina dalil-dalil. The icmpshell.ko jeung target bersih ngagunakeun kerangka ieu sagemblengna. DI obj-m nunjukkeun file obyék anu bakal dirobah jadi modul. Syntax nu remakes main.o в icmpshell.o (icmpshell-objs = main.o) teu kasampak pisan logis pikeun kuring, tapi jadi eta.

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

Urang ngumpulkeun: make. ngamuat: insmod icmpshell.ko. Réngsé, anjeun tiasa pariksa: sudo ./send.py 45.11.26.232 "date > /tmp/test". Upami Anjeun gaduh file dina mesin Anjeun /tmp/test sarta ngandung tanggal pamundut ieu dikirim, nu hartina anjeun ngalakukeun sagalana katuhu jeung kuring ngalakukeun sagalana katuhu.

kacindekan

Pangalaman munggaran kuring sareng pamekaran nuklir langkung gampang tibatan anu kuring ngarepkeun. Malahan tanpa pangalaman ngembang dina C, fokus dina petunjuk kompiler jeung hasil Google, kuring bisa nulis modul gawé sarta ngarasa kawas hacker kernel, sarta dina waktos anu sareng a kiddie Aksara. Salaku tambahan, kuring angkat ka saluran Kernel Newbies, dimana kuring dititah nganggo schedule_work() tinimbang nelepon call_usermodehelper() jero hook sorangan jeung shamed anjeunna, rightly suspecting scam a. Saratus garis kode ngarugikeun kuring ngeunaan saminggu pangwangunan dina waktu luang kuring. Pangalaman suksés anu ngancurkeun mitos pribadi kuring ngeunaan pajeulitna pangwangunan sistem.

Upami aya anu satuju pikeun ngalakukeun ulasan kode dina Github, kuring bakal nganuhunkeun. Kuring yakin yén kuring ngalakukeun seueur kasalahan anu bodo, khususna nalika damel sareng senar.

cangkang nuklir leuwih ICMP

sumber: www.habr.com

Tambahkeun komentar