linux c之syscall示例原型和运行时入口_start

本文详细介绍了系统调用的实现机制,包括不同参数数量的系统调用处理方式,并展示了如何通过汇编指令进行系统调用。此外,还介绍了C语言程序启动时的初始化过程,包括设置参数和环境变量。

参考:https://github.com/lpsantil/rt0

/* Copyright (c) 2015, Louis P. Santillan <lpsantil@gmail.com>
 * All rights reserved.
 * See LICENSE for licensing details.
 */

#ifndef __RT0_SYSCALL__
#define __RT0_SYSCALL__

#include <rt0/rt0.h>
#include <asm-generic/errno.h>

#ifdef __LP64__
   #include <rt0/sys64.h>
#else
   #include <rt0/sys32.h>
#endif

long syscall6( long n, long a0, long a1, long a2, long a3, long a4, long a5 );

#ifndef __RT0_WITH_FASTER_SYSCALL__

#define syscall5( m, b0, b1, b2, b3, b4 )                            \
   syscall6( ( m ), ( b0 ), ( b1 ), ( b2 ), ( b3 ), ( b4 ), 0 )
#define syscall4( m, b0, b1, b2, b3 )                                \
   syscall5( ( m ), ( b0 ), ( b1 ), ( b2 ), ( b3 ), 0 )
#define syscall3( m, b0, b1, b2 )                                    \
   syscall4( ( m ), ( b0 ), ( b1 ), ( b2 ), 0 )
#define syscall2( m, b0, b1 )                                        \
   syscall3( ( m ), ( b0 ), ( b1 ), 0 )
#define syscall1( m, b0 )                                            \
   syscall2( ( m ), ( b0 ), 0 )
#define syscall0( m )                                                \
   syscall1( ( m ), 0 )

#else

long syscall5( long n, long a0, long a1, long a2, long a3, long a4 );
long syscall4( long n, long a0, long a1, long a2, long a3 );
long syscall3( long n, long a0, long a1, long a2 );
long syscall2( long n, long a0, long a1 );
long syscall1( long n, long a0 );
long syscall0( long n );

#endif

#endif
syscall.c

/* Copyright (c) 2015, Louis P. Santillan <lpsantil@gmail.com>
 * All rights reserved.
 * See LICENSE for licensing details.
 */
#include <rt0/rt0.h>

#ifdef __LP64__
   #include <rt0/sys64.h>
#else
   #include <rt0/sys32.h>
#endif

#define __SYSCALL_OUTPUT_REG__            "=a" ( ret )

#define __SYSCALL_CHK_ERROR__()                      \
   ret = ( 0 > ret ? errno = -ret, -1 : ret )

#ifdef __LP64__
   #define __SYSCALL_OPCODE__                "syscall"

   #define __SYSCALL_PREAMBLE__()                    \
      register long r10 __asm__( "r10" ) = a3,       \
                    r08	__asm__( "r8" )  = a4,       \
                    r09 __asm__( "r9" )  = a5

   #define __SYSCALL_INPUT_REGS__                    \
      "a" ( n ), "D" ( a0 ), "S" ( a1 ), "d" ( a2 ), \
      "r" ( r08 ), "r" ( r09 ), "r" ( r10 )

   #define __SYSCALL_CLOBBERS__ "rcx", "r11", "memory"

#else
   #define __SYSCALL_OPCODE__              "int $0x80"

   #define __SYSCALL_PREAMBLE__()                    \
      register long ebp __asm__( "ebp" )  = a5

   #define __SYSCALL_INPUT_REGS__                    \
      "a" ( n ), "b" ( a0 ), "c" ( a1 ), "d" ( a2 ), \
      "S" ( a3 ), "D" ( a4 ), "r" ( ebp )

   #define __SYSCALL_CLOBBERS__               "memory"

#endif

long syscall6( long n, long a0, long a1, long a2, long a3, long a4, long a5 )
{
   long ret;
   __SYSCALL_PREAMBLE__();

   __asm__ volatile( __SYSCALL_OPCODE__
                     : __SYSCALL_OUTPUT_REG__
                     : __SYSCALL_INPUT_REGS__
                     : __SYSCALL_CLOBBERS__ );

   __SYSCALL_CHK_ERROR__();

   return( ret );
}

#ifdef __RT0_WITH_FASTER_SYSCALL__

#ifdef __LP64__
   #define __SYSCALL_PREAMBLE5__()                    \
      register long r10 __asm__( "r10" ) = a3,        \
                    r08	__asm__( "r8" )  = a4
   #define __SYSCALL_PREAMBLE4__()                    \
      register long r10 __asm__( "r10" ) = a3
   #define __SYSCALL_PREAMBLE3__()
   #define __SYSCALL_PREAMBLE2__()
   #define __SYSCALL_PREAMBLE1__()
   #define __SYSCALL_PREAMBLE0__()

   #define __SYSCALL_INPUT_REGS5__                    \
      "a" ( n ), "D" ( a0 ), "S" ( a1 ), "d" ( a2 ),  \
      "r" ( r08 ), "r" ( r10 )
   #define __SYSCALL_INPUT_REGS4__                    \
      "a" ( n ), "D" ( a0 ), "S" ( a1 ), "d" ( a2 ),  \
      "r" ( r10 )
   #define __SYSCALL_INPUT_REGS3__                    \
      "a" ( n ), "D" ( a0 ), "S" ( a1 ), "d" ( a2 )
   #define __SYSCALL_INPUT_REGS2__                    \
      "a" ( n ), "D" ( a0 ), "S" ( a1 )
   #define __SYSCALL_INPUT_REGS1__                    \
      "a" ( n ), "D" ( a0 )
   #define __SYSCALL_INPUT_REGS0__                    \
      "a" ( n )

