የኑክሌር ሼል በ ICMP ላይ

የኑክሌር ሼል በ ICMP ላይ

TL; DRእኔ የከርነል ሞጁል እየጻፍኩ ነው ከ ICMP ክፍያ ጭነት ትዕዛዞችን የሚያነብ እና በአገልጋዩ ላይ የሚያስፈጽመው SSH ቢያበላሽም። በጣም ትዕግስት ለሌላቸው, ሁሉም ኮድ ነው የፊልሙ.

ጥንቃቄ ልምድ ያካበቱ የC ፕሮግራም አዘጋጆች በደም እንባ ሊፈነዱ ይችላሉ! በቃላት ቃላቶች ውስጥ እንኳን ተሳስቼ ሊሆን ይችላል, ነገር ግን ማንኛውም ትችት ተቀባይነት አለው. ልጥፉ የታሰበው ስለ ሲ ፕሮግራሚንግ በጣም ረቂቅ ሀሳብ ላላቸው እና የሊኑክስን የውስጥ ክፍል ማየት ለሚፈልጉ ነው።

የእኔ የመጀመሪያ አስተያየት ውስጥ ጽሑፍ አንዳንድ “መደበኛ” ፕሮቶኮሎችን በተለይም HTTPS፣ ICMP እና ዲ ኤን ኤስን መኮረጅ የሚችል SoftEther VPN ተጠቅሷል። እኔ ከኤችቲቲፒ(S) ጋር በደንብ ስለማውቅ እና በICMP እና ዲ ኤን ኤስ መሿለኪያ መማር ስላለብኝ ከእነሱ መካከል የመጀመሪያዎቹ እንደሚሰሩ መገመት እችላለሁ።

የኑክሌር ሼል በ ICMP ላይ

አዎ፣ በ2020 የዘፈቀደ ጭነት ወደ ICMP ፓኬቶች ማስገባት እንደሚችሉ ተማርኩ። ግን ከመቼውም ጊዜ ዘግይቶ የተሻለ ነው! እና አንድ ነገር በእሱ ላይ ሊደረግ ስለሚችል, ከዚያም መደረግ አለበት. በዕለት ተዕለት ሕይወቴ ብዙውን ጊዜ የትእዛዝ መስመርን በኤስኤስኤች በኩል ስለምጠቀም ​​የ ICMP ሼል ሀሳብ መጀመሪያ ወደ አእምሮዬ መጣ። እና የተሟላ ቡልሼልድ ቢንጎን ለመሰብሰብ፣ እኔ ባሰብኩት ቋንቋ እንደ ሊኑክስ ሞጁል ልጽፈው ወሰንኩ። እንዲህ ዓይነቱ ቅርፊት በሂደቶች ዝርዝር ውስጥ አይታይም, ወደ ከርነል መጫን ይችላሉ እና በፋይል ስርዓቱ ላይ አይሆንም, በማዳመጥ ወደቦች ዝርዝር ውስጥ ምንም አጠራጣሪ ነገር አያዩም. ከችሎታው አንፃር፣ ይህ ሙሉ በሙሉ የተሟላ ሩትኪት ነው፣ ግን እሱን ለማሻሻል እና እንደ የመጨረሻ አማራጭ ሼል ልጠቀምበት ተስፋ አደርጋለሁ የመጫኛ አማካይ በኤስኤስኤች በኩል ለመግባት እና ቢያንስ ለማስፈፀም በጣም ከፍተኛ ነው። echo i > /proc/sysrq-triggerዳግም ሳይነሳ መዳረሻን ወደነበረበት ለመመለስ.

የጽሑፍ አርታዒን እንወስዳለን, መሰረታዊ የፕሮግራም ችሎታዎች በ Python እና C, Google እና ምናባዊ ማሽን ሁሉም ነገር ከተበላሸ (አማራጭ - አካባቢያዊ ቨርቹዋልቦክስ/KVM/ወዘተ) ቢላዋ ስር ማስገባት የማይፈልጉት እና እንሂድ!

የደንበኛ ጎን

