Xem xét khai thác các lỗ hổng

Vì tôi mong muốn tiếp tục thảo luận về chủ đề này, hãy để tôi kể cho bạn nghe một chút lịch sử, lý thuyết và thực hành về các lỗ hổng. Hiện tại chúng ta đều đã nghe nói rằng lỗi bảo mật có thể phải trả giá rất đắt, chúng ta đều biết rằng chúng ta cần phải cập nhật phần mềm của mình, chúng ta đều biết rằng nhiều bản cập nhật là do lỗi bảo mật. Nhưng hôm nay mình sẽ cho các bạn biết một chút về cách phát hiện và khai thác những lỗi này 🙂 Nhưng trước khi chúng ta làm rõ một vài chi tiết để có cái nhìn tổng quan hơn.

Trước khi bạn bắt đầu

Trước tiên, tôi muốn nói với bạn rằng chúng tôi sẽ tập trung vào lỗ hổng đầu tiên mà tôi đã học cách khai thác, Tràn bộ đệm, trong lỗ hổng này, chúng tôi lợi dụng việc thiếu xác minh bộ nhớ để làm những điều thú vị 🙂 Nhưng hãy làm rõ thêm một chút về nó.

Đây sẽ không phải là một kịch bản thế giới thực

Tôi không đủ khả năng để dạy chúng phá vỡ bất kỳ chương trình nào mà chúng xem 🙂 đầu tiên vì nó nguy hiểm cho máy tính của chúng, thứ hai vì điều đó sẽ chiếm nhiều hơn số lượng từ thông thường của tôi.

Chúng ta đi du ngoạn đến những năm 80

Những gì tôi sẽ cho bạn thấy rằng tôi có thể làm được trên máy tính xách tay của mình, nhưng không có nghĩa là nó có thể được thực hiện ngày nay một cách đơn giản 🙂 nhiều khái niệm trong số này đã bị khai thác rất nhiều lần đến mức các phương pháp bảo vệ mới và các phương pháp mới để tránh chúng đã xuất hiện 😛 nhưng điều đó đưa chúng ta trở về cùng một nơi, không có khoảng trống để có thể kể hết những điều đó 🙂

Nó có thể không hoạt động trên bộ xử lý của bạn

Mặc dù tôi sẽ sử dụng một ví dụ rất đơn giản, nhưng tôi muốn nó khá rõ ràng ngay từ đầu rằng các chi tiết của điều này rất nhiều và đa dạng đến mức nó có thể giống với tôi, nếu bạn muốn thử nó, hiệu quả mong muốn cũng có thể không đạt được 🙂 Nhưng bạn có thể tưởng tượng rằng tôi không thể giải thích điều đó trong không gian này, đặc biệt vì với phần giới thiệu này, tôi đã có hơn 300 từ, vì vậy chúng ta đi thẳng vào vấn đề của mình.

Một là gì Tràn bộ nhớ

Để trả lời điều này trước tiên chúng ta phải hiểu nửa đầu của sự kết hợp này.

Bộ đệm

Vì mọi thứ đều liên quan đến bộ nhớ trong máy tính, nên điều hợp lý là phải có một số loại thùng chứa thông tin. Khi chúng ta nói về đầu vào kết quả đầu ra, chúng ta đi thẳng đến khái niệm bộ đệm. Để ngắn gọn, a đệm Nó là một không gian bộ nhớ có kích thước xác định, trong đó chúng ta sẽ lưu trữ một lượng thông tin, đơn giản 🙂

Tràn xảy ra, như tên của nó, khi một bộ đệm lấp đầy với nhiều thông tin hơn nó có thể giữ. Nhưng tại sao điều này lại quan trọng?

Sắp xếp

