Linux
Last updated
Last updated
Hệ điều hành mã nguồn mở
Cấu trúc:
Hardware Layer − Phần cứng bao gồm tất cả các thiết bị ngoại vi (RAM/ HDD/ CPU, v.v.).
Kernel – Đây là thành phần cốt lõi của Hệ điều hành, tương tác trực tiếp với phần cứng, cung cấp các dịch vụ cấp thấp cho các thành phần lớp trên.
Shell − Một giao diện với kernel, ẩn sự phức tạp của các chức năng kernel khỏi người dùng. Shell nhận lệnh từ người dùng và thực thi các chức năng kernel.
Tiện ích − Các chương trình tiện ích cung cấp cho người dùng hầu hết các chức năng của hệ điều hành.
Linux Distro (Bản phân phối) = nhân linux + các phần mềm bổ sung
File khi mở sẽ ánh xạ đến một giá trị gọi là file descriptor, tương tự như HANDLE trong Windows
Các loại file: - File thông thường, chứa các bytes dữ liệu, tổ chức thành 1 mảng
Thư mục và liên kết
File đặc biệt: Block device file (tập tin đề cập đến một thiết bị), Character device file(thường không có địa chỉ, cung cấp quyền truy cập vào dữ liệu dưới dạng luồng, thường là các ký tự), Named pipes(dùng để giao tiếp giữa các tiến trình), Sockets(dùng để giao tiếp mạng),
Lênh thường dùng: ls, cd, cp, mv, mkdir, rm, rmdir, touch, cat, grep, ..
Tệp chứa hàng loạt thông tin mô tả cách chương trình chạy và lưu trữ trên memory. File thực thi trên linux cũng có header, mã máy, entrypoint, symbols(giống thông tin lưu trong file pdb) và bảng relocations, thư viện tĩnh, thư viện động. …
Thông tin về process đang chạy trong /proc, mỗi process id ứng với một thư mục
Ví dụ, vào 1 đường dẫn /proc/<PID>, ta sẽ tìm thấy những tệp cơ bản sau:
/proc/<PID>/cmdline: Các đối số commandline đã sử dụng để khởi chạy tiến trình
/proc/<PID>/status: Thông tin trạng thái chi tiết, bao gồm memory sử dụng và các số liệu thống kê của tiến trình
/proc/<PID>/fd: Symlink đến các files đã mở bởi tiến trình
Trong tất cả các đường dẫn, ta sẽ thấy 1 cấu trúc thư mục tương tự, và những file quan trọng nhất có thể liệt kê là:
cmdline: commandline của tiến trình
environ: các biến môi trường
fd: file descriptors
limits: chứa thông tin về các giới hạn của tiến trình
mounts: thông tin liên quan
Ta cũng sẽ thấy 1 vài liên kết trong những đường dẫn này:
cwd: 1 link đến current working directory của tiến trình
exe: link đến file có thể thực thi của tiến trình
root: link đến work directory của tiến trình
Signal: Cơ chế gửi tín hiệu, thông báo từ kernel đến process, từ process nọ sang process kia hoặc từ 1 process đến chính nó. Khi nhận được signal, hàm callback của process có thể xử lý hoặc bỏ qua(ngoại trừ SIGNKILL và SIGNSTOP)
Thường có
SIGINT 2 (Ctrl+C)
SIGQUIT 3 (Ctrl+D)
Câu lệnh thường dùng:
ps(liệt kê), top(thông tin chi tiết)
w: xem các user còn đang login đang làm gì
free: hiển thị thông tin bộ nhớ.
uptime: thời gian sống của hệ thống
pstree: hiển thị cây tiến trình
pgrep, pkill: tìm hoặc gửi signal đến tiến trình dựa theo tên và các thuộc tính khác
nice, renice, snice: thay đổi priority của tiến trình
Lập lịch bằng crontab:
Người dùng thiết lập các việc cần làm trong các file văn bản đặc biệt của cron (gọi là crontab file)
“crontab –e”: tạo hoặc chỉnh file crontab, giống “vi” “
crontab –l”: hiển thị file crontab
“crontab –r”: xóa file crontab
Thực hiện
Tạo crontab mới: crontab –e
Soạn như soạn thảo “vi”:
Khởi động lại dịch vụ cron để cập nhật lệnh mới: service crond restart
Theo dõi sự cập nhật của file times.log xem dịch vụ chạy đúng không: tail –f /tmp/times.log
Người dùng thường được phân thành 2 loại chính: root(superuser) và user(normal user)
Trong linux có thể có nhiều group khác nhau và một user có thể thuộc nhiều group. Mỗi group sẽ quy định user thuộc group đó có những quyền như thế nào
Mỗi tệp được liên kết với một user sở hữu, group sỡ hữu và một tập hợp các bit phân quyền r,w,x.
Câu lệnh thường dùng: sudo -i, useradd, usermod, userdel, passwd, group add
Phân quyền: chgrp, chown, chmod
Các file cấu hình hệ thống:
.bashrc: chạy khi có một shell(terminal) chạy lên mà có thể tương tác trực tiếp với người dùng (người dùng mở)
.bash_profile(.profile): tự động chạy khi có một phiên login shell
.bash_logout: chạy khi phiên login shell kết thúc
/etc/ld.so.preload: khai báo biến LD_PRELOAD, chứa một thư viện sẽ luôn được tải bởi mọi tiến trình sau này. Thường rootkit usermode trên linux sẽ khai báo LD_PRELOAD trong file .bash_profile hoặc file ld.so.preload
Các loại log:
/var/log/auth.log
/var/log/secure*:
Chứa thông tin nhật kí xác thực, bất kì hoạt động nào liên quan đến xác thực như sudo, su, ssh, …
Cấu trúc log: time + đối tượng đưa ra log + nội dung log
Nhiều dòng có pam_unix, Pluggable Authentication Modules (PAM) là module xác thực của linux.
/var/log/cmdlog.log: Lưu trữ tất cả các lệnh mà user gõ vào terminal. Log này chứa thời gian gõ lệnh, user thực hiện và nội dung. Không phải là log mặc định
.bash_history: chứa lịch sử các lệnh đã chạy, không chứa username và time
xem log
/var/log/daemen.log: chứa các thông tin về việc hệ thống đang chạy như thế nào và các tiến trình ứng dụng
/var/log/boot.log: lưu trữ tất cả thông tin liên quan đến khởi động và mọi thông báo được ghi lại trong quá trình khởi động bao gồm tập lệnh khởi tạo hệ thống, /etc/init.d/bootmisc.sh…
/var/log/dmesg log và /var/log/kern.log
Log về kernel
/var/log/syslog hoặc /var/log/message: Log hệ thống thông thường chứa các thông tin mặc định của hệ thống, thường được lưu trong
Để xem file log chúng ta có thể sử dụng một số phương pháp phổ biến sau:
vi: Chúng ta có thể sử dụng trình soạn thảo vi để kiểm tra file log.
tail: Nếu chúng ta muốn xem nội dung của file log theo thời gian thực ứng dụng đang ghi vào đó, hãy sử dụng tail -f.
grep: Nếu chúng ta biết chính xác những gì đang tìm kiếm trong file log hãy sử dụng lệnh grep để grep một từ khóa.
cat: Hiển thị toàn bộ nội dung file log.
Chương trình thực thi trên Linux chủ yếu là các file ELF. Định dạng này được sử dụng để lưu trữ các tệp nhị phân, thư viện và core dumps trên đĩa trong Linux và các hệ thống Unix-based
Xem thông tin cơ bản về tệp ELF: file /bin/bash
Cấu trúc: 2 phần chính gồm ELF header và ELF data(Program headers, Section headers, Data)
ELF header: 32 byte, xác định định dạng tệp, bắt đầu bằng 4 unique bytes: 0x7F, 0x45, 0x4c, 0x46. Hiển thị ELF: readelf -h /bin/sh
Program Headers: Cung cấp thông tin về các segment của tệp thực thi sẽ được tải vào bộ nhớ trong quá trình thực thi chương trình.
Chỉ ra loại segment như code, data hoặc thông tin dynamic linking
Chỉ định virtual memory address nơi segment được tải vào bộ nhớ
Chỉ định offset nơi segment data được đặt
Kích thước và Quyền của các segment
Hiển thị program header: readelf /bin/bash -l
Section Headers: Bảng Section header rất quan trọng trong thời gian liên kết để tạo tệp thực thi
Các phần chung:
Text Section(.text) chứa hướng dẫn thực thi của chương trình
Data Section(.data) lưu trữ các biến toàn cục và biến tĩnh đã được khởi tạo
BSS Section(.bss) dành không gian cho các biến toàn cục và biến tĩnh chưa được khởi tạo
Symbol Table Section chứa các symbols (functions, variables) và thông tin liên quan
Commands:
Hiển thị Section Headers: readelf -S /bin/sh
Tạo file thực thi:
gcc example.c -o example
Tạo tập tin có thể liên kết:
gcc example.c -0 example.o
Tạo thư viện chia sẻ:
gcc -shared example1.o example2.o -o libexample.so
Sử dụng custom library này cần thêm vào /usr/lib, /usr/local/bin
Inject process
Có những trường hợp cần hook(chặn) các system call, thay đổi tham số đầu vào
Linux cung cấp cơ chế ptrace cho phép tiến trình cha có thể quan sát và kiểm soát việc thực thi của một chương trình con
Mặc định k đc phép sử dụng ptrace, ta phải set cấu hình trong file /proc/sys/kernel/yama/ptrace_scope
0: tất cả process đều có thể debug
1: chỉ parent process có thể debug child process
2: chỉ process admin có thể debug
3: không cho phép ptrace
Nếu chiếm được quyền root, hacker có thể lợi dụng set lại cấu hình ptrace để có thể debug/inject mọi process
Nhận biết: cat /proc/sys/kernel/yama/ptrace_scope -> Nếu hiển thị là 0 thì phải xác minh
Hàm ptrace có cấu trúc:
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
Request: request đến pid, có thể đọc/ghi/alloc data, thực thi code
Có 2 cách thường dùng để inject code:
Alloc + write shellcode và thực thi code này
Alloc + write shell có chức năng load thư viên .so (thường sử dụng nếu inject code nhiều chức năng phức tạp hoặc dành cho script kiddie, chỉ cần code file.so bình thường rồi copy shellcode có chức năng load file .so )
Hook share libary:
Linux cung cấp biến môi trường LD_PRELOAD dùng để chỉ định 1 share library sẽ được ưu tiên gọi lên trước (tương đương Appinit_dlls trong registry của Windows). Thường dùng để debug nhưng cũng có thể lợi dụng để hook một hàm có sẵn
Vd: LD_PRELOAD trỏ đến VT.so(có định nghĩa một hàm puts, cùng tên với hàm puts trong stdio.h). Khi 1 chương trình gọi puts, hàm puts trong stdio.h sẽ được gọi thay vì của stdio.h. Trong hàm puts mới, lấy địa chỉ hàm puts cũ bằng cách dùng dlsym. tương tự getProcAddress windows
Nhận biết: echo $LD_PRELOAD
cat /etc/ld.so.preload
Thực hành: Ẩn file loil8.txt qua lệnh ls
o Build: gcc -Wall -fPIC -shared -o hook_so.so hook_so.c –ldl
o Run: export LD_PRELOAD=”/home/…/hook_ls.so”