mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 19:21:15 +07:00
update chapter1_basic.tex
This commit is contained in:
parent
ca913232b9
commit
bbdabed1a5
Binary file not shown.
@ -467,15 +467,115 @@ db-peda$ x/s 0xffffd584
|
||||
\indent 在 Linux 系统中一切皆可以看成是文件,文件又分为:普通文件、目录文件、链接文件和设备文件。文件描述符(file descriptor)是内核管理已被打开的文件所创建的索引,使用一个非负整数来指代被打开的文件。
|
||||
|
||||
\indent 标准文件描述符如下:
|
||||
\indent \\
|
||||
\begin{tabular}[ht]{|c|c|c|}
|
||||
\hline
|
||||
文件描述符 & 用途 & stdio 流 \\
|
||||
\hline
|
||||
0 & 标准输入 & stdin \\
|
||||
\hline
|
||||
1 & 标准输出 & stdout \\
|
||||
\hline
|
||||
2 & 标准错误 & stderr \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
|
||||
\indent 当一个程序使用 \verb+fork()+ 生成一个子进程后,子进程会继承父进程所打开的文件表,此时,父子进程使用同一个文件表,这可能导致一些安全问题。如果使用 \verb+vfork()+,子进程虽然运行于父进程的空间,但拥有自己的进程表项。
|
||||
\indent 当一个程序使用 \verb+fork+ 生成一个子进程后,子进程会继承父进程所打开的文件表,此时,父子进程使用同一个文件表,这可能导致一些安全问题。如果使用 \verb+fork()+,子进程虽然运行于父进程的空间,但拥有自己的进程表项。
|
||||
|
||||
\subsubsection{核心转储}
|
||||
\indent \setlength{\parindent}{2em}
|
||||
\indent 当程序运行的过程中异常终止或崩溃,操作系统会将程序当时的内存、寄存器状态、堆栈指针、内存管理信息等记录下来,保存在一个文件中,这种行为就叫做核心转储(Core Dump)。
|
||||
|
||||
\indent 会产生核心转储的信号:
|
||||
|
||||
\begin{tabular}{|c|c|c|}
|
||||
\hline
|
||||
Signal & Action & Comment \\
|
||||
\hline
|
||||
SIGQUIT & Core & Quit from keyboard \\
|
||||
\hline
|
||||
SIGILL & Core & Illegal Instruction \\
|
||||
\hline
|
||||
SIGABRT & Core & Abort signal from abort \\
|
||||
\hline
|
||||
SIGSEGV & Core & Invalid memory reference \\
|
||||
\hline
|
||||
SIGTRAP & Core & Trace/breakpoint trap \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
|
||||
\indent 开启核心转储:
|
||||
\indent \begin{itemize}
|
||||
\item 输入命令 \verb+ulimit -c+,输出结果为 0,说明默认是关闭的。
|
||||
\item 输入命令 \verb+ulimit -c unlimited+ 即可在当前终端开启核心转储功能。
|
||||
\item 如果想让核心转储功能永久开启,可以修改文件 \verb+/etc/security/limits.conf+,增加一行:
|
||||
\item \verb+#<domain> <type> <item> <value>+
|
||||
\item \verb+* soft core unlimited+
|
||||
\end{itemize}
|
||||
|
||||
\indent
|
||||
\indent 修改转储文件保存路径:
|
||||
\begin{itemize}
|
||||
\item 通过修改 \verb+/proc/sys/kernel/core_uses_pid+,可以使生成的核心转储文件名变为 \verb+core.[pid]+ 的模式:
|
||||
\item \verb+# echo 1 > /proc/sys/kernel/core_uses_pid+
|
||||
\item 还可以修改 \verb+/proc/sys/kernel/core_pattern+ 来控制生成核心转储文件的保存位置和文件名格式:
|
||||
\item \verb+# echo /tmp/core-%e-%p-%t > /proc/sys/kernel/core_pattern+
|
||||
\end{itemize}
|
||||
|
||||
\indent 此时生成的文件保存在 /tmp/ 目录下,文件名格式为 core-[filename]-[pid]-[time]。
|
||||
|
||||
\indent 例子:
|
||||
\begin{lstlisting}[language=bash, style=customStyleBashDark, caption=内存转储示例]
|
||||
$ cat core.c
|
||||
#include <stdio.h>
|
||||
void main(int argc, char **argv) {
|
||||
char buf[5];
|
||||
scanf("%s", buf);
|
||||
}
|
||||
$ gcc -m32 -fno-stack-protector core.c
|
||||
$ ./a.out
|
||||
AAAAAAAAAAAAAAAAAAAA
|
||||
Segmentation fault (core dumped)
|
||||
$ file /tmp/core-a.out-12444-1503198911
|
||||
/tmp/core-a.out-12444-1503198911: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './a.out', real uid: 1000, effective uid: 1000, real gid: 1000, effective gid: 1000, execfn: './a.out', platform: 'i686'
|
||||
$ gdb a.out /tmp/core-a.out-12444-1503198911 -q
|
||||
Reading symbols from a.out...(no debugging symbols found)...done.
|
||||
[New LWP 12444]
|
||||
Core was generated by `./a.out'.
|
||||
Program terminated with signal SIGSEGV, Segmentation fault.
|
||||
#0 0x5655559b in main ()
|
||||
gdb-peda$ info frame
|
||||
Stack level 0, frame at 0x41414141:
|
||||
eip = 0x5655559b in main; saved eip = <not saved>
|
||||
Outermost frame: Cannot access memory at address 0x4141413d
|
||||
Arglist at 0x41414141, args:
|
||||
Locals at 0x41414141, Previous frame's sp is 0x41414141
|
||||
Cannot access memory at address 0x4141413d
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{调用约定}
|
||||
\indent \setlength{\parindent}{2em}
|
||||
|
||||
\indent 函数调用约定是对函数调用时如何传递参数的一种约定。关于它的约定有许多种,下面我们分别从内核接口和用户接口介绍 32 位和 64 位 Linux 的调用约定。
|
||||
|
||||
\indent 内核接口
|
||||
|
||||
\indent x86-32 系统调用约定:Linux 系统调用使用寄存器传递参数。
|
||||
|
||||
\indent \verb+eax+ 为 \verb+syscall_number+,\verb+ebx+、\verb+ecx+、\verb+edx+、\verb+esi+、\verb+ebp+ 用于将 6 个参数传递给系统调用。返回值保存在 eax 中。所有其他寄存器(包括 \verb+EFLAGS+)都保留在 \verb+int 0x80+ 中。
|
||||
|
||||
\indent x86-64 系统调用约定:内核接口使用的寄存器有:\verb+rdi+、\verb+rsi+、\verb+rdx+、\verb+r10+、\verb+r8+、\verb+r9+。系统调用通过 \verb+syscall+ 指令完成。除了 \verb+rcx+、\verb+r11+ 和 \verb+rax+,其他的寄存器都被保留。系统调用的编号必须在寄存器 \verb+rax+ 中传递。系统调用的参数限制为 6 个,不直接从堆栈上传递任何参数。返回时,\verb+rax+ 中包含了系统调用的结果。而且只有 \verb+INTEGER+ 或者 \verb+MEMORY+ 类型的值才会被传递给内核。
|
||||
|
||||
\indent 用户接口
|
||||
|
||||
\indent x86-32 函数调用约定:
|
||||
|
||||
\indent 参数通过栈进行传递。最后一个参数第一个被放入栈中,直到所有的参数都放置完毕,然后执行 \verb+call+ 指令。这也是 Linux 上 C 语言函数的方式。
|
||||
|
||||
\indent x86-64 函数调用约定:
|
||||
|
||||
\indent x86-64 下通过寄存器传递参数,这样做比通过栈有更高的效率。它避免了内存中参数的存取和额外的指令。根据参数类型的不同,会使用寄存器或传参方式。如果参数的类型是 \verb+MEMORY+,则在栈上传递参数。如果类型是 \verb+INTEGER+,则顺序使用 \verb+rdi+、\verb+rsi+、\verb+rdx+、\verb+rcx+、\verb+r8+ 和 \verb+r9+。所以如果有多于 6 个的 \verb+INTEGER+ 参数,则后面的参数在栈上传递。
|
||||
|
||||
\subsubsection{环境变量}
|
||||
\indent \setlength{\parindent}{2em}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user