Còn được gọi là ngăn xếp, chúng là một kiểu dữ liệu trừu tượng mà chúng ta có thể cây rơm thông tin, đặc điểm chính của họ là họ có một LIFO (Lần xuất trước). Hãy suy nghĩ trong giây lát về một chồng đĩa, chúng ta đặt chúng lên trên từng cái một, và sau đó chúng tôi lấy từng cái một từ trên xuống, điều này làm cho chiếc đĩa cuối cùng mà chúng ta đã đặt (cái ở trên cùng ) là đĩa đầu tiên mà chúng tôi sẽ lấy ra, rõ ràng là nếu chúng tôi chỉ có thể lấy ra một đĩa mỗi lần và chúng tôi quyết định làm theo thứ tự đó: P.

Bây giờ bạn đã biết hai khái niệm này, chúng ta phải sắp xếp chúng theo thứ tự. Ngăn xếp rất quan trọng vì mỗi chương trình chúng tôi chạy đều có chồng thực thi. Nhưng ngăn xếp này có một đặc điểm cụ thểphát triển xuống. Điều duy nhất bạn cần biết về điều này là trong khi một chương trình đang chạy, khi một hàm được gọi, ngăn xếp sẽ chuyển từ một số X trong bộ nhớ sang một số (Xn). Nhưng để tiếp tục chúng ta phải hiểu thêm một khái niệm nữa.

Con trỏ

Đây là một khái niệm khiến nhiều lập trình viên phát điên khi bắt đầu bước vào thế giới của C, trên thực tế sức mạnh to lớn của lập trình C một phần là do việc sử dụng con trỏ. Để đơn giản, một con trỏ trỏ đến một địa chỉ bộ nhớ. Điều này nghe có vẻ phức tạp nhưng không hề phức tạp, trong máy chúng ta đều có RAM phải không? Chà, điều này có thể được định nghĩa là sự sắp xếp liên tiếp của các khối, những vị trí này thường được biểu thị bằng số thập lục phân (từ 0 đến 9 và sau đó từ A đến F, chẳng hạn như 0x0, 0x1, 0x6, 0xA, 0xF, 0x10). Đây là một ghi chú gây tò mò, 0x10 KHÔNG bằng 10 😛 nếu chúng ta chuyển nó sang thứ tự thập phân, nó sẽ giống như nói 15. Đây là một cái gì đó cũng gây nhầm lẫn cho nhiều hơn một lúc đầu, nhưng chúng ta hãy đi xuống nó.

Hồ sơ

Bộ xử lý hoạt động với một số hồ sơ, hoạt động để truyền các vị trí từ bộ nhớ vật lý đến bộ xử lý, đối với các kiến ​​trúc sử dụng 64-bit, số lượng thanh ghi rất lớn và khó mô tả ở đây, nhưng để hiểu được ý tưởng, các thanh ghi giống như con trỏ, chúng chỉ ra giữa các thanh ghi khác vật, một không gian bộ nhớ (vị trí).

Bây giờ thực hành

Tôi biết rằng đã có rất nhiều thông tin để xử lý cho đến bây giờ, nhưng trên thực tế chúng là những vấn đề hơi phức tạp mà tôi cố gắng giải thích một cách rất đơn giản, chúng ta sẽ xem một chương trình nhỏ sử dụng bộ đệm và chúng ta sẽ phá vỡ nó để hiểu điều này về tràn, rõ ràng cái này không Đó là một chương trình thực tế và chúng tôi sẽ "né tránh" nhiều biện pháp đối phó được sử dụng ngày nay, chỉ để cho thấy mọi thứ được thực hiện như thế nào trước đây 🙂 và bởi vì một số nguyên tắc này là cần thiết để có thể học những thứ phức tạp hơn 😉

GDB

Một chương trình tuyệt vời chắc chắn là một trong những chương trình được sử dụng nhiều nhất bởi các lập trình viên C. Trong số nhiều ưu điểm của nó, chúng ta có thực tế là nó cho phép chúng ta thấy tất cả những điều mà chúng ta đã nói đến từ trước đến nay, thanh ghi, ngăn xếp, bộ đệm, v.v. 🙂 Hãy cùng xem chương trình mà chúng tôi sẽ sử dụng cho ví dụ của chúng tôi.

