歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> Unix資訊

學習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. );  

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

Copyright © Linux教程網 All Rights Reserved