Why should I know this?

SystemCall 직접 박아넣기 본문

Knowledge/Android

SystemCall 직접 박아넣기

die4taoam 2022. 12. 7. 03:09

여러가지 이유(?)로 SystemCall를 직접 하는 경우가 존재합니다.

해서 이번 글에서는 간단히 SystemCall을 직접하는 방법을 알아볼까 합니다.

 

/*
 * Generic syscall call.
 * Upon entry:
 *   %rax: system call number
 *   %rdi: arg0 to system call
 *   %rsi: arg1
 *   %rdx: arg2
 *   %rcx: arg3 - syscall expects it at %r10
 *   %r8: arg4
 *   %r9: arg5
 */

#include "arch/bionic_asm.h"

ENTRY_PRIVATE(syscall)
    # All arguments are passed via registers.
    # (Not all will be valid, depending on the syscall.)
    mov     %edi, %eax
    mov     %rsi, %rdi
    mov     %rdx, %rsi
    mov     %rcx, %rdx
    mov     %r8,  %r10
    mov     %r9,  %r8
    mov     8(%rsp), %r9

    # Make the system call.
    syscall
    cmpq    $-MAX_ERRNO, %rax
    jb      1f
    negl    %eax
    movl    %eax, %edi
    call    __set_errno_internal
1:
    ret
END(syscall)

SystemCall 에 관련된 코드는 모두 Android에서 퍼왔습니다.

 

#define K_openat 257

int k_open(const char *__path, int __flags, ...) {
  va_list arg;
  int fd, root;

  root = open("/", O_RDONLY);
  if (__path[1] == '\x00' && __path[0] == '/')
    return root;

  if (__flags & O_CREAT) {
    va_start(arg, __flags);
    mode_t mode = va_arg(arg, mode_t);
    fd = syscall(K_openat, root, __path, __flags, mode);
    if (fd < 0) {
      LOGVVV("syscall failed %s %x %o", __path, __flags, mode);
      fd = open(__path, __flags, mode);
    }
  } else {
    fd = syscall(K_openat, root, __path, __flags);
    if (fd < 0) {
      LOGVVV("syscall failed %s %x", __path, __flags);
      fd = open(__path, __flags);
    }
  }

  return fd;
}

SystemCall Table의 순서는 아키텍쳐마다 다릅니다.

 

위 함수는 시스템 콜을 직접하는 open의 구현입니다.

openat을 사용한 이유는 open에 syscall을 직접하는걸 제한하는 아키텍쳐가 존재하기 때문입니다 (...)

위를 구현한 코드로 frida 로 hooking 테스트를 해봤습니다.

원래는 위에 libc.open 메시지도 안떠야겠지만 왜 계속 뜨냐면, syscall이 실패하면 -1을 리턴하는데 openat 도 open과 마찬가지로 -1을 리턴하기 때문입니다. 그래서 open이 실패한건지 syscall이 실패한건지 모르겠어서 안전성을 위해 실패한 경우 open을 한번더 호출하게 코드가 짜여져있죠. 그래서 위처럼 libc open 관련 메시지가 뜨는 겁니다.

 

 

 

이렇게 Syscall을 직접하게 되면 native 영역의 hooking에서 어느정도 자유로울 수 있다는 장점이 있습니다.

native 영역의 hooking은 검색하면 잔뜩 나오므로 따로 다루지는 않겠습니다.

 

- 끗 -

 

Comments