ለደንበኛው ወደ 80 የሚጠጉ መስመሮችን የያዘ ስክሪፕት መጻፍ እንዳለብኝ መስሎኝ ነበር ፣ ግን ያደረጉልኝ ደግ ሰዎች ነበሩ ። ሁሉም ሥራ. ኮዱ ከ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()

ስክሪፕቱ ሁለት ነጋሪ እሴቶችን ይወስዳል, አድራሻ እና ጭነት. ከመላኩ በፊት፣ የሚከፈለው ጭነት በቁልፍ ይቀድማል run:, በዘፈቀደ የሚጫኑ ጥቅሎችን ለማስቀረት ያስፈልገናል.

ኮርነሉ ጥቅሎችን ለመሥራት ልዩ መብቶችን ይፈልጋል፣ ስለዚህ ስክሪፕቱ እንደ ሱፐር ተጠቃሚ መሆን አለበት። የማስፈጸሚያ ፈቃዶችን መስጠት እና ስካፒን እራሱን መጫንን አይርሱ። ዴቢያን የሚባል ጥቅል አለው። python3-scapy. አሁን ሁሉም እንዴት እንደሚሰራ ማረጋገጥ ይችላሉ.

ትዕዛዙን ማስኬድ እና ማውጣት
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!

በአነፍናፊው ውስጥ የሚመስለው ይህ ነው።
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

በምላሽ ጥቅል ውስጥ ያለው የክፍያ ጭነት አይለወጥም.

የከርነል ሞጁል

በዴቢያን ምናባዊ ማሽን ውስጥ ለመገንባት ቢያንስ ያስፈልግዎታል make и linux-headers-amd64, ቀሪው በጥገኛ መልክ ይመጣል. በጽሁፉ ውስጥ ሙሉውን ኮድ አላቀርብም፤ በ Github ላይ መዝጋት ይችላሉ።

መንጠቆ ማዋቀር

ለመጀመር, ሞጁሉን ለመጫን እና ለማራገፍ ሁለት ተግባራት ያስፈልጉናል. የማውረድ ተግባር አያስፈልግም, ግን ከዚያ rmmod አይሰራም, ሞጁሉ ሲጠፋ ብቻ ይወርዳል.

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

እዚህ ምን እየሆነ ነው:

  1. ሞጁሉን እራሱ እና የተጣራ ማጣሪያውን ለመቆጣጠር ሁለት የራስጌ ፋይሎች ተስቦ ገብተዋል።
  2. ሁሉም ክዋኔዎች በተጣራ ማጣሪያ ውስጥ ያልፋሉ, በውስጡ መንጠቆዎችን ማዘጋጀት ይችላሉ. ይህንን ለማድረግ መንጠቆው የሚዋቀርበትን መዋቅር ማወጅ ያስፈልግዎታል. በጣም አስፈላጊው ነገር እንደ መንጠቆ የሚሠራውን ተግባር መግለጽ ነው- nfho.hook = icmp_cmd_executor; በኋላ ላይ ወደ ተግባሩ እገባለሁ።
    ከዚያ ለጥቅሉ የማስኬጃ ሰዓቱን አዘጋጅቻለሁ፡- NF_INET_PRE_ROUTING ጥቅሉን በከርነል ውስጥ ለመጀመሪያ ጊዜ ሲታይ ለማስኬድ ይገልጻል። መጠቀም ይቻላል NF_INET_POST_ROUTING ከከርነል ሲወጣ ፓኬጁን ለማስኬድ.
    ማጣሪያውን ወደ IPv4 አዘጋጅቻለሁ፡- nfho.pf = PF_INET;.
    የእኔ መንጠቆ ከፍተኛውን ቅድሚያ እሰጣለሁ፡- nfho.priority = NF_IP_PRI_FIRST;
    እና የውሂብ አወቃቀሩን እንደ ትክክለኛው መንጠቆ አስመዘገብኩ፡- nf_register_net_hook(&init_net, &nfho);
  3. የመጨረሻው ተግባር መንጠቆውን ያስወግዳል.
  4. አቀናባሪው ቅሬታ እንዳያሰማ ፈቃዱ በግልፅ ተጠቁሟል።
  5. ተግባሮች module_init() и module_exit() ሞጁሉን ለመጀመር እና ለማቋረጥ ሌሎች ተግባራትን ያዘጋጁ.

