Search This Blog

Wednesday, October 7, 2009

DLL Injection

DLL Injection is a method by which some code is run within the address space of any process by forcing it to load a dynamic-link library.

Library interposition is a useful technique for tuning performance, collecting runtime statistics, or debugging applications. With dynamic linking, you can intercept any function call an application makes to any shared library. Once you intercept it, you can do whatever you want in that function, as well as call the real function the application originally intended to call.

However this feature may also be exploited for some malicious use.

In Linux, the environment variable LD_PRELOAD allows specified libraries to be loaded before any other code.

This variable if set to some code which has a function in it with the constructor attribute, then the control will always go the library code first and then to any other code.

lets look at an example,
The code which will be loaded dynamically :


//demo.c

void __attribute__((constructor)) init() {
printf("How did it come to me??? ;) ;) ");
}

//End of file demo.c

$ gcc -shared demo.c -o demo.so -fPIC
$ export LD_PRELOAD=$PWD/demo.so true

Now execute any command :

$ ls
How did it come to me??? ;) ;) a aj.c a.out arr.s demo.so demo.c

$ gcc a.c
How did it come to me??? ;) ;) How did it come to me??? ;) ;) How did it come to me??? ;) ;) How did it come to me??? ;) ;) How did it come to me??? ;) ;)

$ ps
How did it come to me??? ;) ;) PID TTY TIME CMD
24126 pts/61 00:00:00 ps
28996 pts/61 00:00:00 bash



It doesnt end here...There is something more to it.
As the man page for LD_PRELOAD states "This can be used to selectively override functions in other shared libraries."

see this :

// --- demo.c ---

int printf(char *s, ...) {
fprintf(stdout, "Where is ur printf??? ;) ;) ");
}

// End of demo.c

// --- a.c ----

int main()
{
printf("Hello world");
}

// End of a.c

$ gcc a.c
$ ./a.out
Where is ur printf??? ;) ;)



One way out is.... using static-linking.....
eg :
For the above printf wala code

$ gcc -static a.c
$ ./a.out
Hello



This is because if static linking is done, the control never goes to the dynamic linker as u see below :

$ readelf -d a.out

There is no dynamic segment in this file.

Sunday, October 4, 2009

Allocating memory on heap and stack

The very famous "malloc" allocates space on the heap and returns a pointer to the allocated space.

But there also exists a function which can allocate space on stack frame.

The "alloca" function allocates size bytes of space in the stack frame of the caller. This temporary space is automatically freed when the function that called alloca returns to its caller.

The alloca function returns a pointer to the beginning of the allocated space. However, if the allocation causes stack overflow, program behaviour is undefined.

Allocation on the stack is more convenient and cheaper, but the maximum stack size is limited. It may cause stack overflow if your program allocates large memory on the stack. In addition, allocating large arrays on the stack may fool valgrind . Usually, large arrays should be allocated on the heap.


example :
With malloc :

#include

int main()
{
char *str = (char *)malloc(sizeof(char) * 10);
printf("%p\n",str);
printf("PID = %d\n",getpid());
getchar();
}



$ ./a.out
0x804a008
PID = 16637



$ cat /proc/16637/maps
08048000-08049000 r-xp 00000000 00:15 18172215 /home/fshaikh/trial/a.out
08049000-0804a000 rwxp 00000000 00:15 18172215 /home/fshaikh/trial/a.out
0804a000-0806b000 rwxp 0804a000 00:00 0 [heap]
f7e3d000-f7e3e000 rwxp f7e3d000 00:00 0
f7e3e000-f7f68000 r-xp 00000000 fe:00 1509438 /lib/tls/libc-2.3.2.so
f7f68000-f7f71000 rwxp 00129000 fe:00 1509438 /lib/tls/libc-2.3.2.so
f7f71000-f7f73000 rwxp f7f71000 00:00 0
f7f79000-f7f7c000 rwxp f7f79000 00:00 0
f7f7c000-f7f92000 r-xp 00000000 fe:00 1474565 /lib/ld-2.3.2.so
f7f92000-f7f93000 rwxp 00015000 fe:00 1474565 /lib/ld-2.3.2.so
ffb03000-ffb05000 rw-p ffb03000 00:00 0 [stack]
ffffe000-fffff000 r-xp ffffe000 00:00 0 [vdso]



