歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> Unix資訊 >> 學習Unix操作系統知識

學習Unix操作系統知識

日期:2017/3/6 11:41:06   编辑:Unix資訊

我們知道,Unix操作系統程序的鏈接分為靜態鏈接和動態鏈接,靜態鏈接就是把所有所引用到的函數或變量全部地編譯到可執行文件中。今天我們就來學習下這方面的知識。

我們先來用GDB來研究一下Unix操作系統程序的反匯編。注意其中的一些部分。那就是if語句。如果條件失敗,則會轉到<main+75>。當然,用LD_PRELOAD無法影響表達式,其只能只能影響函數。於是,我們可以在printf上動點歪腦筋。

  1. (gdb) disassemble main
  2. Dump of assembler code for function main:
  3. 0x08048368 <main+0>:push %ebp
  4. 0x08048369 <main+1>:mov%esp,%ebp
  5. 0x0804836b <main+3>:sub$0x18,%esp
  6. 0x0804836e <main+6>:and$0xfffffff0,%esp
  7. 0x08048371 <main+9>:mov$0x0,%eax
  8. 0x08048376 <main+14>: add$0xf,%eax
  9. 0x08048379 <main+17>: add$0xf,%eax
  10. 0x0804837c <main+20>: shr$0x4,%eax
  11. 0x0804837f <main+23>: shl$0x4,%eax
  12. 0x08048382 <main+26>: sub%eax,%esp
  13. 0x08048384 <main+28>: movl $0x1,0xfffffffc(%ebp)
  14. 0x0804838b <main+35>: movl $0x2,0xfffffff8(%ebp)
  15. 0x08048392 <main+42>: mov0xfffffffc(%ebp),%eax
  16. 0x08048395 <main+45>: cmp0xfffffff8(%ebp),%eax
  17. 0x08048398 <main+48>: je 0x80483b3 <main+75>
  18. 0x0804839a <main+50>: sub$0xc,%esp
  19. 0x0804839d <main+53>: push $0x80484b0
  20. 0x080483a2 <main+58>: call 0x80482b0
  21. 0x080483a7 <main+63>: add$0x10,%esp
  22. 0x080483aa <main+66>: movl $0x0,0xfffffff4(%ebp)
  23. 0x080483b1 <main+73>: jmp0x80483ca <main+98>
  24. 0x080483b3 <main+75>: sub$0xc,%esp
  25. 0x080483b6 <main+78>: push $0x80484b8
  26. 0x080483bb <main+83>: call 0x80482b0
  27. 0x080483c0 <main+88>: add$0x10,%esp
  28. 0x080483c3 <main+91>: movl $0x1,0xfffffff4(%ebp)
  29. 0x080483ca <main+98>: mov0xfffffff4(%ebp),%eax
  30. 0x080483cd <main+101>: leave
  31. 0x080483ce <main+102>: ret
  32. End of assembler dump.

下面是我們Unix操作系統重載printf的so文件。讓printf返回後的棧地址變成<main+75>。從而讓程序接著執行。下面是so文件的源,都是讓人反感的匯編代碼。

  1. #include <stdarg.h>
  2. static int (*_printf)(const char *format, ...) = NULL;
  3. int printf(const char *format, ...)
  4. {
  5. if (_printf == NULL) {
  6. /* 取得標准庫中的printf的函數地址 */
  7. _printf = (int (*)(const char *format, ...)) dlsym(RTLD_NEXT, "printf");
  8. /* 把函數返回的地址置到<main+75> */
  9. __asm__ __volatile__ (
  10. "movl 0x4(%ebp), %eax \n"
  11. "addl $15, %eax \n"
  12. "movl %eax, 0x4(%ebp)"
  13. );
  14. return 1;
  15. }
  16. /* 重置 printf的返回地址 */
  17. __asm__ __volatile__ (
  18. "addl $12, %%esp \n"
  19. "jmp *%0 \n"
  20. : /* no output registers */
  21. : "g" (_printf)
  22. : "%esp"
  23. );
  24. }

你可以在你的Unix操作系統下試試這段代碼。

Copyright © Linux教程網 All Rights Reserved