Linux에서의 시스템 기능 분석 소개
이 글은 linux의 시스템기능을 주로 간략하게 분석하는데, 관심 있는 친구들은
간단 분석을 참고하면 된다. Linux에서의 시스템 기능은 다음과 같습니다
int libc_system (const char *line) { if (line == NULL) /* Check that we have a command processor available. It might not be available after a chroot(), for example. */ return do_system ("exit 0") == 0; return do_system (line); } weak_alias (libc_system, system)
코드는 glibc/sysdeps/posix/system.c에 있습니다. 여기서 system은 libc_system의 약한 별칭이고 libc_system은 do_system의 프런트 엔드 기능입니다. 매개변수 포함 검사를 위해 다음으로 do_system 함수를 살펴보세요.
static int do_system (const char *line) { int status, save; pid_t pid; struct sigaction sa; #ifndef _LIBC_REENTRANT struct sigaction intr, quit; #endif sigset_t omask; sa.sa_handler = SIG_IGN; sa.sa_flags = 0; sigemptyset (&sa.sa_mask); DO_LOCK (); if (ADD_REF () == 0) { if (sigaction (SIGINT, &sa, &intr) < 0) { (void) SUB_REF (); goto out; } if (sigaction (SIGQUIT, &sa, &quit) < 0) { save = errno; (void) SUB_REF (); goto out_restore_sigint; } } DO_UNLOCK (); /* We reuse the bitmap in the 'sa' structure. */ sigaddset (&sa.sa_mask, SIGCHLD); save = errno; if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0) { #ifndef _LIBC if (errno == ENOSYS) set_errno (save); else #endif { DO_LOCK (); if (SUB_REF () == 0) { save = errno; (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); out_restore_sigint: (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); set_errno (save); } out: DO_UNLOCK (); return -1; } } #ifdef CLEANUP_HANDLER CLEANUP_HANDLER; #endif #ifdef FORK pid = FORK (); #else pid = fork (); #endif if (pid == (pid_t) 0) { /* Child side. */ const char *new_argv[4]; new_argv[0] = SHELL_NAME; new_argv[1] = "-c"; new_argv[2] = line; new_argv[3] = NULL; /* Restore the signals. */ (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL); INIT_LOCK (); /* Exec the shell. */ (void) execve (SHELL_PATH, (char *const *) new_argv, environ); _exit (127); } else if (pid < (pid_t) 0) /* The fork failed. */ status = -1; else /* Parent side. */ { /* Note the system() is a cancellation point. But since we call waitpid() which itself is a cancellation point we do not have to do anything here. */ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) status = -1; } #ifdef CLEANUP_HANDLER CLEANUP_RESET; #endif save = errno; DO_LOCK (); if ((SUB_REF () == 0 && (sigaction (SIGINT, &intr, (struct sigaction *) NULL) | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0) || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0) { #ifndef _LIBC /* glibc cannot be used on systems without waitpid. */ if (errno == ENOSYS) set_errno (save); else #endif status = -1; } DO_UNLOCK (); return status; } do_system
우선, 이 함수는 SIGINT 및 SIGQUIT 신호를 처리하기 위한 일부 신호 처리기를 설정합니다. 여기서는 크게 신경 쓰지 않습니다. 키 코드 세그먼트는 여기에 있습니다
#ifdef FORK pid = FORK (); #else pid = fork (); #endif if (pid == (pid_t) 0) { /* Child side. */ const char *new_argv[4]; new_argv[0] = SHELL_NAME; new_argv[1] = "-c"; new_argv[2] = line; new_argv[3] = NULL; /* Restore the signals. */ (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL); INIT_LOCK (); /* Exec the shell. */ (void) execve (SHELL_PATH, (char *const *) new_argv, environ); _exit (127); } else if (pid < (pid_t) 0) /* The fork failed. */ status = -1; else /* Parent side. */ { /* Note the system() is a cancellation point. But since we call waitpid() which itself is a cancellation point we do not have to do anything here. */ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) status = -1; }
프론트 엔드 함수를 통해 시스템 호출 포크를 호출합니다. 포크가 두 개의 반환 값을 갖는 자식 프로세스를 생성합니다. 자식 프로세스의 pid는 부모 프로세스에 반환되고 자식 프로세스에는 0이 반환됩니다. 따라서 하위 프로세스는 6~24줄의 코드를 실행하고 상위 프로세스는 30~35줄의 코드를 실행합니다.
자식 프로세스의 논리는 SHELL_PATH에 지정된 프로그램을 실행하기 위해 호출되며 매개 변수는 new_argv를 통해 전달되며 환경 변수 는 환경 변수입니다.
SHELL_PATH 및 SHELL_NAME은 다음과 같이 정의됩니다.
#define SHELL_PATH "/bin/sh" /* Path of the shell. */ #define SHELL_NAME "sh" /* Name to give it. */
실제로 /bin/sh -c "command"를 호출하는 하위 프로세스를 생성합니다. 시스템이 전달한 명령을 실행합니다.
실제로 제가 시스템 함수에 대해 연구하는 이유와 초점은 다음과 같습니다.
CTF의 pwn 질문에서 스택 오버플로를 통해 시스템 함수를 호출하면 가끔 실패한다고 마스터들이 말씀하시는 것을 들었습니다. 환경변수가 덮어씌워졌다고 하는데 늘 헷갈렸는데 오늘 자세히 공부해서 드디어 알아냈습니다.
여기서 시스템 기능에 필요한 환경변수는 전역변수인 environ에 저장되는데, 이 변수의 내용은 무엇일까요?
environ은 glibc/csu/libc-start.c에 정의되어 있습니다. 몇 가지 핵심 설명을 살펴보겠습니다.
# define LIBC_START_MAIN libc_start_main
libc_start_main은 _start에 의해 호출되는 함수로, 프로그램 시작 시 일부 초기화 작업이 포함됩니다. 이러한 용어를 이해하지 못하는 경우 이 문서를 읽어보세요. 다음으로 LIBC_START_MAIN 함수를 살펴보세요.
STATIC int LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), int argc, char **argv, #ifdef LIBC_START_MAIN_AUXVEC_ARG ElfW(auxv_t) *auxvec, #endif typeof (main) init, void (*fini) (void), void (*rtld_fini) (void), void *stack_end) { /* Result of the 'main' function. */ int result; libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; #ifndef SHARED char **ev = &argv[argc + 1]; environ = ev; /* Store the lowest stack address. This is done in ld.so if this is the code for the DSO. */ libc_stack_end = stack_end; ...... /* Nothing fancy, just call the function. */ result = main (argc, argv, environ MAIN_AUXVEC_PARAM); #endif exit (result); }
Environ의 값은 SHARED를 정의하지 않고 19행에서 정의된 것을 볼 수 있습니다. 시작 프로그램은 LIBC_START_MAIN을 호출하기 전에 먼저 환경 변수와 문자열 을 argv에 저장합니다(실제로는 스택에 저장됩니다). 그런 다음 각 문자열의 주소를 환경 변수에 순차적으로 저장하고 argv의 각 문자열 항목 문자열의 주소와 argc가 스택에 푸시되므로 환경 변수 배열 은 argv 배열 바로 뒤에 빈 주소로 구분되어 위치해야 합니다. 따라서 17행의 &argv[argc + 1] 문은 스택에 있는 환경 변수 배열의 첫 번째 주소를 가져와서 ev에 저장하고 마지막으로 Environ에 저장합니다. 203행에서는 Environ 값을 스택에 푸시하는 기본 함수를 호출합니다. 이 함수는 Environ의 주소를 덮어쓰지 않는 한 스택 오버플로로 덮어쓰여도 문제가 없습니다.
따라서 스택 오버플로의 길이가 너무 길고 오버플로 내용이 Environ 주소의 중요한 내용을 덮을 경우 시스템 함수 호출이 실패합니다. 특정 환경 변수가 오버플로 주소에서 얼마나 떨어져 있는지는 _start를 인터럽트하여 확인할 수 있습니다.
위 내용은 Linux에서의 시스템 기능 분석 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Linux는 서버, 개발 환경 및 임베디드 시스템에 적합합니다. 1. 서버 운영 체제로서 Linux는 안정적이고 효율적이며 종종 고 대전성 애플리케이션을 배포하는 데 사용됩니다. 2. 개발 환경으로서 Linux는 효율적인 명령 줄 도구 및 패키지 관리 시스템을 제공하여 개발 효율성을 향상시킵니다. 3. 임베디드 시스템에서 Linux는 가볍고 사용자 정의 가능하며 자원이 제한된 환경에 적합합니다.