retinput.c

Sở hữu. Christopher Diaz Riveros

Đây là một chương trình khá đơn giản, chúng ta sẽ sử dụng thư viện stdio.h để có thể lấy thông tin và hiển thị nó trong một thiết bị đầu cuối. Chúng ta có thể thấy một hàm được gọi là return_input tạo ra một đệm gọi mảng, có chiều dài 30 byte (kiểu dữ liệu char dài 1 byte).

Chức năng gets(array); yêu cầu thông tin bằng bảng điều khiển và chức năng printf() trả về nội dung của mảng và hiển thị nó trên màn hình.

Mọi chương trình được viết bằng C đều bắt đầu bằng hàm main(), điều này sẽ chỉ phụ trách việc gọi return_input, bây giờ chúng ta sẽ biên dịch chương trình.

Sở hữu. Christopher Diaz Riveros

Hãy xem một chút về những gì tôi vừa làm. Tùy chọn -ggdb yêu cầu gcc biên dịch chương trình với thông tin cho gdb để có thể gỡ lỗi đúng cách. -fno-stack-protector Đó là một tùy chọn mà rõ ràng là chúng ta không nên sử dụng, nhưng chúng ta sẽ sử dụng vì nếu không có thể tạo ra tràn bộ đệm trong ngăn xếp. Cuối cùng tôi đã kiểm tra kết quả. ./a.out nó chỉ chạy những gì tôi vừa biên dịch, nó hỏi thông tin và trả về. Đang chạy 🙂

Cảnh báo

Một lưu ý khác ở đây. Bạn có thể xem các cảnh báo? rõ ràng đó là điều cần tính đến khi chúng ta làm việc với mã hoặc biên dịch, điều này hơi hiển nhiên và có rất ít chương trình ngày nay có chức năng gets() Trong mã. Một ưu điểm của Gentoo là bằng cách biên dịch từng chương trình, tôi có thể thấy có gì sai sót, một chương trình "lý tưởng" không nên có chúng, nhưng bạn sẽ ngạc nhiên khi có nhiều chương trình lớn có những cảnh báo này vì chúng rất lớn và rất khó để theo dõi chúng chức năng nguy hiểm khi có nhiều cảnh báo cùng lúc. Bây giờ nếu chúng ta tiếp tục

Gỡ lỗi chương trình

Sở hữu. Christopher Diaz Riveros

Bây giờ, phần này có thể hơi khó hiểu, nhưng vì tôi đã viết khá nhiều, tôi không đủ khả năng để giải thích tất cả mọi thứ, rất tiếc nếu bạn thấy rằng tôi đang đi quá nhanh 🙂

Giải trừ mã

Hãy bắt đầu bằng cách xem chương trình ngôn ngữ máy đã biên dịch của chúng tôi.

Sở hữu. Christopher Diaz Riveros

Đây là mã của chức năng chính của chúng tôi trong hợp ngữ, đây là những gì bộ xử lý của chúng tôi hiểu, dòng bên trái là địa chỉ vật lý trong bộ nhớ, <+ n> được gọi là bù đắp, về cơ bản là khoảng cách từ đầu hàm (chính) đến câu lệnh đó (được gọi là opcode). Sau đó, chúng ta thấy loại lệnh (push / mov / callq…) và một hoặc nhiều thanh ghi. Tóm lại, chúng ta có thể nói rằng đó là chỉ dẫn theo sau là nguồn / xuất xứ và đích. <return_input> đề cập đến chức năng thứ hai của chúng tôi, chúng ta hãy xem xét.

return_input

Sở hữu. Christopher Diaz Riveros

Điều này phức tạp hơn một chút, nhưng tôi chỉ muốn bạn kiểm tra một vài điều, có một thẻ được gọi là <gets@plt> và một mã opcode cuối cùng được gọi là retq cho biết kết thúc của chức năng. Chúng ta sẽ đặt một vài điểm ngắt, một điểm trong hàm gets và một cái khác trong retq.