With alloca :

#include

int main()
{
char *str = (char *)alloca(sizeof(char) * 10);
printf("%p\n",str);
printf("PID = %d\n",getpid());
getchar();
}

$ ./a.out
0xfff26c08
PID = 1324

$ cat /proc/1324/maps
08048000-08049000 r-xp 00000000 00:15 18172215 /home/fshaikh/trial/a.out
08049000-0804a000 rwxp 00000000 00:15 18172215 /home/fshaikh/trial/a.out
f7df0000-f7df1000 rwxp f7df0000 00:00 0
f7df1000-f7f1b000 r-xp 00000000 fe:00 1509438 /lib/tls/libc-2.3.2.so
f7f1b000-f7f24000 rwxp 00129000 fe:00 1509438 /lib/tls/libc-2.3.2.so
f7f24000-f7f26000 rwxp f7f24000 00:00 0
f7f2c000-f7f2f000 rwxp f7f2c000 00:00 0
f7f2f000-f7f45000 r-xp 00000000 fe:00 1474565 /lib/ld-2.3.2.so
f7f45000-f7f46000 rwxp 00015000 fe:00 1474565 /lib/ld-2.3.2.so
fff26000-fff28000 rw-p fff26000 00:00 0 [stack]
ffffe000-fffff000 r-xp ffffe000 00:00 0 [vdso]


Wednesday, September 30, 2009

Sleep-ing in pthread

Using any variant of sleep for pthreads, the behaviour is not guaranteed. All the threads can also sleep since the kernel is not aware of the different threads. Hence a solution is required which the pthread library can handle rather than the kernel.

A safer and cleaner solution to use is the pthread_cond_timedwait...


pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;

void mywait(int timeInSec)
{
struct timespec timeToWait;
struct timeval now;
int rt;

gettimeofday(&now,NULL);

timeToWait.tv_sec = now.tv_sec + timeInSec;
timeToWait.tv_nsec = now.tv_usec*1000;

pthread_mutex_lock(&fakeMutex);
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
pthread_mutex_unlock(&fakeMutex);
printf("\nDone\n");
}

void* fun(void* arg)
{
printf("\nIn thread\n");
mywait(5);
}

int main()
{
pthread_t thread;
void *ret;

pthread_create(&thread, NULL, fun, NULL);
pthread_join(thread,&ret);
}

For pthread_cond_timedwait , you need to specify how much time to wait from current time.

Now by the use of the function mywait() only the thread calling it will sleep and not the other pthreads.

Note : I have not checked the return values of the functions for error. Please do the same.

Thursday, September 17, 2009

Default Path for #include

This is what i got when i googled about "how to check the default path for include"

echo | gcc -v -x c -E -

Reading specs from /usr/lib/gcc-lib/i486-linux/3.3.5/specs
Configured with: ../src/configure -v --enable-languages=c,c++,java,f77,pascal,objc,ada,treelang --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared --enable-__cxa_atexit --with-system-zlib --enable-nls --without-included-gettext --enable-clocale=gnu --enable-debug --enable-java-gc=boehm --enable-java-awt=xlib --enable-objc-gc i486-linux
Thread model: posix
gcc version 3.3.5 (Debian 1:3.3.5-13)
/usr/lib/gcc-lib/i486-linux/3.3.5/cc1 -E -quiet -v -D__GNUC__=3 -D__GNUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=5 -
ignoring nonexistent directory "/usr/i486-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/gcc-lib/i486-linux/3.3.5/include
/usr/include
End of search list.
...
...
...


Tuesday, September 15, 2009

Boot Loader

In the simplest of terms, a boot loader is something which loads the OS.

