-
Notifications
You must be signed in to change notification settings - Fork 24
0x07. Inject Shared Libraries into Executables
While a program is executing, utilizing system calls like ptrace enables you to attach to and debug the target process. Injecting code or dynamic link library (DLL/SO) files into a running process dynamically is typically straightforward. However, injecting DLL/SO into an inactive program(static ELF file) poses challenges. In a prior chapter, we covered static injection of parasitic code. In this section, we will delve into the injection of shared libraries into ELF files.
For binary crackme.bin, the flag will be printed only when the user enters the correct username and password
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ ./crackme.bin tom 123
Wrong password!The username and password detection logic is implemented in check.so. The source code is as follows
int check_username(char* input) {
if (strcmp(input, "tom"))
return 0;
else
return 1;
}
int check_password(char* input) {
if (strcmp(input, "654321"))
return 0;
else
return 1;
}We must now adjust the logic and update the check function. In practical scenarios, check.so typically contains intricate code, making direct replacement challenging. Leveraging static injection allows us to seamlessly substitute a small portion of the codebase.
- Use the
elfspiritediting module, statically inject a fakeso - Use the
elfspiritediting module, modify the external symbol called by ELF and call thesowe just injected
The code of the parasitic code/shellcode/malicious so is as follows. This is mainly to re-implement the detection logic
int my_check_username(char* input) {
return 1;
}
int my_check_password(char* input) {
return 1;
}Inject the target so file(my.so) into the target file. Before injecting, find a suitable location in the .dynamic section to load so
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ elfspirit parse -L crackme.bin
[+] Dynamic link information
[+] Dynamic section at offset 0x2d70 contains 33 entries
[Nr] Tag Type Name/Value
[ 0] 00000001 DT_NEEDED Shared library: [check.so]
[ 1] 00000001 DT_NEEDED Shared library: [libc.so.6]
[ 2] 0000001d DT_RUNPATH 0xeb [./]
[ 3] 0000000c DT_INIT 0x1000
[ 4] 0000000d DT_FINI 0x1388
[ 5] 00000019 DT_INIT_ARRAY 0x3d60
[ 6] 0000001b DT_INIT_ARRAYSZ 0x8
[ 7] 0000001a DT_FINI_ARRAY 0x3d68
[ 8] 0000001c DT_FINI_ARRAYSZ 0x8
...
[25] 6fffffff DT_VERNEEDNUM 0x1
[26] 6ffffff0 DT_VERSYM 0x616
[27] 6ffffff9 DT_RELACOUNT 0x3
[28] 00000000 DT_NULL 0x0
[29] 00000000 DT_NULL 0x0
[30] 00000000 DT_NULL 0x0
[31] 00000000 DT_NULL 0x0
[32] 00000000 DT_NULL 0x0 inject so
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ elfspirit edit -L -i28 -j0 -m1 crackme.bin
0->1
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ elfspirit edit -L -i28 -j2 -smy.so crackme.bin
->my.so
0x0->0xee
[*] dynamic strtab addr: 0x528, size: 0xee
[*] program header table is not at the end of the file
[*] move program header table
[*] move the phdr: 244
[*] get the phdr load index: [13]
[*] add a phdr
[*] add segment successfully: [14]
[*] set phdr
528->8f78
ee->f4
[*] set shdr
528->3f78
528->8f78
ee->f4Check if the injection was successful
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ ldd crackme.bin
linux-vdso.so.1 (0x00007ffee550d000)
check.so => ./check.so (0x000076cb3f4b6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000076cb3f200000)
my.so => ./my.so (0x000076cb3f4a1000)
/lib64/ld-linux-x86-64.so.2 (0x000076cb3f4c7000)After injecting so, we need to consider how to run our own so code. Here, we directly use symbol replacement to hijack the check functions.
Find the coordinates of check_password and check_username
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ elfspirit parse -D crackme.bin
[+] .dynsym table
[Nr] Value Size Type Bind Vis Ndx Name
[ 0] 00000000 0 NOTYPE LOCAL DEFAULT 0
[ 1] 00000000 0 FUNC GLOBAL DEFAULT 0 decrypt
[ 2] 00000000 0 FUNC GLOBAL DEFAULT 0 __libc_st[...]
[ 3] 00000000 0 NOTYPE WEAK DEFAULT 0 _ITM_dere[...]
[ 4] 00000000 0 FUNC GLOBAL DEFAULT 0 puts
[ 5] 00000000 0 FUNC GLOBAL DEFAULT 0 __stack_c[...]
[ 6] 00000000 0 FUNC GLOBAL DEFAULT 0 printf
[ 7] 00000000 0 FUNC GLOBAL DEFAULT 0 getchar
[ 8] 00000000 0 NOTYPE WEAK DEFAULT 0 __gmon_start__
[ 9] 00000000 0 FUNC GLOBAL DEFAULT 0 check_password
[10] 00000000 0 FUNC GLOBAL DEFAULT 0 exit
[11] 00000000 0 FUNC GLOBAL DEFAULT 0 check_username
[12] 00000000 0 NOTYPE WEAK DEFAULT 0 _ITM_regi[...]
[13] 00000000 0 FUNC WEAK DEFAULT 0 __cxa_finalizeDirectly replace the function
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ elfspirit edit -D -i9 -j6 -smy_check_password crackme.bin
check_password->my_check_password
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ elfspirit edit -D -i11 -j6 -smy_check_username crackme.bin
check_username->my_check_usernameThe target program has successfully loaded our so.
At this time, if we run the target program, we will find that no matter what account name and password we enter, the flag will be printed.
jerry@jerry-virtual-machine:~/elfspirit/examples/07_inject_so$ ./crackme.bin 1 1
flag{You_Got_first_lucky_CHARM_of_2025}- 0x01. Play with Symbol
- 0x02. Implement ELF Static Hook by Injecting .got.plt
- 0x03. ELF Virus Technology: ELF Infection
- 0x04. Transform EXE into LIB
- 0x05. Analyze Binary Protection Flags
- 0x06. Obfuscate ELF
- 0x07. Inject Shared Libraries into Executables
- 0x08. Infect ELF Interpreter
- 0x09. Forensics
- 0x10. Other Topics