#else
   #define __SYSCALL_PREAMBLE5__()
   #define __SYSCALL_PREAMBLE4__()
   #define __SYSCALL_PREAMBLE3__()
   #define __SYSCALL_PREAMBLE2__()
   #define __SYSCALL_PREAMBLE1__()
   #define __SYSCALL_PREAMBLE0__()

   #define __SYSCALL_INPUT_REGS5__                    \
      "a" ( n ), "b" ( a0 ), "c" ( a1 ), "d" ( a2 ),  \
      "S" ( a3 ), "D" ( a4 )
   #define __SYSCALL_INPUT_REGS4__                    \
      "a" ( n ), "b" ( a0 ), "c" ( a1 ), "d" ( a2 ),  \
      "S" ( a3 )
   #define __SYSCALL_INPUT_REGS3__                    \
      "a" ( n ), "b" ( a0 ), "c" ( a1 ), "d" ( a2 )
   #define __SYSCALL_INPUT_REGS2__                    \
      "a" ( n ), "b" ( a0 ), "c" ( a1 )
   #define __SYSCALL_INPUT_REGS1__                    \
      "a" ( n ), "b" ( a0 )
   #define __SYSCALL_INPUT_REGS0__                    \
      "a" ( n )

#endif

long syscall5( long n, long a0, long a1, long a2, long a3, long a4 )
{
   long ret;
   __SYSCALL_PREAMBLE5__();

   __asm__ volatile( __SYSCALL_OPCODE__
                     : __SYSCALL_OUTPUT_REG__
                     : __SYSCALL_INPUT_REGS5__
                     : __SYSCALL_CLOBBERS__ );

   __SYSCALL_CHK_ERROR__();

   return( ret );
}

long syscall4( long n, long a0, long a1, long a2, long a3 )
{
   long ret;
   __SYSCALL_PREAMBLE4__();

   __asm__ volatile( __SYSCALL_OPCODE__
                     : __SYSCALL_OUTPUT_REG__
                     : __SYSCALL_INPUT_REGS4__
                     : __SYSCALL_CLOBBERS__ );

   __SYSCALL_CHK_ERROR__();

   return( ret );
}

long syscall3( long n, long a0, long a1, long a2 )
{
   long ret;
   __SYSCALL_PREAMBLE3__();

   __asm__ volatile( __SYSCALL_OPCODE__
                     : __SYSCALL_OUTPUT_REG__
                     : __SYSCALL_INPUT_REGS3__
                     : __SYSCALL_CLOBBERS__ );

   __SYSCALL_CHK_ERROR__();

   return( ret );
}

long syscall2( long n, long a0, long a1 )
{
   long ret;
   __SYSCALL_PREAMBLE2__();

   __asm__ volatile( __SYSCALL_OPCODE__
                     : __SYSCALL_OUTPUT_REG__
                     : __SYSCALL_INPUT_REGS2__
                     : __SYSCALL_CLOBBERS__ );

   __SYSCALL_CHK_ERROR__();

   return( ret );
}

long syscall1( long n, long a0 )
{
   long ret;
   __SYSCALL_PREAMBLE1__();

   __asm__ volatile( __SYSCALL_OPCODE__
                     : __SYSCALL_OUTPUT_REG__
                     : __SYSCALL_INPUT_REGS1__
                     : __SYSCALL_CLOBBERS__ );

   __SYSCALL_CHK_ERROR__();

   return( ret );
}

long syscall0( long n )
{
   long ret;
   __SYSCALL_PREAMBLE0__();

   __asm__ volatile( __SYSCALL_OPCODE__
                     : __SYSCALL_OUTPUT_REG__
                     : __SYSCALL_INPUT_REGS0__
                     : __SYSCALL_CLOBBERS__ );

   __SYSCALL_CHK_ERROR__();

   return( ret );
}

#endif
c语言运行时start函数入口。

/* Copyright (c) 2015, Louis P. Santillan <lpsantil@gmail.com>
 * All rights reserved.
 * See LICENSE for licensing details.
 */

#include <rt0/rt0.h>

