2017-06-30 28 views
6

Tôi đã thực hiện một chương trình C đơn giản rằng chỉ cần in địa chỉ của main() tại thực hiện:Tại sao Windows không giữ ngẫu nhiên địa chỉ cơ sở của tệp thực thi của tôi?

printf("%08X\n", &main);

tôi biên dịch nó với Visual C++ 2015 với tham số /DYNAMICBASE, cho x86 (điều tương tự sẽ xảy ra khi biên dịch cho x64).

Lần đầu tiên tôi chạy nó, địa chỉ được trả lại khác, như dự kiến. Tuy nhiên, sau hai lần, địa chỉ trở về chương trình vẫn như cũ:

00C31050 
00221050 
00221050 
00221050 

biên dịch lại hoặc đổi tên tập tin thực thi randomizes địa chỉ một lần nữa.

Điều gì đang xảy ra ở đây? Là Windows bằng cách nào đó bộ nhớ đệm thực thi?

+1

Bạn quên khởi động lại giữa các lần chạy. Hoặc để so sánh khi bạn chạy nó trên một máy khác, điểm thực của ASLR. Cách bạn thích nó để làm việc sẽ làm cho nó rất khó khăn để chia sẻ mã giữa các quá trình. Một hương vị tinh vi hơn của ASLR có sẵn cho các loại chương trình có thể được dự kiến ​​chạy trong nhiều năm,/HIGHENTRYOPYVA có sẵn cho mã x64. –

+0

Tôi biết nó sẽ thay đổi giữa khởi động lại hoặc trên các máy khác nhau, và đó thực sự là điểm của ASLR. Tôi chỉ tò mò những gì giữ thực thi tại cùng một địa chỉ trên cùng một máy sau một vài lần chạy, và tại sao. – Thomas

+1

@Thomas nó có thể liên quan đến [Trình tìm nạp trước] (https://en.wikipedia.org/wiki/Prefetcher). Điều này làm cho cảm giác IMO vì lần đầu tiên bạn chạy một exe biên dịch mới nó nhận được một địa chỉ ngẫu nhiên và tiếp tục chạy của nó .exe có được nó từ prefetcher do đó bạn getthe cùng một địa chỉ. –

Trả lời

2

Trước hết, bạn không cần phải lấy địa chỉ hàm và các con trỏ tốt hơn để in bằng trình chỉ định% p, giúp trình biên dịch kiểm tra các loại. Các mã chính xác hơn sẽ là:

printf ("%p\n", main); 

Mở chủ đề, ASLR technology, đó là trách nhiệm rebasing hình ảnh thực thi là một tính năng hệ điều hành được thiết kế để chịu được các cuộc tấn công tràn bộ đệm bằng cách làm cho adresses khó dự đoán hơn. Nó không bảo đảm cho hai lần chạy tuần tự hình ảnh sẽ được đặt tại các vị trí khác nhau, nhưng hệ điều hành cố gắng thay đổi cơ sở theo thời gian, tùy thuộc vào nhiều yếu tố. Đối với các bài kiểm tra của tôi, tôi có (ví dụ) kết quả như sau trên Windows 7 32-bit xây dựng cho 10 chạy liên tục ngay sau khi biên dịch:

00BE1260 
00BE1260 
00221260 
00F71260 
01391260 
01391260 
01391260 
01391260 
01391260 
003A1260 

Như bạn có thể thấy, ngay cả khi chạy liên tục được đặt tại các địa điểm tương tự , cơ sở được thay đổi sau một thời gian. Điều có thể được đảm bảo là hình ảnh thực thi mà không hỗ trợ cơ sở động sẽ luôn được đặt ở chân đế, được thiết lập bởi trình liên kết trong các tiêu đề exe. Các cơ sở mặc định cho hình ảnh thực thi là 400000h, vì thế mà giá trị được in sẽ được một cái gì đó như thế này:

00401260 
00401260 
00401260 
00401260 
00401260 
... 

Đối với trường hợp của bạn tôi cho rằng hệ điều hành thuật toán rebasing làm việc tiên đoán hơn do xử lý thuật toán OS tấn công đe dọa ít có thể xảy ra hoặc do thiếu entropy hoặc tài nguyên. Việc rebasing đòi hỏi một thời gian và nguồn lực bổ sung để remap các trang bộ nhớ và điều chỉnh các chuyển vị, do đó hệ điều hành có thể quyết định rằng việc rebasing thường xuyên là không cần thiết trong trường hợp của bạn.

Tất nhiên, Windows lưu trữ các tệp thực thi được tải để tăng tốc khởi động của chúng. Đó là lý do tại sao xác suất mà cơ sở sẽ không thay đổi trong lần chạy tiếp theo là đủ cao. Nếu bạn có nhiều RAM, RAM càng nhiều có thể được sử dụng cho bộ nhớ cache, thì hình ảnh càng có khả năng sẽ không bị xóa. Không có lý do gì để giữ nguyên cơ sở nếu hình ảnh được tải lại hoàn toàn. Ngoài ra, chính sách rebasing có thể khác nhau giữa các phiên bản hệ điều hành.

Giới thiệu về bộ nhớ cache. Nó không chỉ là một bộ nhớ đệm trong chức năng. Nếu hình ảnh được tải vào bộ nhớ, nó có thể được sử dụng đồng thời cho một quá trình nhiều (trường hợp). Những trường hợp này có thể chia sẻ an toàn các trang mã vì mã chỉ đọc. Đây là một trong những lý do chính khiến Windows không "dỡ hàng" ngay sau khi quá trình chấm dứt. Nhưng hai quy trình có thể chia sẻ mã chỉ khi nó được điều chỉnh đến cùng một cơ sở, bởi vì các chuyển vị sẽ vá mã trong bộ nhớ. Nếu chúng ta buộc các quá trình khác nhau được rebased chúng ta chắc chắn cần phải từ bỏ việc chia sẻ mã sẽ dẫn đến tăng tiêu thụ RAM.

EDIT:

BTW, tôi thấy rằng/tùy chọn DYNAMICBASE được bỏ qua bởi VS2015 và mối liên kết luôn luôn tạo hình ảnh thực thi với sự hỗ trợ ASLR, ngay cả khi tôi explicitely thiết lập/DYNAMICBASE: NO. Ngoài ra so sánh bit-to-bit cho thấy rằng các tập tin được biên dịch là giống hệt với ngoại lệ của một dấu thời gian và (như kết quả) một tổng kiểm tra. Để được thực thi bởi VS2015 mà không cần hỗ trợ ASLR, tôi đã phải xóa thủ công bit IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE trong tiêu đề exe. Không biết liệu nó đã được thực hiện cố ý hay nó là một lỗi MS.

+0

Cảm ơn bạn, nó làm cho rất nhiều cảm giác rằng hình ảnh được lưu trữ vì lý do hiệu suất. Nhân tiện; sử dụng/DYNAMICBASE: KHÔNG hoạt động tốt cho tôi trong VC++ 2015, vì vậy bạn có thể gặp lỗi VC++ hoặc lỗi cấu hình. – Thomas

Các vấn đề liên quan