ICMP๋ฅผ ํ†ตํ•œ ํ•ต ๊ป์งˆ

ICMP๋ฅผ ํ†ตํ•œ ํ•ต ๊ป์งˆ

TL; DR: ์ €๋Š” SSH๊ฐ€ ์ถฉ๋Œํ•˜๋”๋ผ๋„ ICMP ํŽ˜์ด๋กœ๋“œ์—์„œ ๋ช…๋ น์„ ์ฝ๊ณ  ์„œ๋ฒ„์—์„œ ์‹คํ–‰ํ•˜๋Š” ์ปค๋„ ๋ชจ๋“ˆ์„ ์ž‘์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ฐธ์„์„ฑ์ด ์—†๋Š” ์‚ฌ๋žŒ์„ ์œ„ํ•ด ๋ชจ๋“  ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. github.

์ฃผ์˜! ์ˆ™๋ จ๋œ C ํ”„๋กœ๊ทธ๋ž˜๋จธ๋ผ๋ฉด ํ”ผ๋ˆˆ๋ฌผ์„ ํ˜๋ฆฌ๊ฒŒ ๋  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค! ์šฉ์–ด๊ฐ€ ํ‹€๋ฆด ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์–ด๋–ค ๋น„ํŒ์ด๋ผ๋„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒŒ์‹œ๋ฌผ์€ C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋Œ€ํ•ด ๋งค์šฐ ๋Œ€๋žต์ ์ธ ๊ฐœ๋…์„ ๊ฐ–๊ณ  ์žˆ๊ณ  Linux์˜ ๋‚ด๋ถ€๋ฅผ ์‚ดํŽด๋ณด๊ณ  ์‹ถ์€ ์‚ฌ๋žŒ๋“ค์„ ๋Œ€์ƒ์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ์ฒซ ๋Œ“๊ธ€์— ๊ธฐ์‚ฌ ์ผ๋ถ€ "์ผ๋ฐ˜" ํ”„๋กœํ† ์ฝœ, ํŠนํžˆ HTTPS, ICMP, ์‹ฌ์ง€์–ด DNS๋ฅผ ๋ชจ๋ฐฉํ•  ์ˆ˜ ์žˆ๋Š” SoftEther VPN์— ๋Œ€ํ•ด ์–ธ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” HTTP(S)์— ๋งค์šฐ ์ต์ˆ™ํ•˜๊ณ  ICMP์™€ DNS๋ฅผ ํ†ตํ•œ ํ„ฐ๋„๋ง์„ ๋ฐฐ์›Œ์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ์ค‘ ์ฒซ ๋ฒˆ์งธ๋งŒ ์ž‘๋™ํ•œ๋‹ค๊ณ  ์ƒ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ICMP๋ฅผ ํ†ตํ•œ ํ•ต ๊ป์งˆ

์˜ˆ, 2020๋…„์— ICMP ํŒจํ‚ท์— ์ž„์˜์˜ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์•ˆ ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ๋Šฆ๋Š” ๊ฒŒ ๋‚ซ์Šต๋‹ˆ๋‹ค! ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๋ญ”๊ฐ€ ์กฐ์น˜๋ฅผ ์ทจํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์กฐ์น˜๋ฅผ ์ทจํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ผ์ƒ ์ƒํ™œ์—์„œ SSH๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ช…๋ น์ค„์„ ๊ฐ€์žฅ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ICMP ์…ธ์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ๊ฐ€์žฅ ๋จผ์ € ๋–  ์˜ฌ๋ž์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์™„์ „ํ•œ Bullshield ๋น™๊ณ ๋ฅผ ์กฐ๋ฆฝํ•˜๊ธฐ ์œ„ํ•ด ๋Œ€๋žต์ ์ธ ์•„์ด๋””์–ด๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์–ธ์–ด๋กœ Linux ๋ชจ๋“ˆ๋กœ ์ž‘์„ฑํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์…ธ์€ ํ”„๋กœ์„ธ์Šค ๋ชฉ๋ก์— ํ‘œ์‹œ๋˜์ง€ ์•Š์œผ๋ฉฐ ์ปค๋„์— ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํŒŒ์ผ ์‹œ์Šคํ…œ์— ์—†์œผ๋ฉฐ ์ˆ˜์‹  ํฌํŠธ ๋ชฉ๋ก์— ์˜์‹ฌ์Šค๋Ÿฌ์šด ํ•ญ๋ชฉ์ด ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ ์ธก๋ฉด์—์„œ ์ด๊ฒƒ์€ ๋ณธ๊ฒฉ์ ์ธ ๋ฃจํŠธํ‚ท์ด์ง€๋งŒ ๋กœ๋“œ ํ‰๊ท ์ด ๋„ˆ๋ฌด ๋†’์•„ SSH๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธํ•˜์—ฌ ์ตœ์†Œํ•œ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์„ ๋•Œ ์ด๋ฅผ ๊ฐœ์„ ํ•˜์—ฌ ์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ํฌ๋งํ•ฉ๋‹ˆ๋‹ค. echo i > /proc/sysrq-trigger์žฌ๋ถ€ํŒ…ํ•˜์ง€ ์•Š๊ณ  ์•ก์„ธ์Šค๋ฅผ ๋ณต์›ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ํ…์ŠคํŠธ ํŽธ์ง‘๊ธฐ, Python ๋ฐ C์˜ ๊ธฐ๋ณธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ์ˆ , Google ๋ฐ ๊ฐ€์ƒ ๋ชจ๋“  ๊ฒƒ์ด ๊ณ ์žฅ๋‚˜๋”๋ผ๋„(์„ ํƒ ์‚ฌํ•ญ - ๋กœ์ปฌ VirtualBox/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:, ๋ฌด์ž‘์œ„ ํŽ˜์ด๋กœ๋“œ๊ฐ€ ์žˆ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์ œ์™ธํ•˜๋ ค๋ฉด ์ด ์ •๋ณด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ปค๋„์—๋Š” ํŒจํ‚ค์ง€๋ฅผ ์ œ์ž‘ํ•˜๋Š” ๊ถŒํ•œ์ด ํ•„์š”ํ•˜๋ฏ€๋กœ ์Šคํฌ๋ฆฝํŠธ๋Š” ์ˆ˜ํผ์œ ์ €๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‹คํ–‰ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๊ณ  scapy ์ž์ฒด๋ฅผ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ๋ฐ๋น„์•ˆ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒจํ‚ค์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. 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

์‘๋‹ต ํŒจํ‚ค์ง€์˜ ํŽ˜์ด๋กœ๋“œ๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ปค๋„ ๋ชจ๋“ˆ

Debian ๊ฐ€์ƒ ๋จธ์‹ ์„ ๊ตฌ์ถ•ํ•˜๋ ค๋ฉด ์ตœ์†Œํ•œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. 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. ๋ชจ๋“ˆ ์ž์ฒด์™€ netfilter๋ฅผ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ๋‘ ๊ฐœ์˜ ํ—ค๋” ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  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๊ฐ€ ์•„๋‹Œ ํŒจํ‚ท๊ณผ Echo๊ฐ€ ์•„๋‹Œ ํŒจํ‚ท์„ ๋ชจ๋‘ ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค. ๋ฐ˜ํ’ˆ 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;
      }

    IP ํ—ค๋”๋ฅผ ํ™•์ธํ•˜์ง€ ์•Š๊ณ  ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚ ์ง€๋Š” ํ…Œ์ŠคํŠธํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. 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-framework๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” make ์ปค๋„ ๋ฒ„์ „๊ณผ ์—ฐ๊ฒฐ๋œ ํŠน์ˆ˜ ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด๋ถ€(์—ฌ๊ธฐ์— ์ •์˜๋จ: KERNELDIR:=/lib/modules/$(shell uname -r)/build), ๋ชจ๋“ˆ์˜ ์œ„์น˜๊ฐ€ ๋ณ€์ˆ˜์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. M ์ธ์ˆ˜์—์„œ. icmpshell.ko ๋ฐ clean ๋Œ€์ƒ์€ ์ด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์™„์ „ํžˆ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์•ˆ์— 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 ์—ฌ๊ธฐ์—๋Š” ์š”์ฒญ์ด ์ „์†ก๋œ ๋‚ ์งœ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ท€ํ•˜๊ฐ€ ๋ชจ๋“  ์ผ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ–ˆ๊ณ  ๋‚˜๋„ ๋ชจ๋“  ์ผ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ–ˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