It basically performs the following tasks :

- decide what to load
- load the kernel and additional data such as initrd or parameters for the kernel
- set up an execution environment suitable for the kernel
- run the kernel

Types of boot loaders :

There are different types of boot-loaders depending upon how they interact with the underlying system.

a) Specialized loaders

They are typically aware of only one storage device. eg : flash memory or floppy disk on which a small number of kernels is stored in some format specific to the boot-loader.
eg: SYSLINUX, LinuxBIOS

b) General loaders running under other operating system

They normally use the services provided by the host operating system for reading the kernel image and additional data. Disadvantages of this approach are (i) slow loading and (ii) problem of overwriting the host OS while loading the other OS.
eg: LOADLIN

c) File-system aware general loaders running on firmware

They are little operating systems by themselves. They know the structure of one or more filesystems. They access the devices via the services provided by the firmware and sometimes they may have their own drivers to access hardware directly.
eg: GRUB


d) File-system unaware general loaders running on firmware

They rely on third-party to map the on-disk data structures to a more general and convenient representation.
eg:LILO


Lets have a look at the GRUB MBR :)

MBR is a 512-byte sector located in the first sector of the disk i.e. sector 1 of cylinder 0, head 0.
GRUB usually replaces the MBR when linux is installed. But it maintains the same structure as the MBR.
i.e. 446 bytes - Executable code and error messages
64 bytes - Partition table
2 bytes - Magic number (0xAA55)

To take a hexdump of the GRUB MBR code ,
# dd if=/dev/sda of=mbr.bin bs=512 count=1

# hexdump -Cv mbr.bin | less

00000000 eb 48 90 00 00 00 00 00 00 00 00 00 00 00 00 00 |ëH..............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 02 |................|
00000040 ff 00 00 20 01 00 00 00 00

The first three bytes specify a Jmp instruction. so the execution jumps over 71 bytes which is also called the BIOS Parameter Block(BPB) and is marked in blue.




00000160 00 eb 0e be 84 7d e8 38 00 eb 06 be 8e 7d e8 30 |.ë.¾.}è8.ë.¾.}è0|
00000170 00 be 93 7d e8 2a 00 eb fe 47 52 55 42 20 00 47 |.¾.}è*.ëþGRUB .G|
00000180 65 6f 6d 00 48 61 72 64 20 44 69 73 6b 00 52 65 |eom.Hard Disk.Re|
00000190 61 64 00 20 45 72 72 6f 72 00 bb 01 00 b4 0e cd |ad. Error.»..´.Í|
000001a0 10 ac 3c 00 75 f4 c3 00 00 00 00 00 00 00 00 00 |.¬<.uôÃ.........|

At offset 179h , we find the zero-terminated string GRUB followed by some error messages.



000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
000001c0 01 00 83 fe ff ff 3f 00 00 00 5b 01 5c 08 00 fe |...þÿÿ?...[.\..þ|
000001d0 ff ff 82 fe ff ff 9a 01 5c 08 42 8e 2f 00 00 00 |ÿÿ.þÿÿ..\.B./...|
000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............Uª|

And finally the MBR ends with the magic number AA55h. (seen in reverse because of little-endianness ;))




Reference :
1) Almesberger, Werner; "Booting Linux: The History and the Future"
http://www.almesberger.net/cv/papers/ols2k-9.ps.gz

2) http://mirror.href.com/thestarman/asm/mbr/GRUB.htm


Monday, September 14, 2009

Understanding the Linux Boot Process

What is booting???
Booting in simplest terms is the process of starting the operating system whenever the computer is switched on.
Booting an operating system is a very complicated process, since it involves large number of initializations, managing all the procedures within the limited memory available at boot time, etc.

Lets start by taking a very high-level view of the whole process...

Figure below depicts the overall Linux boot process

What the above figure says :-
1) On power-up or reset, the processor executes the code at a well-known location. In PC, this location is the BIOS which is stored in the flash memory on motherboard.