Sở hữu. Christopher Diaz Riveros

chạy

Bây giờ chúng ta sẽ chạy chương trình để xem hành động bắt đầu như thế nào.

Sở hữu. Christopher Diaz Riveros

Chúng tôi có thể thấy rằng một mũi tên nhỏ xuất hiện cho biết opcode nơi chúng tôi đang ở, tôi muốn chúng tính đến hướng 0x000055555555469b, đây là địa chỉ sau cuộc gọi tới return_input trong chức năng main , điều này rất quan trọng vì đây là nơi chương trình sẽ quay lại khi bạn hoàn tất việc nhận đầu vào, chúng ta hãy đi vào chức năng. Bây giờ chúng ta sẽ kiểm tra bộ nhớ trước khi nhập hàm gets.

Sở hữu. Christopher Diaz Riveros

Tôi đã sao lưu chức năng chính cho bạn và đánh dấu mã tôi đang đề cập đến, như bạn có thể thấy, do sự đặc biệt đã được tách thành hai đoạn, tôi muốn bạn tính đến hướng 0x7fffffffdbf0 (người đầu tiên từ bên trái sau khi biệt kích x/20x $rsp) vì đây là vị trí chúng ta phải sử dụng để kiểm tra kết quả nhận được, hãy tiếp tục:

Phá vỡ chương trình

Sở hữu. Christopher Diaz Riveros

Tôi đã đánh dấu những 0x44444444bởi vì chúng là đại diện cho các D của chúng tôi 🙂 bây giờ chúng tôi đã bắt đầu thêm đầu vào vào chương trình và như bạn có thể thấy, chúng tôi chỉ còn cách địa chỉ mong muốn của chúng tôi hai dòng, chúng tôi sẽ điền nó cho đến khi chúng tôi ở ngay trước các địa chỉ mà chúng tôi đã đánh dấu trong bước trước.

Thay đổi đường dẫn trở lại

Bây giờ chúng ta đã quản lý để nhập phần này của mã nơi nó chỉ ra sự trả lại của hàm, hãy xem điều gì sẽ xảy ra nếu chúng ta thay đổi địa chỉ 🙂 thay vì đi đến vị trí của mã opcode theo sau địa chỉ mà chúng ta đã có một lúc trước, bạn nghĩ sao nếu chúng ta quay trở lại return_input? Nhưng đối với điều này, cần phải viết địa chỉ chúng ta muốn ở dạng nhị phân, chúng ta sẽ thực hiện điều đó với hàm printf khỏi bash 🙂

Sở hữu. Christopher Diaz Riveros

Bây giờ chúng tôi đã nhận được thông tin hai lần 😀 chắc chắn chương trình không được tạo ra cho điều đó, nhưng chúng tôi đã tìm cách phá vỡ mã và khiến nó lặp lại điều mà nó không được phép làm.

Suy ngẫm

Thay đổi đơn giản này có thể được coi là một khai thác rất cơ bản 🙂 anh ấy đã xoay sở để phá vỡ chương trình và làm điều gì đó mà chúng tôi muốn anh ấy làm.

Đây chỉ là bước đầu tiên trong danh sách gần như vô hạn những thứ cần xem và thêm vào, có nhiều cách để thêm nhiều thứ hơn là đơn giản lặp lại một thứ tự, nhưng lần này tôi đã viết rất nhiều và mọi thứ liên quan đến mã vỏ sò Nó là một chủ đề để viết nhiều hơn các bài báo, những cuốn sách hoàn chỉnh mà tôi muốn nói. Xin lỗi nếu tôi không thể nghiên cứu sâu hơn một chút về các chủ đề mà tôi muốn, nhưng chắc chắn sẽ có cơ hội 🙂 Xin chào và cảm ơn vì đã đến đây.


Để lại bình luận của bạn

