프로그램을 검사 할 때 strace
동적 로더의 시스템 호출이 끝나고 프로그램의 시스템 호출이 시작되는 위치를 찾는 데 종종 어려움을 겪습니다.
strace ./hello
간단한 hello world C 프로그램 의 출력 hello
에는 36줄이 있습니다. 예는 다음과 같습니다.
execve("./hello", ["./hello"], 0x7fffb38f4a30 /* 73 vars */) = 0
brk(NULL) = 0x1304000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffe6715fe60) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=92340, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 92340, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f78d9fbd000
close(3) = 0
openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260|\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
동적 로더 시스템 호출을 무시하는 방법이 있습니까?
답변1
arch_prctl(ARCH_SET_FS)
x86_64에서는 몇 초 후에 기본 프로그램이 시작되므로 출력을 볼 mprotect()
수 있습니다 .sed 1,/ARCH_SET_FS/d
strace
모든 플랫폼에서 사용할 수 있는 한 가지 LD_PRELOAD
비결 __libc_start_main()
은 write(-1, "IT_STARTS_HERE", 14)
원본 __libc_start_main()
.
cat >hack.c <<'EOT'
#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>
#include <errno.h>
#include <err.h>
int __libc_start_main(
int (*main)(int,char**,char**), int ac, char **av,
int (*init)(int,char**,char**), void (*fini)(void),
void (*rtld_fini)(void), void *stack_end)
{
typeof(__libc_start_main) *next = dlsym(RTLD_NEXT, "__libc_start_main");
write(-1, "IT_STARTS_HERE", 14); errno = 0;
return next(main, ac, av, init, fini, rtld_fini, stack_end);
}
EOT
cc -shared -ldl hack.c -o hack.so
hack_strace(){ strace -E LD_PRELOAD=./hack.so "$@" 2>&1 >&3 3>&- | sed 1,/IT_STARTS_HERE/d >&2; } 3>&1
# usage
hack_strace sh -c 'echo LOL'
getuid() = 2000
getgid() = 2000
getpid() = 11443
rt_sigaction(SIGCHLD, {sa_handler=0x55eba5c19380, sa_mask=~[RTMIN RT_1], sa_flags=SA_RESTORER, sa_restorer=0x7fae5c55f840}, NULL, 8) = 0
geteuid() = 2000