2) BIOS determines which devices are the candidates for booting.

3) When boot-device is found, first stage boot-loader is loaded into RAM and executed.

4) The job of the first stage boot loader is to load the second stage boot-loader.

5) The second stage boot-loader provides the options for loading an operating system from various available options.

6) It then loads the compressed kernel image and the initial RAMdisk image.

7) Once the kernel is up, the init process is the first user space process to start execution, which perform high-level system initialization.

::All of the above steps can be summarized into 2 major steps ::
a) Booting the Linux kernel into memory and passing control to it.

b) Initializing the normal environment.


Now, lets look into what each step actually does.

Phase - 1 : Loading the kernel

This phase involves retrieving the kernel executable and some additional data from some storage media, load them at the right memory location and pass control to the kernel.

(1) System Startup

In PC, booting Linux begins in BIOS at an address 0xFFFF0. The BIOS routine consists of two parts. One is the POST code and other is the runtime services.

BIOS = POST code + Runtime services.

POST stands for Power-on self-test. It performs some preliminary tests. After POST is complete, it is flushed from memory.However, BIOS runtime services remain and are available to the target OS.

To boot an OS,
BIOS runtime services search for the devices that are both active and bootable in the order of preference defined by the CMOS settings. Now this device can be either of the following:

1) Floppy
2) CD-ROM
3) Partition on Hard Disk
4) Device on Network
5) USB flash memory stick

Let us consider the very common scenario i.e. Linux booting from a hard disk, where MBR(Master Boot Record) contains the primary boot.

MBR is a 512-byte sector located in the first sector on disk i.e. sector 1 of cylinder 0 head 0.

Once MBR is loaded into RAM, BIOS passes control to it.

(2) Stage 1 Boot-Loader

Primary boot loader resides in the MBR in 512-byte image. It contains both program code and a small partition table.


The partition table contains a record for each of the 4 primary partitions.

Job of the primary loader is to find and load the secondary boot loader. In order to achieve this, what it does is :
(i) Look through the partition table for active partition.
(ii) When it finds an active partition, it scans remaining partitions to ensure that they are all inactive.
(iii) On verification, active partition's boot record is read from the device into RAM and executed.

(3) Stage 2 Boot-Loader

Its task is to load the Linux kernel and optional RAMdisk. Both the first and second stages are combined called LILO or the GRUB loader in x86 PC environment. (Detailed explanation of boot loaders is a separate topic...coming soon ;) )

Here, i would just mention that the GRUB loader is a file-aware boot loader. i.e. it includes knowledge of Linux file systems.

GRUB can load a linux kernel from a ext2 or ext3 fs instead of raw disk. It does this by making the two-stage boot loader into 3-stage one.

Stage 1(MBR) boots stage 1.5 boot loader that understands the file system containing the Linux kernel image.
eg :
# ls /boot/grub/*stage1_5 -1
/boot/grub/e2fs_stage1_5
/boot/grub/fat_stage1_5
/boot/grub/jfs_stage1_5
/boot/grub/minix_stage1_5
/boot/grub/reiserfs_stage1_5
/boot/grub/xfs_stage1_5

When stage 1.5 is loaded and running, stage 2 can be loaded. With stage 2 loaded, GRUB can display a list of available kernels.This list is defined in /etc/grub.conf.
At this point of time, command line options can be given for booting a specific kernel and also ammendments are possible.

With 2nd stage loader in memory, the FS is consulted and default kernel image and initrd image are loaded into memory. Then Stage 2 loader invokes the kernel image.

Phase 2 - Running the kernel

(1) Kernel Image
Due to various memory limits on i386, the kernel image is actually a compressed image either zImage or bzImage, with some uncompressed code at the head of the image.
The head of the image contains routine that does some minimal amount of network setup and then decompresses the kernel contained within the image and places it into the high memory.
Then calls the kernel.


Following functions are called in the order specified.

a) startup_32
arch/x86/boot/compressed/head_32.S