የተከፈለውን ጭነት በማንሳት ላይ

አሁን የክፍያውን ጭነት ማውጣት አለብን, ይህ በጣም ከባድ ስራ ሆኖ ተገኝቷል. ኮርነሉ ከክፍያ ጭነቶች ጋር አብሮ ለመስራት አብሮ የተሰሩ ተግባራት የሉትም፤ የከፍተኛ ደረጃ ፕሮቶኮሎችን ራስጌዎች ብቻ መተንተን ይችላሉ።

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

ምን እየተደረገ ነው:

  1. ተጨማሪ የራስጌ ፋይሎችን ማካተት ነበረብኝ፣ በዚህ ጊዜ IP እና ICMP ራስጌዎችን ለመቆጣጠር።
  2. ከፍተኛውን የመስመር ርዝመት አዘጋጅቻለሁ፡- #define MAX_CMD_LEN 1976. ለምን በትክክል ይህ? ምክንያቱም አቀናባሪው ስለእሱ ቅሬታ አለው! ቁልል እና ክምር መረዳት እንዳለብኝ አስቀድመው ጠቁመውኛል፣ አንድ ቀን በእርግጠኝነት ይህን አደርጋለሁ እና ምናልባት ኮዱን አስተካክላለሁ። ወዲያውኑ ትዕዛዙን የያዘውን መስመር አዘጋጅቻለሁ፡- char cmd_string[MAX_CMD_LEN];. በሁሉም ተግባራት ውስጥ መታየት አለበት, ስለዚህ ጉዳይ በአንቀጽ 9 ላይ በበለጠ ዝርዝር እናገራለሁ.
  3. አሁን ማስጀመር አለብን (struct work_struct my_work;) መዋቅር እና ከሌላ ተግባር ጋር ያገናኙት (DECLARE_WORK(my_work, work_handler);). በዘጠነኛው አንቀጽ ላይ ይህ ለምን አስፈላጊ እንደሆነ እናገራለሁ.
  4. አሁን አንድ ተግባር አውጃለሁ, እሱም መንጠቆ ይሆናል. ዓይነት እና ተቀባይነት ያላቸው ክርክሮች በ netfilter የታዘዙ ናቸው, እኛ ብቻ ፍላጎት አለን skb. ይህ የሶኬት ቋት ነው፣ ስለ ፓኬት ሁሉንም የሚገኙ መረጃዎችን የያዘ መሠረታዊ የውሂብ መዋቅር ነው።
  5. ተግባሩ እንዲሠራ ሁለት ተደጋጋሚዎችን ጨምሮ ሁለት አወቃቀሮችን እና በርካታ ተለዋዋጮችን ያስፈልግዎታል።
      struct iphdr *iph;
      struct icmphdr *icmph;
    
      unsigned char *user_data;
      unsigned char *tail;
      unsigned char *i;
      int j = 0;
  6. በሎጂክ መጀመር እንችላለን። ሞጁሉ እንዲሰራ፣ ከ ICMP Echo ሌላ ምንም እሽጎች አያስፈልግም፣ ስለዚህ አብሮ የተሰሩ ተግባራትን በመጠቀም ቋቱን እንተነተን እና ሁሉንም ICMP ያልሆኑ እና ኢኮ ያልሆኑ ፓኬቶችን እንጥላለን። ተመለስ NF_ACCEPT ፓኬጁን መቀበል ማለት ነው, ነገር ግን በመመለስ ጥቅሎችን መጣል ይችላሉ 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;
      }

    የአይፒ ራስጌዎችን ሳላረጋግጥ ምን እንደሚሆን አልሞከርኩም። ስለ C ያለኝ አነስተኛ እውቀት ያለ ተጨማሪ ቼኮች አንድ አስከፊ ነገር መከሰቱ አይቀርም ይለኛል። ከዚህ ብታሳምኑኝ ደስ ይለኛል!

  7. አሁን ጥቅሉ የሚያስፈልግዎ ትክክለኛ አይነት ስለሆነ ውሂቡን ማውጣት ይችላሉ. አብሮ የተሰራ ተግባር ከሌለ በመጀመሪያ ለክፍያው መጀመሪያ ጠቋሚ ማግኘት አለብዎት። ይህ በአንድ ቦታ ይከናወናል, ጠቋሚውን ወደ ICMP ራስጌ መጀመሪያ መውሰድ እና ወደዚህ ራስጌ መጠን መውሰድ ያስፈልግዎታል. ሁሉም ነገር መዋቅርን ይጠቀማል icmph: user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
    የራስጌው መጨረሻ ከተጫነው ጭነት መጨረሻ ጋር መዛመድ አለበት። skb, ስለዚህ እኛ ከተዛማጅ መዋቅር የኑክሌር ዘዴዎችን በመጠቀም እናገኛለን: tail = skb_tail_pointer(skb);.

    የኑክሌር ሼል በ ICMP ላይ

    ምስሉ ተሰርቋል እዚህ፣ ስለ ሶኬት ቋት የበለጠ ማንበብ ይችላሉ።

  8. መጀመሪያ እና መጨረሻ ላይ ጠቋሚዎች ካሉዎት በኋላ ውሂቡን ወደ ሕብረቁምፊ መቅዳት ይችላሉ። cmd_string, ቅድመ ቅጥያ መኖሩን ያረጋግጡ run: እና፣ ወይ ጥቅሉን ከጠፋ ያስወግዱት፣ ወይም መስመሩን እንደገና ይፃፉ፣ ይህን ቅድመ ቅጥያ ያስወግዱ።
  9. ያ ብቻ ነው፣ አሁን ወደ ሌላ ተቆጣጣሪ መደወል ይችላሉ፡- schedule_work(&my_work);. ለእንደዚህ አይነት ጥሪ መለኪያ ማስተላለፍ ስለማይቻል ከትእዛዙ ጋር ያለው መስመር ዓለም አቀፋዊ መሆን አለበት. schedule_work() ከታለፈው መዋቅር ጋር የተያያዘውን ተግባር ወደ ተግባር መርሐግብር አጠቃላይ ወረፋ ያስቀምጣል እና ያጠናቅቃል, ይህም ትዕዛዙ እስኪጠናቀቅ ድረስ እንዳይጠብቁ ያስችልዎታል. መንጠቆው በጣም ፈጣን መሆን አለበት ምክንያቱም ይህ አስፈላጊ ነው. አለበለዚያ ምርጫዎ ምንም ነገር አይጀምርም ወይም የከርነል ሽብር ይደርስብዎታል. መዘግየት እንደ ሞት ነው!
  10. ያ ብቻ ነው፣ ጥቅሉን በተዛማጅ መመለሻ መቀበል ይችላሉ።