#ifdef __LP64__
   #define __STARTUP_PREAMBLE__() register long rax __asm__( "rax" )

   /* Setup the base */
   /* argc = RDI = [ RSP ] */
   /* argv = RSI = [ RSP+8 ] */
   /* envp = RDX = [ argv+8*argc+8 ] */
   /* align the stack */
   #define __STARTUP_ASM__                                           \
                     "pop	%rbp\n\t"                            \
                     "mov	%rsp,	%rbp\n\t"                    \
                     "mov	(0)(%rbp),	%rdi\n\t"            \
                     "lea	(8)(%rbp),	%rsi\n\t"            \
                     "lea	(8)(%rsi,%rdi,8),	%rdx\n\t"    \
                     "and	$-16,	%rsp\n\t"

   #define __STARTUP_GETRETVAL__ "=a"( rax )

   #define __STARTUP_RETVAL__ rax
#else
   #define __STARTUP_PREAMBLE__() register long eax __asm__( "eax" )

   /* Setup the base */
   /* Fix GCC's 'helpful" 16-byte alignment */
   /* argc = ECX = [ ESP ] */
   /* argv = EDX = [ ESP+8 ] */
   /* envp = EAX = [ argv+8*argc+8 ] */
   /* align the stack */
   /* push args onto re-aligned stack */
   #define __STARTUP_ASM__                                           \
                     "mov	%esp,	%ebp\n\t"                    \
                     "add	$0x1c,	%ebp\n\t"                    \
                     "mov	(0)(%ebp),	%ecx\n\t"            \
                     "lea	(4)(%ebp),	%edx\n\t"            \
                     "lea	(4)(%edx,%ecx,4),	%eax\n\t"    \
                     "and	$-16,	%esp\n\t"                    \
                     "push	%eax\n\t"                            \
                     "push	%edx\n\t"                            \
                     "push	%ecx\n\t"

   #define __STARTUP_GETRETVAL__ "=a"( eax )

   #define __STARTUP_RETVAL__ eax
#endif

/* pointer to array of char* strings that define the current environment variables */
char **__environ;
int errno;

void _start( void ) __attribute__((noreturn));

void _start( void )
{
   __STARTUP_PREAMBLE__();

   __asm__ volatile( __STARTUP_ASM__
                     "call	main" );

   _exit( __STARTUP_RETVAL__ );

   for(;;);
}





#include <stdio.h> #include <stdlib.h> #include <unistd.h> #define _GNU_SOURCE #include <dlfcn.h> #include <sys/stat.h> #include <fcntl.h> #include <syscall.h> typedef void* (*hook_alloc)(size_t size); typedef void* (*hook_free)(void* ptr); typedef void (*hook_start)(); typedef void (*hook_exit)(int exit_code); typedef int (*hook_main)(int argc, char *argv[]); static char logname[1024] = "./hook.log"; static int fd = 0; void *malloc(size_t size){ static hook_alloc pmalloc = NULL; if(pmalloc == NULL){ pmalloc = (hook_alloc)dlsym(RTLD_NEXT, "malloc"); } static char buffer[128] = {0}; void *caller_addr = __builtin_return_address(0); void *ptr = pmalloc(size); sprintf(buffer, "%p: malloc:%p,%ld\n", caller_addr, ptr, size); write(1, buffer, 128); return ptr; } void free(void *ptr){ static hook_free pfree = NULL; if(pfree == NULL){ pfree = (hook_free)dlsym(RTLD_NEXT, "free"); } static char buffer[128] = {0}; void *caller_addr = __builtin_return_address(0); sprintf(buffer, "%p: free:%p\n", caller_addr, ptr); write(1, buffer, 128); pfree(ptr); } void _start(){ static hook_start pstart = NULL; const char msg[] = "\n!!! _START FUNCTION HIJACKED VIA LD_PRELOAD !!!\n"; syscall(SYS_write, STDOUT_FILENO, msg, sizeof(msg)-1); if(pstart == NULL){ pstart = (hook_start)dlsym(RTLD_NEXT, "_start"); if(pstart == NULL){ fprintf(stderr, "Failed to get original _start function\n"); _exit(1); } } fd = open(logname, O_RDWR | O_CREAT | O_APPEND, 0644); if(fd < 0){ fprintf(stderr, "Failed to open log file %s\n", logname); _exit(1); } printf("program start : open log file: %s\n", logname); pstart(); } static hook_exit pexit = NULL; __attribute__((noreturn)) void _exit(int exit_code){ if(pexit == NULL){ pexit = (hook_exit)dlsym(RTLD_NEXT, "_exit"); } printf("program exit : close log file: %s\n", logname); close(fd); pexit(exit_code); __builtin_unreachable(); // return; } // __attribute__((constructor)) void init() { // pexit = dlsym(RTLD_NEXT, "_exit"); // } // __attribute__((visibility("default"))) void _start(){} int main(int argc, char *argv[]){ static hook_main pmain = NULL; if(pmain == NULL){ pmain = (hook_main)dlsym(RTLD_NEXT, "main"); } fd = open(logname, O_RDWR | O_CREAT | O_APPEND, 0644); if(fd < 0){ fprintf(stderr, "Failed to open log file %s\n", logname); _exit(1); } printf("program start : open log file: %s\n", logname); return pmain(argc, argv); } 劫持main函数失败
07-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值