Linux에서 Docker를 사용하면 개발 및 배포 효율성을 향상시킬 수 있습니다. 1. Docker 설치 : 스크립트를 사용하여 Ubuntu에 Docker를 설치하십시오. 2. 설치 확인 : Sudodockerrunhello-World를 실행하십시오. 3. 기본 사용 : Nginx 컨테이너 생성 Dockerrun-Namemy-Nginx-P8080 : 80-Dnginx. 4. 고급 사용 : DockerFile을 사용하여 사용자 정의 이미지를 만들고 빌드 및 실행하십시오. 5. 최적화 및 모범 사례 : 다단계 빌드 및 dockercompose를 사용하여 Dockerfiles를 작성하기위한 모범 사례를 따르십시오.

Apache를 시작하는 단계는 다음과 같습니다. Apache 설치 (명령 : Sudo apt-get Apache2를 설치하거나 공식 웹 사이트에서 다운로드) 시작 apache (linux : sudo systemctl start : windes (선택 사항, Linux : Sudo SystemCtl

Apache 80 포트가 점유되면 솔루션은 다음과 같습니다. 포트를 차지하고 닫는 프로세스를 찾으십시오. 방화벽 설정을 확인하여 Apache가 차단되지 않았는지 확인하십시오. 위의 방법이 작동하지 않으면 Apache를 재구성하여 다른 포트를 사용하십시오. Apache 서비스를 다시 시작하십시오.

Oracle 청취자를 시작하는 단계는 다음과 같습니다. Windows의 리스너 상태 (LSNRCTL 상태 명령 사용)를 확인하고 Linux 및 UNIX의 Oracle Services Manager에서 "TNS 리스너"서비스를 시작하고 LSNRCTL 시작 명령을 사용하여 리스너가 LSNRCTL 명령을 사용하여 리스너가 시작되었음을 확인하십시오.

이 기사에서는 데비안 시스템에서 NGINX 서버의 SSL 성능을 효과적으로 모니터링하는 방법에 대해 설명합니다. NginxOxporter를 사용하여 Nginx 상태 데이터를 프로 메테우스로 내보낸 다음 Grafana를 통해 시각적으로 표시합니다. 1 단계 : nginx 구성 먼저 Nginx 구성 파일에서 stub_status 모듈을 활성화하여 nginx의 상태 정보를 얻어야합니다. nginx 구성 파일에 다음 스 니펫을 추가하십시오 (일반적으로 /etc/nginx/nginx.conf에 있거나 포함 파일에 위치) : location/nginx_status {stub_status

이 기사는 데비안 시스템에서 재활용 빈을 구성하는 두 가지 방법 인 그래픽 인터페이스와 명령 줄을 소개합니다. 방법 1 : Nautilus 그래픽 인터페이스를 사용하여 파일 관리자를 엽니 다. 데스크탑 또는 응용 프로그램 메뉴에서 Nautilus 파일 관리자 (일반적으로 "파일")를 찾아 시작하십시오. Recycle Bin 찾기 : 왼쪽 탐색 표시 줄에서 재활용 빈 폴더를 찾으십시오. 찾을 수없는 경우 검색하려면 "기타 위치"또는 "컴퓨터"를 클릭하십시오. 재활용 빈 속성을 구성하십시오 : "Recycle Bin"을 마우스 오른쪽 버튼으로 클릭하고 "속성"을 선택하십시오. 속성 창에서 다음 설정을 조정할 수 있습니다. 최대 크기 : 재활용 빈에서 사용 가능한 디스크 공간을 제한하십시오. 유지 시간 : 재활용 쓰레기통에서 파일이 자동으로 삭제되기 전에 보존을 설정합니다.

Apache 서버를 다시 시작하려면 다음 단계를 따르십시오. Linux/MacOS : Sudo SystemCTL 실행 Apache2를 다시 시작하십시오. Windows : Net Stop Apache2.4를 실행 한 다음 Net Start Apache2.4를 시작하십시오. Netstat -A |를 실행하십시오 서버 상태를 확인하려면 Findstr 80.