በተጠቃሚ ቦታ ላይ ፕሮግራም በመደወል ላይ

ይህ ተግባር በጣም ለመረዳት የሚቻል ነው. ውስጥ ስሙ ተሰጥቷል። DECLARE_WORK(), ዓይነት እና ተቀባይነት ያላቸው ክርክሮች አስደሳች አይደሉም. መስመሩን ከትእዛዙ ጋር እንይዛለን እና ሙሉ በሙሉ ወደ ዛጎል እናስተላልፋለን. መተንተንን፣ ሁለትዮሽዎችን እና ሌሎች ነገሮችን በመፈለግ ላይ እንዲሰራ ይፍቀዱለት።

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. ክርክሮችን ወደ የሕብረቁምፊዎች ድርድር ያቀናብሩ argv[]. እኔ እገምታለሁ ፕሮግራሞች በእውነቱ በዚህ መንገድ እንደሚፈጸሙ እና እንደ ቀጣይ መስመር ሳይሆን ከቦታዎች ጋር ሁሉም ሰው እንደሚያውቅ እገምታለሁ።
  2. የአካባቢ ተለዋዋጮችን ያዘጋጁ። PATH ያስገባሁት በትንሹ የመንገዶች ስብስብ ብቻ ነው፣ ሁሉም ቀድሞውኑ ተጣምረው ነበር ብዬ ተስፋ በማድረግ /bin с /usr/bin и /sbin с /usr/sbin. ሌሎች መንገዶች በተግባር እምብዛም አስፈላጊ አይደሉም።
  3. ተከናውኗል፣ እናድርገው! የከርነል ተግባር call_usermodehelper() መግቢያ ይቀበላል. ወደ ሁለትዮሽ የሚወስደው መንገድ፣ የክርክር ድርድር፣ የአካባቢ ተለዋዋጮች ድርድር። እዚህ በተጨማሪ ሁሉም ሰው ወደ ፈጻሚው ፋይል የሚወስደውን መንገድ እንደ የተለየ ሙግት የመተላለፉን ትርጉም እንደሚረዳው እገምታለሁ, ነገር ግን እርስዎ መጠየቅ ይችላሉ. የመጨረሻው መከራከሪያ ሂደቱ እስኪጠናቀቅ ድረስ መጠበቅን ወይም አለመጠበቅን ይገልጻል (UMH_WAIT_PROCየሂደቱ መጀመሪያ (UMH_WAIT_EXEC) ወይም ጨርሶ አለመጠበቅ (UMH_NO_WAIT). ሌላም አለ? UMH_KILLABLE፣ አላየሁትም።

መሰብሰብ

የከርነል ሞጁሎችን መሰብሰብ የሚከናወነው በከርነል ማቀፊያ በኩል ነው። ተጠርቷል። make ከከርነል ሥሪት ጋር በተሳሰረ ልዩ ማውጫ ውስጥ (እዚህ ይገለጻል፡) KERNELDIR:=/lib/modules/$(shell uname -r)/build), እና የሞጁሉ ቦታ ወደ ተለዋዋጭ ተላልፏል M በክርክር ውስጥ. የ icmpshell.ko እና ንጹህ ኢላማዎች ይህንን ማዕቀፍ ሙሉ ለሙሉ ይጠቀማሉ። ውስጥ obj-m ወደ ሞጁል የሚለወጠውን የነገር ፋይል ያሳያል። እንደገና የሚሠራ አገባብ main.o в icmpshell.o (icmpshell-objs = main.o) ለእኔ በጣም ምክንያታዊ አይመስልም, ግን እንደዚያው ይሁን.

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