b) decompress_kernel
arch/x86/boot/compressed/misc.c

c) startup_32
arch/x86/kernel/head_32.S

d) start_kernel
init/main.c

e) Kernel_thread -- (called from rest_init in start_kernel)
arch/x86/kernel/process_32.c
Starts the init function....The first user-space program.

Finally cpu_idle is invoked and scheduler can take control.

(2) initrd
The initrd function allows you to create a small Linux kernel with drivers compiled as loadable modules. These loadable modules give the kernel the means to access disks and the file systems on those disks, as well as drivers for other hardware assets. Because the root file system is a file system on a disk, the initrd function provides a means of bootstrapping to gain access to the disk and mount the real root file system.

It thus serves as temporary root file systems and allows kernel to fully boot without having to mount any physical disks.

Necessary modules to interact with all the peripherals can be a part of the initrs. Thus, kernel can be small.

initrd is mainly designed to allow system startup to occur in two phases,
where the kernel comes up with a minimum set of compiled-in drivers, and
where additional modules are loaded from initrd.

Now once the kernel is booted, the root fs is changed via pivot_root. i.e. root fs is mounted and initrd is removed.

This procedure of pivoting is something like you are standing on a carpet and you wish to replace the carpet underneath you. The solution is you spread the new carpet at the end of the present one and just jump over from old carpet to new carpet ;) .

(3) init
Kernel starts the user-space process. This is the first process executed which is compiled with the standard C library.

Reference :
1) http://www.ibm.com/developerworks/library/l-linuxboot/index.html
Above post is almost the same as the link given but presentation is somewhat different and has a few more points.

2) Almesberger, Werner; "Booting Linux: The History and the Future"
http://www.almesberger.net/cv/papers/ols2k-9.ps.gz



Wednesday, September 9, 2009

__attribute__ keyword

The __attribute__ is used to assign an attribute to a function or data declarations.

Primary Purpose : Make it possible for the compiler to perform optimization.

a) Functions :
The keyword is assigned to a function in declaration of function prototype.

eg : void func() __attribute__((, ,...)) ;

void func()
{
.......
.......
}

b) Data declarations
Attributes can also be assigned to variables, and also to members of struct.


I have explained a few attributes which i found might be more of use, others are just mentioned. For detailed explanation, u can refer to the source mentioned at the end.
  • Attributes in Function Declaration:
(i) alias
Function becomes a weak alias of another function.

(ii) always_inline
Function will always be expanded as inline, even if no optimization is specified.

(iii) const
Function does not read/write global memory. Optimizer need not make certain that global values are updated before the function is called. Helps in exploiting parallelism.

(iv) constructor
Function will be called before main is called.

(v) deprecated
Gives warning on use.

(v1) destructor
Function will be called after main has returned or exit is called.

(vii) format

(viii) format_arg

(ix) malloc

(x) no_instrument_function

(xi) noinline
Function will never be expanded as inline code.

(xii) noreturn
Function will not return to its caller. Thus, the optimizer can neglect any code that would be normally executed on the functions return.

(xiii) pure
Function does not write to global memory. Allows optimizer to perform common subexpression optimization, since global data wont change in the function.

(xiv) section
The assembly code of the function is kept in the named section instead of the default text section.

Example :
Consider a C program try.c
void try(void) __attribute__((section("mysection")));

void try()
{
int a = 0;
a = a + 10;
}

int main()
{
printf("\nIn main\n");
return 0;
}

Compile it with -S option to get the equivalent assembly code for the program.
gcc -S try.c

A try.s file will be created. You can see the new section there.
.file "try.c"
.section mysection,"ax",@progbits
.globl try
.type try, @function
try:
pushl %ebp
....
leave
ret
.size try, .-try
.section .rodata
.LC0:
.string "\nIn main\n"
.text
.globl main
.type main, @function
main:
pushl %ebp
.....
ret
.size main, .-main
....

As you see in the above example, the function try is kept in a separate section and not in the .text section as main is.