์›์ž๋ ฅ ๊ฐœ๋ฐœ์— ๋Œ€ํ•œ ๋‚˜์˜ ์ฒซ ๊ฒฝํ—˜์€ ์˜ˆ์ƒ๋ณด๋‹ค ํ›จ์”ฌ ์‰ฌ์› ์Šต๋‹ˆ๋‹ค. C ๊ฐœ๋ฐœ ๊ฒฝํ—˜์ด ์—†์–ด๋„ ์ปดํŒŒ์ผ๋Ÿฌ ํžŒํŠธ์™€ Google ๊ฒฐ๊ณผ์— ์ค‘์ ์„ ๋‘์–ด ์ž‘์—… ๋ชจ๋“ˆ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ  ์ปค๋„ ํ•ด์ปค์ด์ž ๋™์‹œ์— ์Šคํฌ๋ฆฝํŠธ ํ‚ค๋”” ๊ฐ™์€ ๋Š๋‚Œ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Kernel Newbies ์ฑ„๋„์— ๊ฐ”๋Š”๋ฐ ๊ฑฐ๊ธฐ์„œ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ํ•˜๋”๊ตฐ์š”. schedule_work() ์ „ํ™”ํ•˜๋Š” ๋Œ€์‹  call_usermodehelper() ํ›„ํฌ ์ž์ฒด ๋‚ด๋ถ€์—์„œ ๊ทธ๋ฅผ ๋ถ€๋„๋Ÿฝ๊ฒŒ ์ƒ๊ฐํ•˜์—ฌ ์‚ฌ๊ธฐ๋ฅผ ์˜์‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. XNUMX์ค„์˜ ์ฝ”๋“œ ๋•Œ๋ฌธ์— ์—ฌ๊ฐ€ ์‹œ๊ฐ„์— ๊ฐœ๋ฐœํ•˜๋Š” ๋ฐ ์•ฝ ์ผ์ฃผ์ผ์ด ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ ๊ฐœ๋ฐœ์˜ ์••๋„์ ์ธ ๋ณต์žก์„ฑ์— ๋Œ€ํ•œ ๊ฐœ์ธ์ ์ธ ์‹ ํ™”๋ฅผ ๋ฌด๋„ˆ๋œจ๋ฆฐ ์„ฑ๊ณต์ ์ธ ๊ฒฝํ—˜์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ Github์—์„œ ์ฝ”๋“œ ๊ฒ€ํ† ์— ๋™์˜ํ•œ๋‹ค๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ํŠนํžˆ ๋ฌธ์ž์—ด๋กœ ์ž‘์—…ํ•  ๋•Œ ์–ด๋ฆฌ์„์€ ์‹ค์ˆ˜๋ฅผ ๋งŽ์ด ์ €์งˆ๋ €๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

ICMP๋ฅผ ํ†ตํ•œ ํ•ต ๊ป์งˆ

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€