10
This blog is dedicated to low level programming in Assembler and C/C++ (although, C++ is unwelcome) in either *Nix or Windows based operating systems. System Programming Home Contact Information Search Sunday, October 9, 2011 Interfacing Linux Signals NOTE: All information provided here is related to x86 and IA64 and may be incorrect in regard of other platforms. More than that, it may not be the same on every x86/IA64, so check your kernel/libc sources first. All source file paths are relative to your Linux Kernel source directory (most probably "/usr/src/linux") unless it is mentioned otherwise. Sample code for this article may be downloaded from here. Signals Internet is full of information on Linux signals and usage thereof, starting with simple "signal(SIGSEGV, foo)" examples through more complicated tutorials. The purpose of this article is to show the way your applications interface with Linux kernel when it comes to signal handling. First of all, what are signals? For windows guys (welcome!) reading this post and for those who has not yet reached this topic while mastering Linux programming - signals are exception notifications sent to your application by the underlying operating system (list of signals may be found in include/asm-generic/signal.h ). There are several options for what your application should do upon signal reception: ignore/block, pass to default handler, pass to custom handler. It is important, however, to mention that SIGSTOP and SIGKILL can neither be blocked nor handled with custom handler. We will concentrate on custom signal handlers in this article. Good old signal() This call is deprecated, although, it is still available on 32 bit systems (__NR_signal = 0x30), on 64 bit systems it is just a libc replacement. It accepts two parameters: Number of the signal (as defined in signal.h) in EBX; address of the custom handler in ECX; EAX should contain the __NR_signal value before int 0x80 (invocation of a system call in 32 bit Linux kernels). This call returns either a previous value for signal handler or SIG_ERR (0xFFFFFFFF) on error. It is hard enough to correct errors while using this system call as it only provides you with a signal number leaving you clueless of what has caused an exception. The Mighty Sigaction We have a much more powerful mechanism for signal handling nowadays. The name of this mighty mechanism is sigaction and it is described in libc's signal.h as this: int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); This call allows us to set custom signal handler in two ways. The first way is to set a "good old" simple handler which would only receive the number of the signal, the other is to ask the system to provide us with extended information about the signal and about the state of the process at the time of exception by specifying SA_SIGINFO flag in the struct sigaction's sa_flags field. Sigaction (2) manual page states that "sigaction structure is defined as something like:" struct sigaction { void (*sa_handler)(int); /* for the simple handler */ void (*sa_sigaction)(int, siginfo_t *, void *); /* for the handler that\ requires extended information */ sigset_t sa_mask; Alexey Lyashko 157 Follow View my complete profile About Me Join this site with Google Friend Connect Members (80) More » Already a member? Sign in Followers Alexey Lyash 157 have me in circles View all Add to circles Google+ Followers 2013 (2) Blog Archive 0 Compartilhar mais Próximo blog» Criar um blog Login System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals... 1 of 10 07/19/2013 10:04 PM

assembly implementation of unix signals

Embed Size (px)

DESCRIPTION

assembly implementation of unix signals

Citation preview

Page 1: assembly implementation of unix signals

This blog is dedicated to low level programming in Assembler and C/C++ (although, C++ is unwelcome) in either*Nix or Windows based operating systems.

System Programming

Home Contact Information

Search

Sunday, October 9, 2011

Interfacing Linux Signals

NOTE: All information provided here is related to x86 and IA64 and may be incorrect inregard of other platforms. More than that, it may not be the same on every x86/IA64, socheck your kernel/libc sources first.All source file paths are relative to your Linux Kernel source directory (most probably"/usr/src/linux") unless it is mentioned otherwise.

Sample code for this article may be downloaded from here.

Signals

Internet is full of information on Linux signals and usage thereof, starting with simple "signal(SIGSEGV, foo)" examples

through more complicated tutorials. The purpose of this article is to show the way your applications interface with Linux kernel

when it comes to signal handling.

First of all, what are signals? For windows guys (welcome!) reading this post and for those who has not yet reached this topic

while mastering Linux programming - signals are exception notifications sent to your application by the underlying operating

system (list of signals may be found in include/asm-generic/signal.h ). There are several options for what your

application should do upon signal reception: ignore/block, pass to default handler, pass to custom handler. It is important,

however, to mention that SIGSTOP and SIGKILL can neither be blocked nor handled with custom handler. We will concentrate

on custom signal handlers in this article.

Good old signal()This call is deprecated, although, it is still available on 32 bit systems (__NR_signal = 0x30), on 64 bit systems it is just a

libc replacement. It accepts two parameters:

Number of the signal (as defined in signal.h) in EBX;

address of the custom handler in ECX;

EAX should contain the __NR_signal value before int 0x80 (invocation of a system call in 32 bit Linux kernels). This call

returns either a previous value for signal handler or SIG_ERR (0xFFFFFFFF) on error.

It is hard enough to correct errors while using this system call as it only provides you with a signal number leaving you clueless

of what has caused an exception.

The Mighty Sigaction

We have a much more powerful mechanism for signal handling nowadays. The name of this mighty mechanism is sigaction and

it is described in libc's signal.h as this:

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

This call allows us to set custom signal handler in two ways. The first way is to set a "good old" simple handler which would only

receive the number of the signal, the other is to ask the system to provide us with extended information about the signal and

about the state of the process at the time of exception by specifying SA_SIGINFO flag in the struct sigaction's sa_flags field.

Sigaction (2) manual page states that "sigaction structure is defined as something like:"

struct sigaction{ void (*sa_handler)(int); /* for the simple handler */ void (*sa_sigaction)(int, siginfo_t *, void *); /* for the handler that\ requires extended information */ sigset_t sa_mask;

Alexey Lyashko

157Follow

View my complete profile

About Me

Join this sitewith Google FriendConnect

Members (80)More »

Already a member? Signin

Followers

Alexey Lyash

157 haveme incircles

Viewall

Add to circles

Google+Followers

► 2013 (2)

Blog Archive

0Compartilhar mais Próximo blog» Criar um blog Login

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

1 of 10 07/19/2013 10:04 PM

Page 2: assembly implementation of unix signals

int sa_flags; /* This field would hold the SA_SIGINFO flag if needed */ void (*sa_restorer)(void);};

Why "something like"? The answer is simple. On many architectures there is a union instead of two fields (sa_handler and

sa_sigaction) and we are advised not to define both. As to the sa_restorer field - there is less information about it in the internet,

then about me, though, we will cover this field a bit later.

Low Level Implementation of Sigaction

It seems to me that raw explanation of what and how would be too boring and may cut off a major part of the audience,

therefore, I think, that the best explanation is done by example. In this particular case, the example is a small program written in

Assembly language for bot 32 and 64 bit Linux and compiled using Flat Assembler. It has some encrypted code in its code

section and encrypted string in data section. The program uses custom handler for SIGSEGV in order to decode those parts

and encode them again when they are no longer needed. This technique involves another mighty system call - mprotect. But

before we start - forget everything that has been said about structures till now, as things become different the closer we get to

the kernel.

Sigaction a la 32 bit

First of all, we need to do some preparations and define several constants and structures which we are going to use in our

code. Let's start with memory protection flags for the mprotect call:

PROT_READ = 0x00000001 ;Page may be accessed for readingPROT_WRITE = 0x00000002 ;Page may be accessed for writingPROT_EXEC = 0x00000004 ;Page's content may be executed as code

Flags for the sigaction structure's sa_flags field:

SA_SIGINFO = 0x00000004 ;We need more info about the signal

Our signal number (for memory access violation):

SIGSEGV = 0x0B

And finally we have to define the system calls that will be used:

__NR_exit = 0x01__NR_write = 0x04__NR_sigaction = 0x43__NR_mprotect = 0x7D

But before we may start coding, we have to prepare several structures. Of course, we will start with

the sigaction32 structure defined in arch/x86/include/asm/ia32.h:

struc sigaction32{ ;Field size offset .sa_handler dd ? ;0x00 .sa_restorer dd ? ;0x04 .sa_flags dd ? ;0x08 .sa_mask dd ? ;0x0C}

sa_handler will contain the address of our custom handler, sa_flags will be assigned the value of SA_SIGINFO as we do

need extended information about the signal and the state of the process at the time of the exception. We will ignore

the sa_mask field for now.

sa_restorer cannot be ignored any more as it pops up each time we mention sigaction. As I have already mentioned above,

this field is deprecated and should not be defined/used on newer platforms. More than that POSIX is not aware of this field at

all. It used to contain the address of the procedure that would restore user context once we are done with handling the signal

(typically, this procedure would simply invoke __NR_sigreturn system call). However, this operation is performed automatically

by the VDSO.

Basically, we are set to start. So, as a first step, we need to initialize the sigaction32 structure which resides in our data

section and is named sa :

_start: ;Setup sigaction handler mov [sa.sa_handler], _handler ;flags - we use SA_SIGINFO mov [sa.sa_flags], SA_SIGINFO ;set system call number

► 2012 (16)

▼ 2011 (15)

► December(7)

► November(1)

▼ October (7)

DennisRitchie,R.I.P.

HijackLinuxSystemCalls:Part III.SystemCall T...

HijackLinuxSystemCalls:Part II.Miscellaneous...

HijackLinuxSystemCalls:Part I.Modules

InterfacingLinuxSignals

StealthImportofWindows API

WindowsStructured andVectoredExceptionHandling...

Select Real Security -useful resources andinformation on computersecurity

WINPORTAL - safe andfree software

Download Room - bestsoftware of the network(reviews & downloadlinks)

oDisZaPc notes (rus)

Friends of thisblog(recommended)

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

2 of 10 07/19/2013 10:04 PM

Page 3: assembly implementation of unix signals

mov eax, __NR_sigaction ;set the number of signal we want to handle mov ebx, SIGSEGV ;set the address of our sigaction structure mov ecx, sa ;EDX should contain the address of sigaction ;structure to store previous action. We have none ;so we pass NULL as last argument xor edx, edx ;call int 0x80

EAX register should contain 0, otherwise - as usual, check your code. We have just set our custom handler (pointed

by _handler) for SIGSEGV . We will now cause a segmentation fault in order to decode the encrypted code we have in our

program:

mov eax, .hidden_code.reason1: ;Address of the first segfault xor dword [eax], 0x8BADF00D

This is followed by our encrypted code. You may use whatever encryption algorithm you want, I personally used simple XOR:

.hidden_code: ;print the "It works!" string mov eax, __NR_write mov ebx, 1 mov ecx, str_it_works mov edx, str_it_works_length int 0x80

;Cause segmentation fault in order to encode this block mov eax, .hidden_code.reason2: ;Address of the second segfault xor dword [eax], 0x8BADF00D.hidden_code_length = $ - .hidden_code

;End of our program.finish: mov eax, __NR_exit xor ebx, ebx int 0x80

;Macro for encryption of hidden_coderepeat .hidden_code_length load a byte from .hidden_code+%-1 store byte a xor 0xE5 at .hidden_code+%-1end repeat

Once we reach the line labeled as ".reason1", we actually reach the place in code that causes segmentation fault. This brings

us to our custom handler _handler.

_handler: ;Usual prologue push ebp mov ebp,esp ;We will use some registers, so let's save them push eax ebx ecx edx

By now, we have the signum parameter at [ebp+8], pointer to siginfo structure at [ebp+12] and pointer to

the ucontext_ia32 structure at [ebp+16]. Let's take a short break from coding and concentrate on those structures.

struc siginfo{ .si_signo dd ? .si_errno dd ? .si_code dd ? ;The rest of this structure may be a union and depends on signal}

.si_signo - signal number;

.si_errno - an errno value, generally unused on Linux;

.si_code - signal code, which gives more information regarding the source of the signal.

Check include/asm-generic/siginfo.h for detailed layout specs for each signal. Generally speaking, this structure is

BaofengUV-3R Mark II

www.radioddit

$29.99Dual-Band

Two-Way HamRadio VHF

136-174MHz &UHF

400-470MHz

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

3 of 10 07/19/2013 10:04 PM

Page 4: assembly implementation of unix signals

designed to give exact idea of what has happened.

Next structure in the row of handler's arguments is the ucontext_ia32. This is a snapshot of the CPU at the time of signal

reception and is defined in arch/x86/include/asm/ia32.h

struc ucontext_ia32{ ;Field size offset .uc_flags dd ? ;0x00 .uc_link dd ? ;0x04 .uc_stack sigaltstack_ia32 ;0x08 .uc_mcontext sigcontext_ia32 ;0x14 .uc_sigmask dd ? ;0x6C}

Struct sigaltstack_ia32 is actually a definition of type stack_ia32_t in the same header file. It describes alternative

stack for signal handler if such exists. We make no use of this field as we use the same stack as the main process. Here is it's

definition in our example program

struc sigaltstack_ia32{ .ss_sp dd ? .ss_flags dd ? .ss_size dd ?};stack_ia32_t

But the structure we are particularly interested in is the sigcontext_ia32 and may be found at offset 0x14 in the

ucontext_ia32:

;defined int arch/x86/include/asm/sigcontext32.hstruc sigcontext_ia32{ ;Field size offset .gs dw ;0x00 .__gsh dw ;0x02 .fs dw ;0x04 .__fsh dw ;0x06 .es dw ;0x08 .__esh dw ;0x0A .ds dw ;0x0C .__dsh dw ;0x0E .edi dd ;0x10 .esi dd ;0x14 .ebp dd ;0x18 .esp dd ;0x1C .ebx dd ;0x20 .edx dd ;0x24 .ecx dd ;0x28 .eax dd ;0x2C .trapno dd ;0x30 .err dd ;0x34 .eip dd ;0x38 .cs dw ;0x3C .__csh dw ;0x3E .flags dd ;0x40 EFLAGS .sp_at_signal dd ;0x44 .ss dw ;0x48 .__ssh dw ;0x4A .fpstate dd ;0x4C .oldmask dd ;0x50 .cr2 dd ;0x54}

This structure is quite self-explanatory except, may be the .fpstate field. Those familiar with Windows are regular to structure

named FLOATING_SAVE_AREA which is embedded into the CONTEXT structure, however, in Linux this structure is stored

separately and .fpstate only contains its address.

As it has been mentioned above, this structure represents the CPU snapshot and, what is especially good about it, it is writable,

meaning that we may alter contents of CPU register in the context structure. This means that once we are done with out

handler (unless it terminates the process) this structure, with all the modified values will be used to restore the CPU state.

The Handler

It finally happened! We have finally got to the handler function. This part has very little to do with signals and is used to dilute

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

4 of 10 07/19/2013 10:04 PM

Page 5: assembly implementation of unix signals

the tones of raw information with something (hopefully) interesting.

In this function we are going to decode the encrypted executable code and data. First if all, we need to get the address of the

encrypted code in such a way that it would be good for the mprotect function which requires page aligned addresses. Our

program is small enough to assume that the handler and the encrypted code are within the same page (I actually checked it).

Thus, we first get the current EIP:

call .get_eip.get_eip: ;EBX register will be used throughout this function to hold the address of the current page pop ebx

;Make it page aligned in order to use with mprotect and bx, 0xF000

;Get the length of the region to change access permissions mov ecx, _start.hidden_code + _start.hidden_code_length sub ecx, ebx

;Load new protection flags mov edx, PROT_READ or PROT_WRITE or PROT_EXEC mov eax, __NR_mprotect ;Call mprotect int 0x80

;We have to check the result returned by mprotect as ; in case of error we would not be able to proceed or eax, 0 ;If error is returned, then we simply terminate the process jnz _start.finish

You should have mentioned the labels .reason1 and .reason2 earlier. They are commented as the first and the second

segfaults. We are going to use them as action indicators for our signal handler - decode encrypted code and data if signal has

been raised by memory access violation at .reason1 or encode them back if the violation occurred at .reason2. The next

step is to check what should we do:

;Get the address of the ucontext_ia32 structure (the third parameter) mov eax, [ebp+16]

;The following is FASM specific macro which makes it possible to use symbolic names ; instead of register base + offset virtual at eax .context ucontext_ia32 end virtual

;We check for reason by comparing the value of the EIP register in ucontext_ia32 ;against the address of .reason1 cmp dword[.context.uc_mcontext.eip], _start.reason1 ;I let myself assume, that it is address of .reason2 if the above ;expression is not true (i.e. does not set the zero flag). But you should check ;that in order to avoid errors jnz ._reason2

So, we have found that the value of the EIP register from the ucontext_ia32 structure equals to _start.reason1, in this

case, save the EAX and EBX registers on stack and perform all operations needed to decode the encrypted parts of your

program.

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

5 of 10 07/19/2013 10:04 PM

Page 6: assembly implementation of unix signals

Content of the _start function before decryption of the .hidden_code

Content of the _start function after the .hidden_code has been decrypted

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

6 of 10 07/19/2013 10:04 PM

Page 7: assembly implementation of unix signals

Once we have decoded all the encrypted parts, we need to modify the value of the EIP register in the ucontext_ia32, so

that it would point to .hidden_code

mov dword [.context.uc_mcontext.eip], _start.hidden_code

We are almost done with the handler, however, there is one little thing to be done - we have to write protect our code section

again. The EBX register should still point to the beginning of the page which contains our code section (unless you forgot to

back it up), so all we have to do is the following:

;Get the size of the region mov ecx, _start.hidden_code + start.hidden_code_length sub ecx, ebx mov eax, __NR_mprotect mov edx, PROT_READ or PROT_EXEC int 0x80

Now we may restore the stack and ret from the handler.

Due to the fact that we modified EIP in the ucontext_ia32 structure, our program will continue from .hidden_code instead

of trying to execute the code at .reason1. As it has been deciphered by our signal handler, it will do what it was designed to

do, namely - output a string (in our case it is "It works!"). The last operation performed by .hidden_code is attempt to write to

code section (which we made write protected), this, in turn, will cause another segmentation fault, but this time, the EIP in the

ucontext_ia32 structure will contain the address of .reason2 and our handler will encode the .hidden_code and the string

and set EIP to point to _start.finish.

At the end, if we try to run our program, we get the following output:

By now, we know how to interact with the sigaction system call on the lowest level (you say whether it is really needed ;-) ) on

