我们知道,Unix操作系统程序的链接分为静态链接和动态链接,静态链接就是把所有所引用到的函数或变量全部地编译到可执行文件中。今天我们就来学习下这方面的知识。
我们先来用GDB来研究一下Unix操作系统程序的反汇编。注意其中的一些部分。那就是if语句。如果条件失败,则会转到<main+75>。当然,用LD_PRELOAD无法影响表达式,其只能只能影响函数。于是,我们可以在printf上动点歪脑筋。
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048368 <main+0>:push %ebp
- 0x08048369 <main+1>:mov%esp,%ebp
- 0x0804836b <main+3>:sub$0x18,%esp
- 0x0804836e <main+6>:and$0xfffffff0,%esp
- 0x08048371 <main+9>:mov$0x0,%eax
- 0x08048376 <main+14>: add$0xf,%eax
- 0x08048379 <main+17>: add$0xf,%eax
- 0x0804837c <main+20>: shr$0x4,%eax
- 0x0804837f <main+23>: shl$0x4,%eax
- 0x08048382 <main+26>: sub%eax,%esp
- 0x08048384 <main+28>: movl $0x1,0xfffffffc(%ebp)
- 0x0804838b <main+35>: movl $0x2,0xfffffff8(%ebp)
- 0x08048392 <main+42>: mov0xfffffffc(%ebp),%eax
- 0x08048395 <main+45>: cmp0xfffffff8(%ebp),%eax
- 0x08048398 <main+48>: je 0x80483b3 <main+75>
- 0x0804839a <main+50>: sub$0xc,%esp
- 0x0804839d <main+53>: push $0x80484b0
- 0x080483a2 <main+58>: call 0x80482b0
- 0x080483a7 <main+63>: add$0x10,%esp
- 0x080483aa <main+66>: movl $0x0,0xfffffff4(%ebp)
- 0x080483b1 <main+73>: jmp0x80483ca <main+98>
- 0x080483b3 <main+75>: sub$0xc,%esp
- 0x080483b6 <main+78>: push $0x80484b8
- 0x080483bb <main+83>: call 0x80482b0
- 0x080483c0 <main+88>: add$0x10,%esp
- 0x080483c3 <main+91>: movl $0x1,0xfffffff4(%ebp)
- 0x080483ca <main+98>: mov0xfffffff4(%ebp),%eax
- 0x080483cd <main+101>: leave
- 0x080483ce <main+102>: ret
- End of assembler dump.
下面是我们Unix操作系统重载printf的so文件。让printf返回后的栈地址变成<main+75>。从而让程序接着执行。下面是so文件的源,都是让人反感的汇编代码。
- #include <stdarg.h>
- static int (*_printf)(const char *format, ...) = NULL;
- int printf(const char *format, ...)
- {
- if (_printf == NULL) {
- /* 取得标准库中的printf的函数地址 */
- _printf = (int (*)(const char *format, ...)) dlsym(RTLD_NEXT, "printf");
- /* 把函数返回的地址置到<main+75> */
- __asm__ __volatile__ (
- "movl 0x4(%ebp), %eax \n"
- "addl $15, %eax \n"
- "movl %eax, 0x4(%ebp)"
- );
- return 1;
- }
- /* 重置 printf的返回地址 */
- __asm__ __volatile__ (
- "addl $12, %%esp \n"
- "jmp *%0 \n"
- : /* no output registers */
- : "g" (_printf)
- : "%esp"
- );
- }
你可以在你的Unix操作系统下试试这段代码。
【编辑推荐】