TL; DR: ์ ๋ SSH๊ฐ ์ถฉ๋ํ๋๋ผ๋ ICMP ํ์ด๋ก๋์์ ๋ช
๋ น์ ์ฝ๊ณ ์๋ฒ์์ ์คํํ๋ ์ปค๋ ๋ชจ๋์ ์์ฑ ์ค์
๋๋ค. ๊ฐ์ฅ ์ฐธ์์ฑ์ด ์๋ ์ฌ๋์ ์ํด ๋ชจ๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ฃผ์! ์๋ จ๋ C ํ๋ก๊ทธ๋๋จธ๋ผ๋ฉด ํผ๋๋ฌผ์ ํ๋ฆฌ๊ฒ ๋ ์ํ์ด ์์ต๋๋ค! ์ฉ์ด๊ฐ ํ๋ฆด ์๋ ์์ง๋ง ์ด๋ค ๋นํ์ด๋ผ๋ ํ์ํฉ๋๋ค. ์ด ๊ฒ์๋ฌผ์ C ํ๋ก๊ทธ๋๋ฐ์ ๋ํด ๋งค์ฐ ๋๋ต์ ์ธ ๊ฐ๋ ์ ๊ฐ๊ณ ์๊ณ Linux์ ๋ด๋ถ๋ฅผ ์ดํด๋ณด๊ณ ์ถ์ ์ฌ๋๋ค์ ๋์์ผ๋ก ์์ฑ๋์์ต๋๋ค.
๋ด ์ฒซ ๋๊ธ์
์, 2020๋
์ ICMP ํจํท์ ์์์ ํ์ด๋ก๋๋ฅผ ์ฝ์
ํ ์ ์๋ค๋ ๊ฒ์ ๋ฐฐ์ ์ต๋๋ค. ํ์ง๋ง ์ ํ๋ ๊ฒ๋ณด๋ค๋ ๋ฆ๋ ๊ฒ ๋ซ์ต๋๋ค! ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ ๋ํด ๋ญ๊ฐ ์กฐ์น๋ฅผ ์ทจํ ์ ์์ผ๋ฏ๋ก ์กฐ์น๋ฅผ ์ทจํด์ผ ํฉ๋๋ค. ์ผ์ ์ํ์์ SSH๋ฅผ ํฌํจํ์ฌ ๋ช
๋ น์ค์ ๊ฐ์ฅ ์์ฃผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ICMP ์
ธ์ ๋ํ ์์ด๋์ด๊ฐ ๊ฐ์ฅ ๋จผ์ ๋ ์ฌ๋์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์์ ํ Bullshield ๋น๊ณ ๋ฅผ ์กฐ๋ฆฝํ๊ธฐ ์ํด ๋๋ต์ ์ธ ์์ด๋์ด๋ง ๊ฐ์ง๊ณ ์๋ ์ธ์ด๋ก Linux ๋ชจ๋๋ก ์์ฑํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ์ด๋ฌํ ์
ธ์ ํ๋ก์ธ์ค ๋ชฉ๋ก์ ํ์๋์ง ์์ผ๋ฉฐ ์ปค๋์ ๋ก๋ํ ์ ์์ผ๋ฉฐ ํ์ผ ์์คํ
์ ์์ผ๋ฉฐ ์์ ํฌํธ ๋ชฉ๋ก์ ์์ฌ์ค๋ฌ์ด ํญ๋ชฉ์ด ํ์๋์ง ์์ต๋๋ค. ๊ธฐ๋ฅ ์ธก๋ฉด์์ ์ด๊ฒ์ ๋ณธ๊ฒฉ์ ์ธ ๋ฃจํธํท์ด์ง๋ง ๋ก๋ ํ๊ท ์ด ๋๋ฌด ๋์ SSH๋ฅผ ํตํด ๋ก๊ทธ์ธํ์ฌ ์ต์ํ ์คํํ ์ ์์ ๋ ์ด๋ฅผ ๊ฐ์ ํ์ฌ ์ตํ์ ์๋จ์ผ๋ก ์ฌ์ฉํ๊ธฐ๋ฅผ ํฌ๋งํฉ๋๋ค. echo i > /proc/sysrq-trigger
์ฌ๋ถํ
ํ์ง ์๊ณ ์ก์ธ์ค๋ฅผ ๋ณต์ํฉ๋๋ค.
์ฐ๋ฆฌ๋ ํ
์คํธ ํธ์ง๊ธฐ, Python ๋ฐ C์ ๊ธฐ๋ณธ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ์ , Google ๋ฐ
ํด๋ผ์ด์ธํธ ๋ถ๋ถ
ํด๋ผ์ด์ธํธ ๋ถ๋ถ์ 80์ค ์ ๋์ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํด์ผ ํ ๊ฒ ๊ฐ์๋๋ฐ, ์น์ ํ๊ฒ ํด์ฃผ์๋ ๋ถ๋ค์ด ๊ณ์
จ์ด์.
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);
๋ฌด์จ ์ผ์ด์ผ?
- ๋ชจ๋ ์์ฒด์ netfilter๋ฅผ ์กฐ์ํ๊ธฐ ์ํด ๋ ๊ฐ์ ํค๋ ํ์ผ์ ๊ฐ์ ธ์ต๋๋ค.
- ๋ชจ๋ ์์
์ ๋ทํํฐ๋ฅผ ๊ฑฐ์น๋ฉฐ ์ฌ๊ธฐ์ ํํฌ๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด ํํฌ๋ฅผ ๊ตฌ์ฑํ ๊ตฌ์กฐ๋ฅผ ์ ์ธํด์ผ ํฉ๋๋ค. ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ํํฌ๋ก ์คํ๋ ํจ์๋ฅผ ์ง์ ํ๋ ๊ฒ์
๋๋ค.
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);
- ๋ง์ง๋ง ํจ์๋ ํํฌ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
- ์ปดํ์ผ๋ฌ๊ฐ ๋ถํํ์ง ์๋๋ก ๋ผ์ด์ผ์ค๊ฐ ๋ช ํํ๊ฒ ํ์๋์ด ์์ต๋๋ค.
- ๊ธฐ๋ฅ
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;
}
๋ฌด์จ ์ผ์ด์ผ:
- ์ด๋ฒ์๋ IP ๋ฐ ICMP ํค๋๋ฅผ ์กฐ์ํ๊ธฐ ์ํด ์ถ๊ฐ ํค๋ ํ์ผ์ ํฌํจํด์ผ ํ์ต๋๋ค.
- ์ต๋ ์ค ๊ธธ์ด๋ฅผ ์ค์ ํ์ต๋๋ค.
#define MAX_CMD_LEN 1976
. ์ ํํ ์ ์ด๋ฐ๊ฐ์? ์ปดํ์ผ๋ฌ๊ฐ ๊ทธ๊ฒ์ ๋ํด ๋ถํํ๊ธฐ ๋๋ฌธ์ ๋๋ค! ๊ทธ๋ค์ ์ด๋ฏธ ๋์๊ฒ ์คํ๊ณผ ํ์ ์ดํดํด์ผ ํ๋ค๊ณ ์ ์ํ์ต๋๋ค. ์ธ์ ๊ฐ๋ ๋ฐ๋์ ์ด๋ฅผ ์ํํ๊ณ ์ฝ๋๋ฅผ ์์ ํ ์๋ ์์ต๋๋ค. ๋๋ ์ฆ์ ๋ช ๋ น์ ํฌํจํ ์ค์ ์ค์ ํ์ต๋๋ค.char cmd_string[MAX_CMD_LEN];
. ๋ชจ๋ ํจ์์์ ๋ณผ ์ ์์ด์ผ ํ๋ฉฐ ์ด์ ๋ํด์๋ 9๋จ๋ฝ์์ ์์ธํ ์ค๋ช ํ๊ฒ ์ต๋๋ค. - ์ด์ ์ด๊ธฐํํด์ผ ํฉ๋๋ค(
struct work_struct my_work;
) ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ณ ์ด๋ฅผ ๋ค๋ฅธ ํจ์์ ์ฐ๊ฒฐํฉ๋๋ค(DECLARE_WORK(my_work, work_handler);
). ์ด๊ฒ์ด ์ ํ์ํ์ง์ ๋ํด์๋ ์ํ ๋ฒ์งธ ๋ฌธ๋จ์์ ์ด์ผ๊ธฐํ๊ฒ ์ต๋๋ค. - ์ด์ ํํฌ๊ฐ ๋ ํจ์๋ฅผ ์ ์ธํฉ๋๋ค. ์ ํ๊ณผ ํ์ฉ๋๋ ์ธ์๋ netfilter์ ์ํด ๊ฒฐ์ ๋๋ฉฐ ์ฐ๋ฆฌ๋ ๋ค์์๋ง ๊ด์ฌ์ด ์์ต๋๋ค.
skb
. ์ด๊ฒ์ ํจํท์ ๋ํด ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ์ ๋ณด๋ฅผ ํฌํจํ๋ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ธ ์์ผ ๋ฒํผ์ ๋๋ค. - ํจ์๊ฐ ์๋ํ๋ ค๋ฉด ๋ ๊ฐ์ ๊ตฌ์กฐ์ ๋ ๊ฐ์ ๋ฐ๋ณต์๋ฅผ ํฌํจํ ์ฌ๋ฌ ๋ณ์๊ฐ ํ์ํฉ๋๋ค.
struct iphdr *iph; struct icmphdr *icmph; unsigned char *user_data; unsigned char *tail; unsigned char *i; int j = 0;
- ์ฐ๋ฆฌ๋ ๋
ผ๋ฆฌ๋ถํฐ ์์ํ ์ ์์ต๋๋ค. ๋ชจ๋์ด ์๋ํ๋ ค๋ฉด 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์ ๋ํ ๋์ ์ต์ํ์ ์ง์์ ์ถ๊ฐ ํ์ธ ์์ด๋ ๋์ฐํ ์ผ์ด ๋ฐ์ํ ์๋ฐ์ ์๋ค๋ ๊ฒ์ ๋งํด์ค๋๋ค. ๋น์ ์ด ๋๋ฅผ ์ค๋ํ๋ฉด ๊ธฐ๋ปํ ๊ฒ์ ๋๋ค!
- ์ด์ ํจํค์ง๊ฐ ํ์ํ ์ ํํ ์ ํ์ด๋ฏ๋ก ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํ ์ ์์ต๋๋ค. ๋ด์ฅ ํจ์๊ฐ ์์ผ๋ฉด ๋จผ์ ํ์ด๋ก๋์ ์์ ๋ถ๋ถ์ ๋ํ ํฌ์ธํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํฉ๋๋ค. ์ด ์์
์ ํ ๊ณณ์์ ์ํ๋ฉ๋๋ค. ํฌ์ธํฐ๋ฅผ ICMP ํค๋์ ์์ ๋ถ๋ถ์ผ๋ก ๊ฐ์ ธ์ ์ด ํค๋์ ํฌ๊ธฐ๋ก ์ด๋ํด์ผ ํฉ๋๋ค. ๋ชจ๋ ๊ฒ์ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ค
icmph
:user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
ํค๋์ ๋์ ํ์ด๋ก๋์ ๋๊ณผ ์ผ์นํด์ผ ํฉ๋๋ค.skb
๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ ํด๋น ๊ตฌ์กฐ์ ํต ์๋จ์ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์ป์ต๋๋ค.tail = skb_tail_pointer(skb);
.
์ฌ์ง์ด ๋๋๋นํ์ด์๋ฐ๋ผ์ , ์์ผ ๋ฒํผ์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ฝ์ ์ ์์ต๋๋ค. - ์์๊ณผ ๋์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๊ฐ ์์ผ๋ฉด ๋ฐ์ดํฐ๋ฅผ ๋ฌธ์์ด๋ก ๋ณต์ฌํ ์ ์์ต๋๋ค.
cmd_string
, ์ ๋์ฌ๊ฐ ์๋์ง ํ์ธํ์ธ์.run:
ํจํค์ง๊ฐ ๋๋ฝ๋ ๊ฒฝ์ฐ ํด๋น ํจํค์ง๋ฅผ ์ญ์ ํ๊ฑฐ๋ ์ด ์ ๋์ฌ๋ฅผ ์ ๊ฑฐํ์ฌ ์ค์ ๋ค์ ์์ฑํ์ธ์. - ๊ทธ๊ฒ ๋ค์
๋๋ค. ์ด์ ๋ค๋ฅธ ํธ๋ค๋ฌ๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
schedule_work(&my_work);
. ์ด๋ฌํ ํธ์ถ์๋ ๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ฌํ ์ ์์ผ๋ฏ๋ก ๋ช ๋ น์ด ํฌํจ๋ ํ์ ์ ์ญ์ ์ด์ด์ผ ํฉ๋๋ค.schedule_work()
์ ๋ฌ๋ ๊ตฌ์กฐ์ ๊ด๋ จ๋ ๊ธฐ๋ฅ์ ์์ ์ค์ผ์ค๋ฌ์ ์ผ๋ฐ ๋๊ธฐ์ด์ ๋ฐฐ์นํ๊ณ ์๋ฃํ๋ฏ๋ก ๋ช ๋ น์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์์๋ ๋ฉ๋๋ค. ์ด๋ ํํฌ๊ฐ ๋งค์ฐ ๋นจ๋ผ์ผ ํ๊ธฐ ๋๋ฌธ์ ํ์ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ์์๋์ง ์๊ฑฐ๋ ์ปค๋ ํจ๋์ด ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค. ์ง์ฐ์ ์ฃฝ์๊ณผ ๊ฐ์ต๋๋ค! - ๊ทธ๊ฒ ๋ค์ ๋๋ค. ํด๋น ๋ฐํ์ด ํฌํจ๋ ํจํค์ง๋ฅผ ์๋ฝํ ์ ์์ต๋๋ค.
์ฌ์ฉ์ ๊ณต๊ฐ์์ ํ๋ก๊ทธ๋จ ํธ์ถํ๊ธฐ
์ด ๊ธฐ๋ฅ์ด ๊ฐ์ฅ ์ดํดํ๊ธฐ ์ฝ์ต๋๋ค. ๊ทธ ์ด๋ฆ์ 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);
}
- ์ธ์๋ฅผ ๋ฌธ์์ด ๋ฐฐ์ด๋ก ์ค์
argv[]
. ๋๋ ํ๋ก๊ทธ๋จ์ด ์ค์ ๋ก ๊ณต๋ฐฑ์ด ์๋ ์ฐ์๋ ์ ์ด ์๋๋ผ ์ด๋ฐ ๋ฐฉ์์ผ๋ก ์คํ๋๋ค๋ ๊ฒ์ ๋ชจ๋ ์ฌ๋์ด ์๊ณ ์๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค. - ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํฉ๋๋ค. ๋ชจ๋ ์ด๋ฏธ ๊ฒฐํฉ๋์ด ์๊ธฐ๋ฅผ ๋ฐ๋ผ๋ฉด์ ์ต์ํ์ ๊ฒฝ๋ก ์งํฉ์ด ์๋ PATH๋ง ์ฝ์
ํ์ต๋๋ค.
/bin
ั/usr/bin
ะธ/sbin
ั/usr/sbin
. ๋ค๋ฅธ ๊ฒฝ๋ก๋ ์ค์ ๋ก ๊ฑฐ์ ์ค์ํ์ง ์์ต๋๋ค. - ๋์ด์, ํด๋ณด์! ์ปค๋ ๊ธฐ๋ฅ
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์์ ์ฝ๋ ๊ฒํ ์ ๋์ํ๋ค๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ๋๋ ํนํ ๋ฌธ์์ด๋ก ์์ ํ ๋ ์ด๋ฆฌ์์ ์ค์๋ฅผ ๋ง์ด ์ ์ง๋ ๋ค๊ณ ํ์ ํฉ๋๋ค.
์ถ์ฒ : habr.com