32 bit Linux (PC).

Sigaction on 64 bit. Is it much different?

If we try to implement the above example on 64 bit Intel platform, algorithmically, it would be the same. We would use almost

the same system calls and almost the same flags. I will not cover the whole process here, instead, let us concentrate on major

differences.

First of all system call numbers are different:

__NR_exit = 0x3C__NR_write = 0x01__NR_rt_sigaction = 0x0D__NR_mprotect = 0x0A__NR_rt_sigreturn = 0x0F

Another difference is that there is no such thing as sys_sigaction on 64 bit platform. This does not mean that there is no

such option at all. We will use sys_rt_sigaction system call which slightly differs from the old good sys_sigaction. The

main difference is that we have to specify one additional parameter - the size of sa_mask in 64 bit words. Here are the same

structures that we used in 32 bit example adapted for 64 bits. All structure definitions are taken from arch/x86/include/asm/sigcontext.h except struct sigaction, which was taken from libc sources (it is called struct kernel_sigactionthere).

struc sigaction{ .__sigaction_handler dq ? ;Address of the handler

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

7 of 10 07/19/2013 10:04 PM

Page 8: assembly implementation of unix signals

.sa_flags dq ? ;In this example we set this field ;to "SA_SIGINFO or ;SA_RESTORER=0x04000000" .sa_restorer dq ? ;Either my platform is not as ;new as I thought, ;but I had to specify restorer ;procedure too. ;You may try both and see whether rt_sigaction ;returns error. If this is the case, add ;restorer procedure like this ;_restorer: ; mov eax, __NR_rt_sigreturn ; syscall .__val sigset_t ;Mask}

