Exploit deaslr through _dl_runtime_resolve

Chào tất cả mọi người, cuối cùng thì tôi cũng đã quay lại sau bao ngày im hơi lặng tiếng :))



Abstract:

Hôm nay nhân một ngày đẹp trời, để đánh dấu sự trở lại của mình tôi có một bài viết để phân tích về một kỹ thuật exploit khi mà bạn không thể leak được bất kì thông tin gì và ASLR (Address space layout randomization) đang được bật và cũng không có bất kỳ thông tin về phiên bản libc được sử dụng trên server. 

Explain:

Đã bao giờ bạn đặt ra một câu hỏi "WTF? Tại sao chương trình nó chạy lại có thể run đến một cái hàm ở trong thư viện libc?"

Để tìm hiểu thì bây giờ hãy thử compiler một file dơn giản sử dụng một hàm của thư viện nhé!
File: test.c
Hãy thử debug và next từng dòng lệnh assembly để khám phá!!
Debug nào :))




Hãy chú ý đến từng lệnh vì tất cả nó đề có ý nghĩa rất quan trọng.
Nhìn qua flow của chương trình thì thấy chương trình call đến hàm _dl_runtime_resolve_avx với 2 tham số được push vào stack. Trong trường hợp này là:
Hàm _dl_runtime_resolve_avx dưa 2 tham số trong stack vào 2 thanh ghi rsi, rdi rồi call đến hàm _dl_fixup:
 Trong hàm _dl_fixup sử lý các tham số rồi call đến hàm  _dl_lookup_symbol_x để lấy địa chỉ của hàm cần chạy với các tham số là:
Nhận thấy để call đến một func khác thì ta phải thay đổi được giá trị của tham số đầu tiên, thay vì trỏ tới 'puts' thì trỏ tới 'system' để call system.
Nhưng làm thế nào để có thể làm được điều đó???


Ban đầu tôi đã nghĩ đến việc thực hiện fake một link_map mới nhưng sau một thời gian dài cố gắng để nó đi vào hoạt động thì mọi con đường đều dẫn tới crash.
Trong lúc mọi thứ đi vào bế tắc thì lại phát hiện ra một hướng đi khác để control được giá trị của tham số đầu tiên.
Để thực hiện được tấn công này thì tôi sử dụng đoạn code sau để demo (với file như bên dưới chỉ có thể thực hiện tấn công trong cấu trúc x86 với cấu trúc x86_64 thì cần thêm điều kiện để có thể khai thác được (by pass offset DT_VERSYM)):
File: vuln.c and vuln
Compile file xong ta nhận thấy có một vùng nhớ data có quyền ghi và địa chỉ của nó luôn luôn cố định ==> việc ghi vô vùng nhớ đó là điều hoàn toàn có thể.

Phân tích những gì ta có trong trường hợp này:
  1. Stack overflow.
  2. Địa chỉ của hàm  _dl_runtime_resolve_avx.
  3. Có thể control được param thứ 2 của hàm _dl_runtime_resolve_avx
Review source code lib tại: https://github.com/lattera/glibc/blob/master/elf/dl-runtime.c
Ngoài ra để có thể hiểu hơn cấu trúc x86 nên sử dụng IDA để mở file lib bởi vì các source code x86_64 có hơi khác so với x86.

Để control được param thứ nhất thì ta cần phải hiểu được nó được tính toán như thế nào:  strtab + sym->st_name 
strtab (string table) giá trị sẽ không bị ảnh hưởng bởi param thứ 2 của hàm _dl_fixup nên ta chỉ cần quan tâm đến giá trị chính xác của nó. Không cần nghĩ cách control nó.
sym là một giá trị được tính dựa vào giá trị của link_map và reloc_arg :v lol thế là ngon rồi :))

symtab cũng là một địa chỉ cố định và không bị ảnh hưởng bởi reloc_arg. 


0x80481CC chính là giá trị của symtab và 0x804821C chính là giá trị của strtab.
Tuy nhiên dựa vào giá trị của reloc_offset (chính bằng reloc_arg trong chuẩn x86_64 thì = reloc_arg*sizeof(Elf64_Rel) ) ta có thể control giá trị của reloc.
Trong trường hợp này thì reloc = 0x8048298+ reloc_arg
Như vậy chỉ cần control giá trị của reloc_arg để giá trị của relloc là một vùng nhớ nằm trên data segment.
Qua đó control được giá trị của reloc->r_info ==> control được giá trị của sym đến một vùng nhớ trên data.

Tuy nhiên có một vài chú ý ở đây. Hãy để ý đến một vài struct được sử dụng. Các giá trị của nó đôi khi phải tuân thủ theo một số quy định về quyền read/write
Trong reloc có 2 giá trị cần quan tâm:
  1. reloc->r_offset là địa chỉ GOT của hàm (phải có quyền write)
  2. reloc->r_info gồm 2 giá trị là R_SYM(3 byte cao) và R_TYPE(1 byte thấp) và giá trị của R_TYPE phải đảm bảo == 7
  3. Giá trị R_SYM được sử dụng để tính giá trị của sym = ELF Symbol Table + R_SYM

Vậy để thực hiện khai thác cân thực hiện các bước sau:
  1. Xác định data segment.
  2. Xác định các địa chỉ của: ELF String Table, ELF Symbol Table, ELF JMPREL Relocation Table.
  3. Xác định được địa chỉ vùng nhớ để tạo một fake Elf64_Rela ==> chọn reloc_arg phù hợp. 
  4. Xác định được địa chỉ vùng nhớ để tạo một fake Elf64_Sym ==> tính được R_SYM ==> reloc->r_info.
  5. Xác định vùng nhớ để làm GOT của symbol ==> xác định được reloc->r_offset.
  6. Xác định vùng nhớ để ghi giá trị của string symbol ==> tính được Elf64_Sym->st_name.
  7. Ghi các giá trị mới tính được tới các vùng nhớ mới được xác định.
Sau đây là phần test exploit của mình với file vuln:
POC: exploit.py

Comments

  1. Sloty Casino - Mapyro
    Find your perfect game at Sloty 이천 출장샵 Casino and 문경 출장안마 Win up 나주 출장안마 to ₹2,500 Welcome 전라북도 출장안마 Bonus! Play for Free or Real Money in Sloty Casino Games. 강원도 출장마사지

    ReplyDelete

Post a Comment

Popular posts from this blog

WriteUp PWN 500pts - PwC Hackaday

[Night St0rm CTF] - WRITE UP PWN