እኛ እንሰበስባለን: make. በመጫን ላይ፡ insmod icmpshell.ko. ተከናውኗል፣ ማረጋገጥ ትችላለህ፡- sudo ./send.py 45.11.26.232 "date > /tmp/test". በማሽንዎ ላይ ፋይል ካለዎት /tmp/test እና ጥያቄው የተላከበትን ቀን ይዟል, ይህም ማለት ሁሉንም ነገር በትክክል አደረጉ እና ሁሉንም ነገር በትክክል አደረግሁ ማለት ነው.

መደምደሚያ

በኒውክሌር ልማት የመጀመሪያ ተሞክሮዬ ከጠበቅኩት በላይ ቀላል ነበር። ምንም እንኳን በሲ ውስጥ ያለ ልምድ ፣ በአቀናባሪ ፍንጮች እና በ Google ውጤቶች ላይ በማተኮር ፣ የሚሰራ ሞጁል ለመፃፍ እና እንደ ከርነል ጠላፊ ፣ እና በተመሳሳይ ጊዜ የስክሪፕት ልጅ ይሰማኛል። በተጨማሪም፣ እንድጠቀም ተነገረኝ ወደ Kernel Newbies ቻናል ሄጄ ነበር። schedule_work() ከመደወል ይልቅ call_usermodehelper() መንጠቆው ውስጥ ራሱ እና ማጭበርበርን በመጠራጠር አሳፈረው። አንድ መቶ መስመር ኮድ በእኔ ነፃ ጊዜ ውስጥ አንድ ሳምንት ያህል ልማት ወጪ እኔን. ስለ ስርዓት ልማት እጅግ ውስብስብነት ያለኝን የግል አፈ ታሪክ ያጠፋ የተሳካ ተሞክሮ።

አንድ ሰው በ Github ላይ የኮድ ግምገማ ለማድረግ ከተስማማ፣ አመስጋኝ እሆናለሁ። እርግጠኛ ነኝ ብዙ ደደብ ስህተቶችን እንደሰራሁ እርግጠኛ ነኝ በተለይ በገመድ ስሰራ።

የኑክሌር ሼል በ ICMP ላይ

ምንጭ: hab.com

አስተያየት ያክሉ