This is how you setup this structure:

_start: mov r10, _NSIG_WORDS ;Size of mask in 64 bit words mov [sa.__sigaction_handler], _handler ;Address of our custom handler mov [sa.sa_flags], SA_SIGINFO or SA_RESTORER mov [sa.sa_restorer], _restorer ;Address of the restorer procedure xor rdx, rdx ;We do not specify the oldact mov rsi, sa ;Load the address of our sigaction structure mov rdi, SIGSEGV ;Set signal number mov rax, __NR_rt_sigaction syscall

The _NSIG_WORDS constant is calculated this way:

_NSIG = 64_NSIG_BPW = 8_NSIG_WORDS = _NSIG / _NSIG_BPW

The rest of the structures are:

struc sigcontext{ ;Field size offset .r8 dq ? ;0x00 .r9 dq ? ;0x08 .r10 dq ? ;0x10 .r11 dq ? ;0x18 .r12 dq ? ;0x20 .r13 dq ? ;0x28 .r14 dq ? ;0x30 .r15 dq ? ;0x38 .rdi dq ? ;0x40 .rsi dq ? ;0x48 .rbp dq ? ;0x50 .rbx dq ? ;0x58 .rdx dq ? ;0x60 .rax dq ? ;0x68 .rcx dq ? ;0x70 .rsp dq ? ;0x78 .rip dq ? ;0x80 .rflags dq ? ;0x88 .cs dw ? ;0x90 .gs dw ? ;0x92 .fs dw ? ;0x94 .__pad0 dw ? ;0x96 .err dq ? ;0x98 .trapno dq ? ;0xA0 .oldmask dq ? ;0xA8 .cr2 dq ? ;0xB0 .fpstate dq ? ;0xB8

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

8 of 10 07/19/2013 10:04 PM

Page 9: assembly implementation of unix signals

Posted by Alexey Lyashko at 12:53 AM

Labels: assembly language, exception handling, linux, sigaction, signal

.reserved rq 8 ;0xC0}

