Ld_preload provides a common way of injection is convenient, but also inconvenient: Injection library error after debugging more difficult. I have figured out a few days to find a workable method of debugging, certainly not the most effective way. Throw the burrow, hope to attract jade ~
First, write a piece of code as a normal dynamic library, exposing the interface for human invocation, as follows:
True.cint Fake (const char* s1,const char* s2) {return 0;} Gcc-g3-o0-o libtrue.so True.c-fpic-sharedecho "/root/desktop" >>/etc/ld.so.confldconfig
This is almost an empty function.
Here is the code that ld_preload will inject:
Fake.c#include <string.h> #include <stdio.h>int fake (const char* s1,const char* s2) {printf ("s1:%s-s2:%s\ n ", S1,s2), while (1) sleep (1); return 0;} Makefileall:gcc-g3-o0-fpic-shared-wa,-adlhn-c fake.c-fno-builtin-strcmp > Fake.cod Gcc-g3-o0-fpic-sha Red-o fake.so Fake.o-wl,-map,sym.map
FAKE.C generates a symbol map file in addition to the debug information, why?
Let's not explain why, first look at what's in Sym.map:
. Init 0x0000000000000498 0x18 * (. init). Init 0x0000000000000498 0x9/usr/lib/gcc/x86_64-re dhat-linux/4.4.7/. /.. /.. /.. /LIB64/CRTI.O 0x0000000000000498 _init. Init 0x00000000000004a1 0x5/usr/lib /GCC/X86_64-REDHAT-LINUX/4.4.7/CRTBEGINS.O. Init 0x00000000000004a6 0X5/USR/LIB/GCC/X86_64-REDHAT-LINUX/4 .4.7/crtends.o. Init 0x00000000000004ab 0x5/usr/lib/gcc/x86_64-redhat-linux/4.4.7/. /.. /.. /.. /LIB64/CRTN.O.PLT 0x00000000000004b0 0x40 * (. plt). PLT 0x00000000000004b0 0x40/usr/lib/g cc/x86_64-redhat-linux/4.4.7/. /.. /.. /.. /LIB64/CRTI.O * (. iplt). Text 0x00000000000004f0 0x148 * (. text.unlikely. text.*_unlikely) * (. Text. stub. Text . *. gnu.linkonce.t.*). Text 0x00000000000004f0 0x17/usr/lib/gcc/x86_64-redhat-linux/4.4.7/. /.. /.. /.. /LIB64/CRTI.O *fill* 0x0000000000000507 0x9 90909090. Text 0x0000000000000510 0xaa/usr/lib/gcc/x86_64-redhat-linux/4.4.7/crtbegins.o *fill* 0x00000000000005ba 0x2 90909090 . Text 0X00000000000005BC 0x40 fake.o 0X00000000000005BC fake *fill* 0X00000000000005FC 0x4 90909090. Text 0x0000000000000600 0x36/usr/lib/gcc/x86_64-redhat-linux/4.4.7 /CRTENDS.O *fill* 0x0000000000000636 0x2 90909090. Text 0x0000000000000638 0X0/USR/LIB/GCC /x86_64-redhat-linux/4.4.7/. /.. /.. /.. /LIB64/CRTN.O * (. gnu.warning). Fini 0x0000000000000638 0xe * (. fini). Fini 0x0000000000000638 0x4/usr/lib/gcc/x86_64-redhat-linux/4.4.7/. /.. /.. /.. /LIB64/CRTI.O 0x0000000000000638 _fini. Fini 0x000000000000063c 0x5/usr/lib /GCC/X86_64-REDHAT-LINUX/4.4.7/CRTBEGINS.O. Fini 0x0000000000000641 0X5/USR/LIB/GCC/X86_64-REDHAT-LINUX/4 .4.7/. /.. /.. /.. /LIB64/CRTN.O 0x0000000000000646 provide (__etext,.) 0x0000000000000646 provide (_etext,.) 0x0000000000000646 provide (etext,.)
Only the Sym.map code snippet is intercepted here. There is a. init section in the Code snippet. Text section. Fini section. Each section is made up of Ownchoice. o files, such as the CRTI.O associated with the CRT runtime library and the FAKE.O generated fake.c after compilation. After the compiler compiles the source code into an. O intermediate file, you also need to connect all the intermediate files to the same page properties and assign the link addresses (for a detailed description of the compilation connection, see < Programmer's self-cultivation >). The Sym.map file shows the offset of each. o file in the entire fake.so file when the link is displayed: such as FAKE.O offset in the file is 0X5BC
Now explain why you need to Sym.map: Because fake.so is a dynamic library, when the program runs, the location that is loaded into memory is not fixed. Because of his non-fixation, it is difficult to break the breakpoint or disassembly. However, after the program is running, you can view the process memory load by Cat/proc/pidnum/maps and get the base address of the fake.so load. With the base address, plus the offset, you can determine the specific address of the code provided by FAKE.C in the process space:
The figure shows that the fake.so is loaded into address 7ffff7deb000-7ffff7dee000, where 7ffff7deb000 is the base. In addition to the offset shown in the previous sym.map, it is now possible to predict the functions provided by fake at address 7FFFF7DEB5BC.
Continue down, with a dynamic library, and a test file to invoke the Dynamic library interface:
Test.c#include <string.h> #include <unistd.h>extern int fake (const char* s1,const char* s2); int main () {if ( Fake ("1", "2") = = 0) {printf ("nothing\n");} return 0;} Gcc-o Test Test.cstrip--strip-all Test
In order to compare the real environment of simulating a program published by others, test.c not only generates debug information, but also strips the symbol table.
The following starts the injection and starts debugging.
Export LD_PRELOAD=/ROOT/DESKTOP/FAKE.SOGDB Test
Because there is no debug information, GDB cannot find the main function, so the breakpoint cannot be broken under the main function, which directly causes the program to run after start:
(GDB) Start Function "main" not defined. Make breakpoint pending on the future shared library load? (Y or [n]) nstarting program:/root/desktop/test s1:1-s2:2
OK, now you can only re-debug it and try to find out where the program started:
[Email protected] desktop]# GDB Test (GDB) info files Symbols from "/root/desktop/test". Local exec file: '/root/desktop/test ', file type elf64-x86-64. Entry point:0x400520
This will get the entry of the program, and at this point the breakpoint then start to run, the program at 0x400520 stop:
At this point, the various dynamic libraries that depend on the process have already been loaded and can see the memory load:
[[email protected] ~]# PS x|grep test 4352 pts/8 s+ 0:00 gdb test& nbsp;4381 pts/8 t 0:00/root/desktop/test[[email protected] ~] # cat/proc/4381/maps 00400000-00401000 R-xp 00000000 fd:00 131451 /root/desktop/test00600000-00601000 Rw-p 00000000 fd:00 131451 /root/desktop/test3326400000-3326420000 R-xp 00000000 fd:00 75830 /lib64/ld-2.12.so332661f000-3326620000 r--p 0001f000 fd:00 75830 /lib64/ld-2.12.so3326620000-3326621000 rw-p 00020000 fd:00 75830 /lib64/ld-2.12.so3326621000-3326622000 Rw-p 00000000 00:00 0 3326c00000-3326d8b000 R-xp 00000000 FD : 75831 /lib64/libc-2.12.so3326d8b000-3326f8a000---p 0018b000 fd:00 75831 /lib64/libc-2.12.so3326f8a000-3326f8e000 r--p 0018a000 fd:00 75831 /lib64/libc-2.12.so3326f8e000-3326f8f000 rw-p 0018e000 fd:00 75831 /lib64/libc-2.12.so3326f8f000-3326f94000 Rw-p 00000000 00:00 0 7ffff7bea000-7ffff7bed000 Rw-p 00000000 00:00 0 7ffff7bed000-7ffff7bee000 R-xp 00000000 fd:00 136044 & nbsp; /root/ desktop/libtrue.so7ffff7bee000-7ffff7ded000---p 00001000 fd:00 136044 /root/desktop/ libtrue.so7ffff7ded000-7ffff7dee000 Rw-p 00000000 fd:00 136044 /root/desktop/ libtrue.so7ffff7dfc000-7ffff7dfd000 R-xp 00000000 FD: 136014 /root/desktop/fake.so7ffff7dfd000-7ffff7ffc000---p 00001000 fd:00 136014 / root/desktop/fake.so7ffff7ffc000-7ffff7ffd000 Rw-p 00000000 fd:00 136014 /root/desktop/ fake.so7ffff7ffd000-7ffff7ffe000 Rw-p 00000000 00:00 0 7ffff7ffe000-7ffff7fff000 R-xp 00000000 00:00 0 [vdso]7ffffffea000-7ffffffff000 Rw-p 00000000 00:00 0 [STACK]FFFfffffff600000-ffffffffff601000 R-xp 00000000 00:00 0 [Vsyscall]
Well, fake.so in 7FFFF7DFC000,FAKE.O should be at 7FFFF7DFC5BC. It can also be seen that the libtrue.so covered by the ld_preload is loaded into the 7ffff7bed000 place.
Can be directly in this position down, of course, you can not rest assured that the test with Objdump to see the disassembly:
[[email protected] desktop]# objdump-d testdisassembly of section. Plt:00000000004004d8 <[email protected]>: 4004d8: ff D2 00 pushq 0X2004D2 (%rip) # 6009b0 <_fini+0x2002a8> 4004de: ff d4 00 jmpq *0x2004d4 (%rip) & nbsp; # 6009b8 <_fini+0x2002b0> 4004e4: 0f 1f 00 & nbsp; nopl 0x0 (%rax) 00000000004004e8 <[email protected]>: 4004e8: ff D2 00 jmpq *0X2004D2 (%rip) # 6009c0 <_fini+0x2002b8> 4004ee: 68 xx 00 pushq $0x0 4004f3: e9 e0 FF FF ff &NBSP;JMPQ 4004d8 <_init+0x18>, ..... 0000000000400520 <.text>: 400520: 31 ed xor %ebp,%ebp 400522: 49 d1 mov %rdx,%r9 400525: 5e pop %rsi 400526: 48 e2 mov %rsp,%rdx 400529: 48 e4 f0 &Nbsp;and $0xfffffffffffffff0,%rsp 40052d: 50 push %rax 40052e: 54 push %rsp 40052f: &NBSP;49 C7 C0-$0x400630,%r8 400536: 4 8 C7 C1, mov $0x400640,%rcx 40053d: 48 C7 C7 04 06 mov $0x400604,%rdi 400544: e8 BF ff FF ff callq 400508 <[email protected]>
which
00000000004004e8 <[email protected]>: 4004e8:ff D2, JMPQ *0x2004d2 (%rip) # 6009c0 &L T;_fini+0x2002b8> 4004ee:68 (XX) Pushq $0x0 4004f3:e9 e0 FF FF FF JMPQ 4004D8 & Lt;_init+0x18>
Is the address of the function jump that the test exported to fake.so, where it can also be the next breakpoint.
======================================================================
Note that when testing this code, I have closed the random address load so the connection address of the objdump-d output is the same as the test load address, both 0x400520. The method of closing random address loading is as follows:
======================================================================
Continue running, the program 0x4004e8 to stop after the disassembly to see, and then continue to run into the fake.so
(GDB) Ccontinuing.breakpoint 2, 0x00000000004004e8 in [email protected] (GDB) x/32i $pc = 0x4004e8 <[email Protec TED]>:JMPQ *0x2004d2 (%rip) # 0x6009c0 <[email protected]> 0x4004ee <[email protected]+6> :p Ushq $0x0 0x4004f3 <[email protected]+11>:jmpq 0x4004d8
(GDB) Ccontinuing.breakpoint 3, Fake (s1=0x3326621188 "", s2=0x332640e9f0 "uh\211\345awavauate1\344s1\333h\203\354hh\ 307e\250 ") at fake.c:55{(gdb) x/32i $pc (gdb) x/32i $pc = = 0X7FFFF7DFC5BC <fake>: push %rbp 0x7ffff7dfc5bd <fake+1>: mov %RSP,%RBP 0x7ffff7dfc5c0 <fake+4>: sub $0x10,%rsp 0X7FFFF7DFC5C4 <fake+8>: mov %rdi,-0x8 (%RBP) 0x7ffff7dfc5c8 <fake+12>: mov %rsi,-0x10 (%RBP) 0x7ffff7dfc5cc <fake+16 >: lea 0x73 (%rip),%rax # 0x7ffff7dfc646 0x7ffff7dfc5d3 <fake+23>: mov -0x10 (%RBP),% rdx 0x7ffff7dfc5d7 <fake+27>: mov -0x8 (%RBp),%rcx 0x7ffff7dfc5db <fake+31>: mov %rcx,%rsi 0X7FFFF7DFC5DE <fake+34>: mov %rax,%rdi 0x7ffff7dfc5e1 < fake+37>: mov $0x0,%eax 0x7ffff7dfc5e6 <fake+42>: callq 0x7ffff7dfc4c0 <[email protected]> 0x7ffff7dfc5eb <fake+47>: mov $0x1,%edi 0x7ffff7dfc5f0 <fake+52>: mov $0x0,%eax 0x7ffff7dfc5f5 <fake+57>: callq 0x7ffff7dfc4e0 <[email protected]> 0x7ffff7dfc5fa <fake+62>: jmp 0x7ffff7dfc5eb <fake+47>
In this disassembly code, we see 2 functions: Printf/sleep, a bit like the code in FAKE.C.
Because, fake.so is the source code compiled, you can see the source code, and the next breakpoint:
0x7ffff7dfc604 <__do_global_ctors_aux+4>:p Ush
Of course, view variables are also supported:
At this point, debug ld_preload injected so file end, 3q
Qq:[email protected]
Debugging code injected by Ld_preload