2015-04-07 18 views
5

Để nghiên cứu cách tệp đối tượng được tải và chạy trong linux, tôi đã tạo mã c đơn giản nhất, tên tệp simple.c.cách thức hoạt động của __libc_start_main @ plt?

int main(){} 

Tiếp theo, tôi tạo tệp đối tượng và lưu tệp đối tượng dưới dạng tệp văn bản.

$gcc ./simple.c 
$objdump -xD ./a.out > simple.text 

Từ nhiều bài viết internet, tôi có thể bắt gcc đó tự động tải chức năng bắt đầu như _start, _init, __libc_start_main @ plt, và vân vân. Vì vậy, tôi bắt đầu đọc mã lắp ráp của tôi, được hỗ trợ bởi http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html.

Dưới đây là một số phần của mã lắp ráp.

080482e0 <[email protected]>: 
80482e0:  ff 25 10 a0 04 08  jmp *0x804a010 
80482e6:  68 08 00 00 00   push $0x8 
80482eb:  e9 d0 ff ff ff   jmp 80482c0 <_init+0x2c> 

Disassembly of section .text: 

080482f0 <_start>: 
80482f0:  31 ed     xor %ebp,%ebp 
80482f2:  5e      pop %esi 
80482f3:  89 e1     mov %esp,%ecx 
80482f5:  83 e4 f0    and $0xfffffff0,%esp 
80482f8:  50      push %eax 
80482f9:  54      push %esp 
80482fa:  52      push %edx 
80482fb:  68 70 84 04 08   push $0x8048470 
8048300:  68 00 84 04 08   push $0x8048400 
8048305:  51      push %ecx 
8048306:  56      push %esi 
8048307:  68 ed 83 04 08   push $0x80483ed 
804830c:  e8 cf ff ff ff   call 80482e0 <[email protected]> 
8048311:  f4      hlt 
8048312:  66 90     xchg %ax,%ax 
8048314:  66 90     xchg %ax,%ax 
8048316:  66 90     xchg %ax,%ax 
8048318:  66 90     xchg %ax,%ax 
804831a:  66 90     xchg %ax,%ax 
804831c:  66 90     xchg %ax,%ax 
804831e:  66 90     xchg %ax,%ax 

080483ed <main>: 
80483ed:  55      push %ebp 
80483ee:  89 e5     mov %esp,%ebp 
80483f0:  b8 00 00 00 00   mov $0x0,%eax 
80483f5:  5d      pop %ebp 
80483f6:  c3      ret 
80483f7:  66 90     xchg %ax,%ax 
80483f9:  66 90     xchg %ax,%ax 
80483fb:  66 90     xchg %ax,%ax 
80483fd:  66 90     xchg %ax,%ax 
80483ff:  90      nop 



... 

Disassembly of section .got: 

08049ffc <.got>: 
8049ffc:  00 00     add %al,(%eax) 
     ... 

Disassembly of section .got.plt: 

0804a000 <_GLOBAL_OFFSET_TABLE_>: 
804a000:  14 9f     adc $0x9f,%al 
804a002:  04 08     add $0x8,%al 
     ... 
804a00c:  d6      (bad) 
804a00d:  82      (bad) 
804a00e:  04 08     add $0x8,%al 
804a010:  e6 82     out %al,$0x82 
804a012:  04 08     add $0x8,%al 

Câu hỏi của tôi là;

Trong 0x804830c, 0x80482e0 được gọi (Tôi đã nắm bắt các hướng dẫn trước đó).

Trong 0x80482e0, quá trình chuyển đến 0x804a010.

Trong 0x804a010, hướng dẫn là < ra% al, $ 0x82>

... chờ đợi. chỉ ra? Có gì trong% al và 0x82 ở đâu ?? Tôi đã bị mắc kẹt trong dòng này.

Vui lòng trợ giúp ....

* p.s. Tôi mới bắt đầu với Linux và hệ điều hành. Tôi đang nghiên cứu các khái niệm hệ điều hành theo lớp học, nhưng vẫn không thể tìm ra cách học ngôn ngữ lắp ráp Linux phù hợp. Tôi đã tải về hướng dẫn sử dụng bộ xử lý intel nhưng nó quá lớn để đọc. Có ai có thể thông báo cho tôi tài liệu tốt cho tôi không? Cảm ơn.

Trả lời

6
80482e0:  ff 25 10 a0 04 08  jmp *0x804a010 

Điều này có nghĩa là "truy xuất địa chỉ 4 byte được lưu trữ ở 0x804a010 và chuyển đến địa chỉ đó".

804a010:  e6 82     out %al,$0x82 
804a012:  04 08     add $0x8,%al 

4 byte đó sẽ được coi là địa chỉ, 0x80482e6, không phải như hướng dẫn.

80482e0:  ff 25 10 a0 04 08  jmp *0x804a010 
80482e6:  68 08 00 00 00   push $0x8 
80482eb:  e9 d0 ff ff ff   jmp 80482c0 <_init+0x2c> 

Vì vậy, chúng tôi vừa thực hiện một hướng dẫn đã chuyển chính xác cho chúng tôi một hướng dẫn. Tại thời điểm này, bạn có thể tự hỏi nếu có một lý do chính đáng cho việc này.

Có. Đây là một triển khai PLT/GOT điển hình. Chi tiết hơn, bao gồm sơ đồ, nằm ở số Position Independent Code in shared libraries: The Procedure Linkage Table.

Mã thực tế cho __libc_start_main nằm trong thư viện được chia sẻ, glibc.Trình biên dịch và thời gian biên dịch liên kết không biết nơi mã sẽ có mặt tại thời gian chạy, vì vậy họ đặt trong chương trình biên soạn của bạn một __libc_start_main chức năng ngắn mà chỉ có ba hướng dẫn:

  • nhảy đến một vị trí được xác định bởi lần thứ 4 (hoặc 5, tùy thuộc vào việc bạn muốn đếm từ 0 hoặc 1) mục trong GOT
  • push $ 8 vào stack
  • nhảy đến một trình giải quyết thói quen

lần đầu tiên bạn gọi __libc_start_main , mã phân giải sẽ chạy. Nó sẽ tìm thấy vị trí thực tế của __libc_start_main trong một thư viện được chia sẻ và sẽ vá mục 4 của GOT là địa chỉ đó. Nếu chương trình của bạn gọi lại __libc_start_main, lệnh jmp *0x804a010 sẽ đưa chương trình trực tiếp đến mã trong thư viện được chia sẻ.

Có ai có thể thông báo cho tôi tài liệu tốt cho tôi không?

Cuốn sách x86 Assembly tại Wikibooks có thể là một nơi để bắt đầu.

+0

Thật là một lời giải thích thú vị! Cảm ơn! – casamia

+0

Tôi nghi ngờ rằng '__libc_start_main' được cho là sẽ gọi chính chương trình và thực hiện cuộc gọi hệ thống để thoát với giá trị trả về. Bạn có quan tâm đến việc mở rộng sự cần thiết của 'hlt' (tôi nghi ngờ nó cho phép các trường hợp có sự chậm trễ/cuộc đua với dọn dẹp trong lối thoát sys),' hlt' là một hướng dẫn đặc quyền, là điểm chỉ để bẫy vào bất hợp pháp hướng dẫn nếu nó đến đó? Điều gì về sự trượt của 'xchg'? –

+0

* xchg nop sled. –

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