struc sigaltstack{ .ss_sp dq ? .ss_flags dq ? .ss_size dq ?};stack_t

struc sigset_t{ .sig: repeat _NSIG_WORDS dq ? end repeat}

struc ucontext{ .uc_flags dq ? .uc_link dq ? .uc_stack sigaltstack .uc_mcontext sigcontext .uc_sigmask sigset_t}

When it comes to structures, the most visible difference (in addition to some other fields in sigcontext) is the size - almost all

is 64 bits instead of 32. All the rest is very similar to what we have done in the previous section.

Handler

There is almost no difference between the 32 and 64 bit handlers except the way the later receives its parameters as they are

passed via registers instead of being pushed on stack. In this case we have:

RDI = signum; RSI = siginfo_t*; RDX = sigcontext*;

This is according to AMD64 ABI, but this is beyond the scope of this article.

Hope this post was helpful. See you at the next one!

Recommend this on Google

Comment as: Select profile...

Publish Preview

No comments:

Post a Comment

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

9 of 10 07/19/2013 10:04 PM

Page 10: assembly implementation of unix signals

Newer Post Older PostHome

Subscribe to: Post Comments (Atom)

Copyright (C) Alexey Lyashko 2011-2012. Awesome Inc. template. Powered by Blogger.

System Programming: Interfacing Linux Signals http://syprog.blogspot.com.br/2011/10/iterfacing-linux-signals...

10 of 10 07/19/2013 10:04 PM