địa chỉ email của bạn sẽ không được công bố. Các trường bắt buộc được đánh dấu bằng *

*

*

  1. Chịu trách nhiệm về dữ liệu: Miguel Ángel Gatón
  2. Mục đích của dữ liệu: Kiểm soát SPAM, quản lý bình luận.
  3. Hợp pháp: Sự đồng ý của bạn
  4. Truyền thông dữ liệu: Dữ liệu sẽ không được thông báo cho các bên thứ ba trừ khi có nghĩa vụ pháp lý.
  5. Lưu trữ dữ liệu: Cơ sở dữ liệu do Occentus Networks (EU) lưu trữ
  6. Quyền: Bất cứ lúc nào bạn có thể giới hạn, khôi phục và xóa thông tin của mình.

  1.   2p2 dijo

    Trực tiếp hơn. Viết ít hơn và tập trung vào những gì quan trọng

    1.    ChrisADR dijo

      Xin chào, cảm ơn đã nhận xét.

      Thành thật mà nói, tôi đã cắt bỏ một phần ý tưởng tốt, nhưng ngay cả như vậy đối với tôi dường như tôi vẫn để lại mức tối thiểu để những người không có kiến ​​thức về lập trình có thể có được ý tưởng.

      Liên quan

      1.    Vô danh dijo

        Vấn đề là những người không có kiến ​​thức lập trình sẽ không tìm hiểu về bất cứ điều gì vì nó quá phức tạp để bắt đầu, nhưng những người biết cách lập trình đánh giá cao sự trực tiếp hơn.

        Tôi đoán bạn không thể tiếp cận tất cả mọi người, bạn phải lựa chọn, và trong trường hợp này, bạn đã phạm tội khi muốn che đậy rất nhiều.

        Nhân đây, tôi nói với bạn như một phản biện mang tính xây dựng, tôi yêu thích những chủ đề này và tôi muốn bạn tiếp tục viết bài, xin chúc mừng!

    2.    Vô danh dijo

      Tôi nghĩ cùng một điều.

      1.    ChrisADR dijo

        Cảm ơn cả hai rất nhiều !! chắc chắn là khó hiểu làm thế nào để tiếp cận đối tượng mục tiêu khi sự thật là số lượng người có trình độ lập trình nâng cao đọc những bài báo này là rất ít (ít nhất có thể suy ra dựa trên các nhận xét)

        Tôi chắc chắn đã phạm tội khi muốn đơn giản hóa một điều gì đó đòi hỏi một nền tảng kiến ​​thức rộng để có thể hiểu được. Tôi hy vọng bạn hiểu rằng vì tôi mới bắt đầu viết blog, tôi vẫn chưa khám phá ra điểm chính xác nơi người đọc của tôi biết và hiểu những gì tôi đang nói. Điều đó sẽ giúp nói ra sự thật dễ dàng hơn rất nhiều 🙂

        Tôi sẽ cố gắng rút ngắn hơn khi nó phù hợp mà không làm giảm cá nhân hóa định dạng, vì tách cách viết khỏi nội dung phức tạp hơn một chút so với những gì người ta có thể tưởng tượng, ít nhất tôi đã có chúng khá liên kết, nhưng tôi cho rằng cuối cùng tôi sẽ có thể để thêm dòng thay vì cắt nội dung.

        Liên quan

  2.   Mario dijo

    Bạn có thể tìm hiểu thêm về chủ đề này ở đâu? Bất kỳ cuốn sách được đề xuất?

    1.    ChrisADR dijo

      Ví dụ được lấy từ The Shellcoder's Handbook của Chris Anley, John Heasman, Felix Linder và Gerardo Richarte, nhưng để thực hiện bản dịch 64 bit, tôi phải tìm hiểu về kiến ​​trúc của mình, hướng dẫn dành cho nhà phát triển intel, tập 2 và 3 là một nguồn khá đáng tin cậy cho điều đó. Đọc tài liệu GDB có kèm theo lệnh 'info gdb' cũng rất hay, Để học Assembly và C có nhiều sách rất hay, chỉ khác là sách Assembly hơi cũ nên có chỗ trống cần điền thêm gõ tài liệu.

      Bản thân shellcode ngày nay không còn hiệu quả vì nhiều lý do khác nhau, nhưng vẫn rất thú vị khi học các kỹ thuật mới.

      Hy vọng nó sẽ giúp một chút 🙂 Chúc mừng

  3.   Franz dijo

    Bài viết hay, blog cũ desdelinux đã được tái sinh một lần nữa =))
    Khi bạn nói trình bao từ xa không hiệu quả, bạn có nghĩa là các biện pháp đối phó được thiết kế để giảm thiểu các cuộc tấn công, họ gọi đó là bảo mật tấn công.
    Xin chào và duy trì nó

    1.    ChrisADR dijo

      Cảm ơn bạn rất nhiều Franz, những lời rất tử tế, thực ra ý tôi là Shellcoding ngày nay phức tạp hơn nhiều so với những gì chúng ta thấy ở đây. Chúng tôi có ASLR (trình tạo vị trí bộ nhớ ngẫu nhiên) bảo vệ ngăn xếp, các biện pháp và biện pháp đối phó khác nhau giới hạn số lượng mã opc có thể được đưa vào một chương trình và đó mới chỉ là bước khởi đầu.

      Kính trọng,

  4.   Phần mềm miễn phí dijo

    Xin chào, bạn sẽ làm một phần khác mở rộng chủ đề? Thật thú vị

    1.    ChrisADR dijo

      Xin chào, chủ đề chắc chắn khá thú vị, nhưng mức độ phức tạp mà chúng tôi thực hiện sẽ trở nên rất cao, có thể liên quan đến một số lượng lớn các bài đăng để giải thích các điều kiện tiên quyết khác nhau để hiểu được chủ đề khác. Tôi có thể sẽ viết về nó, nhưng nó sẽ không phải là những bài viết sau, tôi muốn viết một vài chủ đề trước khi tiếp tục với điều này.

      Xin chào và cảm ơn vì đã chia sẻ

  5.   cây xương rồng dijo

    Che rất tốt! Bạn đang đóng góp những bài viết tuyệt vời! Một câu hỏi đặt ra, tôi đang bắt đầu công việc Bảo mật CNTT này bằng cách đọc một cuốn sách có tên "Đảm bảo an ninh bằng cách kiểm tra bút". Cuốn sách này có được khuyến khích không? Làm thế nào để bạn đề nghị tôi bắt đầu hỏi về những vấn đề này?

    1.    ChrisADR dijo

      Xin chào cây xương rồng, nó là cả một vũ trụ về các lỗ hổng bảo mật và những lỗ hổng khác, nói thật là nó phụ thuộc rất nhiều vào những gì thu hút sự chú ý của bạn và nhu cầu của bạn, một người quản lý CNTT không cần biết như một người kiểm tra bút, Hoặc một nhà điều tra lỗ hổng, hoặc một nhà phân tích pháp y, một nhóm khắc phục thảm họa có một bộ kỹ năng rất khác nhau. Rõ ràng là mỗi người trong số họ yêu cầu một mức độ kiến ​​thức kỹ thuật khác nhau, tôi khuyên bạn nên bắt đầu khám phá chính xác những gì bạn thích và bắt đầu ngấu nghiến sách, bài báo và những thứ khác, và quan trọng nhất, hãy thực hành mọi thứ bạn đọc, ngay cả khi nó đã lỗi thời , điều đó cuối cùng sẽ tạo ra sự khác biệt.
      Kính trọng,

  6.   Eizen dijo

    Hey.
    Cảm ơn bạn rất nhiều vì đã giải thích chủ đề này, cũng như nhận xét rằng để có thêm thông tin, chúng tôi có "Sổ tay của Shellcoder". Tôi đã có một bài đọc đang chờ xử lý 😉