Also the section can be viewed by readelf i.e. reading the Executable and Linkable format(ELF)
gcc try.c
readelf -a a.out | less

Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
.........
[10] .init PROGBITS 08048278 000278 000017 00 AX 0 0 4
[11] .plt PROGBITS 08048290 000290 000030 04 AX 0 0 4
[12] .text PROGBITS 080482c0 0002c0 0001e0 00 AX 0 0 16
[13] mysection PROGBITS 080484a0 0004a0 000015 00 AX 0 0 1
[14] .fini PROGBITS 080484b8 0004b8 00001b 00 AX 0 0 4
[15] .rodata PROGBITS 080484d4 0004d4 000012 00 A 0 0 4
[16] .data PROGBITS 080494e8 0004e8 00000c 00 WA 0 0 4
..........


(xv) used
Compiler will generate code for the function, even if it finds that the function is not used.

(xvi) weak
  • Attributes in Data Declaration:
(i) aligned
Variable with this attribute will be aligned on amemory address that is an even multiple of the number specified for alignment.
Also default alignment can be set by using the keyword align which has no parameter, instead of aligned. It aligns the variable to largest alignment for any data item supported by hardware.

(ii) deprecated

(iii) mode
Variable with this attribute is sized to match the size of specified mode.

Now u can even declare integer of one byte :) :).. But pointer arithmetic leads to unusual results. :(

modes are : word, byte, pointer.

#include

int main()
{
int iTemp __attribute__((mode(byte)));
printf("\nSize of iTemp = %d \n",sizeof(iTemp));
}

$ gcc trymode.c
$ ./a.out

Size of iTemp = 1

(iv) nocommon

(v) packed
Variable with this attribute has the smallest alignment possible. In struct, a field with this attribute will be allocated with no space between it and the field before it.

ex :
struct record {
char id;
int var[32] __attribute__((packed));
};
The member var of struct record will start 1 byte from the start of the structure.

A struct or union with this attribute takes minimum amount of space possible. It is equivalent to the attribute being apploed to each member of it.

(vi) section
Same as for function

(vii) unused
Tells the complier that the variable may not be used and hence do not issue warnings. :D


(viii) vector_size
A variable with this size is allocated a space equal to the value specified as an argument.
ex : float try __attribute__((vector_size(32)));
Assuming float takes 4 bytes, a block of 8 float variables is created.

IMP!!!! Many things here are very architecture-specific.


Source : GCC : Complete Reference
Page No. 80

Another method of initializing struct

A simple way to initialize the struct, which you will often encounter in Linux Kernel is :

Consider a struct :
struct temp {
int a;
int b;
};

To initialize the struct,
struct temp try = {.a = 2};
struct temp try1 = {.a = 3, .b =4};
struct temp try2 = {.a=4,};

All are valid initializations.

Imp!! However, this is allowed only for initialization while declaration, not later.

i.e. struct temp try;
try = {.a=2,.b=3};
is not allowed

Initialization functions and data in Linux Kernel

- Macros exist that are used to mark some functions or intialized data as 'initialization functions'.
N.B. This does not apply to uninitialized data.

- The kernel can take this as hint that the function is used only during the initialization
phase and free up used memory resources after usage.


1) For functions:

You should add __init immediately before the function name, like:

static void __init initme(int x, int y)
{
extern int z; z = x * y;
}

If the function has a prototype somewhere, you can also add
__init between closing brace of the prototype and semicolon:

extern int initialize_foobar_device(int, int, int) __init;


2) For initialized data:
You should insert __initdata between the variable name and equal
sign followed by value, e.g.:

static int init_variable __initdata = 0;
static char linux_logo[] __initdata = { 0x32, 0x36, ... };

IMP!! Don't forget to initialize data not at file scope, i.e. within a function,
as gcc otherwise puts the data into the bss section and not into the init
section.

IMP!! Also note, that this data cannot be "const".


Source : Linux Kernel Documentation
Refer file include/linux/init.h
Line No. 8