安装工具
1 2 3 4 5 6 7 8 9 10 ida pro ghidra pwntools zio one_gadget ROPgadget ropper pwndbg peda gef checksec qemu busybox seccomp-tools pathelf main_arena_offset windbg ollydbg x96dbg LibcSearcher(libc_database) glibc_all_in_one
C程序形成过程
编译原理
GCC基本使用
GCC安装
下载GCC
1 2 3 sudo apt install gcc g++ # 安装完成后检查是否成功安装输入以下指令 gcc --version
在Windows下安装GCC
Windows下安装的GCC是,MinGW(Minimalist GNU for Windows),官网在上面。
进入官网后点击下面的红色框
跳转页面后下滑找到下图的红色框,点击红色框最左边的
跳转后再点击红色框里面的,跳转到github上下载
选择下图红色框版本安装,听说13.2.0版本有点bug,可以先下载12.2.0版本
配置系统环境变量
下载压缩包到自己指定的文件夹中,再将压缩包解压后,点击进去文件夹,进入到bin目录里面去,bin目录的地址
完成上图后,会出现如下页面,点击新建,将bin目录的绝对地址复制进去
检查GCC安装是否成功
添加完环境变量后就按 Ctrl + R
,输入 cmd
,打开终端即可
然后输入gcc --version
,出现如下内容就表面gcc安装成功了
编译单个文件
1 2 3 4 5 6 7 #include <stdio.h> int main (void ) { printf ("hello world!" ); return 0 ; }
1 2 3 4 5 6 7 8 9 #include <iostream> using namespace std;int main () { std::cout<<"Hello World From CPP" << std::endl; return 0 ; }
两个程序的目录下,输入cmd指令,终端就会在该目录下运行
1 2 3 4 5 6 7 8 9 10 11 12 gcc hello.c # 会生成一个a.exe文件 # 使用gcc hello.c编译时,默认生成文件名为a的可执行文件 # 在Linux下会生成a.out文件 # 要运行则需要:./a.out gcc -o hello hello.c gcc hello.c -o hello # 这样就会生成一个文件名为hello的可执行文件 # 编译.cpp文件则不能不能用gcc指令,要用g++指令 g++ -o hello2 hello.cpp
gcc指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 gcc(g++) <options> <sourcefiles> options -o<filename> 指定文件名 -fexec-charset=GBK 指定运行时编码 -finput-charset=UTF-8 指定源文件编码 -Wall 输出警告信息 -O(0-3) 指定代码优化级别 -E -o<filename.i> 编译过程进行到预处理 -S 编译过程进行到编译 -c 编译过程进行到汇编 -static 静态链接 -I<dir> 指定头文件搜索路径 -L<dir> 指定库搜索路径 -Wl,-rpath,<libpath> 指定运行时动态链接搜索库(Linux有效) -Wl指定的是链接选项,支持的选项用ld -help查看
编译过程
gcc hello.c -o hello
GCC编译器驱动程序读取源程序文件hello.c,并把它编译成一个可执行文件main
这个编译过程分为四个阶段:预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)、链接(Linking)
预处理阶段
处理#include预编译指令,将被包含的文件直接插入到预编译指令的位置
处理所有的条件预编译指令,比如#if、#ifdef、#elif、#else、#endif等
预处理器将所有的#define删除,并且展开所有的宏定义
删除所有的注释
添加行号和文件标识、以便编译时产生调试用的行号及编译错误警告行号
保留所有的#pragma编译器指令,因为编译器需要使用它们
1 2 3 4 5 6 7 8 9 10 11 # fun.h文件 #ifndef FUN_H #define FUN_H int add (int a, int b) { return a+b; } #endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # main.cpp文件 #include "fun.h" #define ADD(x,y) x + y #define PI 3.1415927 #define STR #ifdef STR const char *str= "已定义了STR" ;#else const char *str= "没有定义STR" ;#endif int main () { double f = PI; double d = ADD(PI, 2.71828 ); return 0 ; }
1 2 g++ -E main.cpp -o main.i # -E指令是让gcc只做预处理,做完预处理后会生成.i后缀
预处理阶段把.h头文件的函数复制到main.i文件中
处理了所有的条件预编译指令,.h头文件的预编译指令也是删除后再复制过来的
预处理器将所有的#define删除,将宏定义的东西全部给替换了,比如PI
所有注释都被删除
编译
编译器将预处理完的文本文件main.i进行一系列的词法分析、语法分析、语义分析和优化、翻译成文本文件main.s
1 2 3 g++ -S main.i # -S指令是进行编译,该部分不需要用-o指定输出文件名, # gcc会根据输入文件名,确定输出文件名
汇编阶段
汇编器将main.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保持在目标文件main.o中,main.o是一个二进制文件
1 2 g++ -c main.s # -c指令是汇编指令
汇编后再打开main.o文件就会出现乱码,这是一些二进制指令
链接阶段
main函数程序调用了printf函数,它存在于一个单独的编译号了的目标文件中,而这个文件必须以某种方式合并到我们的main.o程序中
链接器就负责处理这种合并。结果就得到了main文件,它是一个可执行目标文件(或者称为可执行文件)
该文件可以被加载到内存中,由系统执行。(链接程序运行需要一大堆目标文件,以及所依赖的其他库文件,最后生成可执行文件)
1 2 3 4 5 6 7 8 9 # main.c文件 #include <stdio.h> int main () { printf ("Hello world From C\n" ); return 0 ; }
静态链接
在生成可执行文件的时候(链接阶段),把所有需要的函数的二进制代码都包含到可执行文件中去。
在程序发布的时候就不需要依赖库,也就是不再需要带着库一块发布,程序可以独立执行。
缺点:
浪费内存空间。在多进程的操作系统下,同一时间,内存中可能存在多个相同的公共库函数
程序的开发与发布流程受模块制约。只要有一个模块更新,那么就需要重新编译打包整个代码
具体演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include "fun.h" #include <iostream> #define ADD(x,y) x + y #define PI 3.1415927 #define STR #ifdef STR const char *str= "已定义了STR" ;#else const char *str= "没有定义STR" ;#endif int main () { std::cout << PI << std::endl; double f = PI; double d = ADD (PI, 2.71828 ); return 0 ; }
1 2 g++ -c main.cpp g++ -o main main.o
1 g++ -static -o main main.o
可以看到动态链接和静态链接的main.exe程序大小相差很大
动态链接
.dll
文件是动态链接库
gcc默认使用动态链接
在编译的时候不直接拷贝可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统
操作系统负责将需要的动态链接库加载到内存中,然后程序运行到指定的代码时,去共享执行内存中已经加载的动态库可执行代码,最终达到运行时链接的目的
解决了静态链接的缺陷,更适应现代的大规模的软件开发。
由于是运行时加载,可能会影响程序的前期执行性能
编码问题
1 2 3 4 5 6 7 8 9 10 #include <iostream> int main () { std::cout<<"白日依山尽" <<std::endl; std::cout<<"黄河入海流" <<std::endl; std::cout<<"欲穷千里目" <<std::endl; std::cout<<"更上一层楼" <<std::endl; return 0 }
在代码中输出了一些汉字,直接编译运行会出现这样一团乱码
原因:现在这些编辑器用的都是UTF-8编码,但命令行编码使用的是GBK。
将代码文件编码转换为GBK,设置为GBK后保持一下
将命令行的编码改为UTF-8
输入指令chcp 65001
在编译的时候指明各种编码
g++ -o main -finput-charset=UTF-8 -fexec-charset=GBK main.cpp
警告与优化选项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> int * fun () { int a=100 ; return &a; } int main () { int c=100 ; unsigned int d =210 ; bool gt = c >d; return 0 ; }
对该代码进行编译,会出现警告:在函数里面返回了一个局部变量的地址
-W
指令用来开启警告,-Wall
表示开启所有的警告
-Wunsued-variable
,即-W指令+警告类型,开启指定的警告
-Wno-return-local-addr
,关闭指定警告
-Werror
把警告当做错误来处理
-O0或-O1或-O2或-O3
对代码进行优化,3代表是最高级别的优化
与小写字母o区别
多文件编译
指定头文件搜索路径
汇编基础
描述字的量词
名称
翻译
大小
bit
比特
1位(1b)
byte
字节
8位(1B)
word
字
16位
dword
双字
32位
qword
四字
64位
dword:double word
qword: quadra word
寄存器种类
1 2 3 4 5 rbp rsp # 与栈有关,保护栈 rax # 储存程序的返回值,return的数据都储存在rax rip # 存放当前执行的指令地址 rsp # 存放当前栈帧的栈顶地址 rbp # 存放当前栈帧的栈底
Linux
ELF文件结构
linux环境中,二进制可执行文件的类型是ELF (Executable and Linkable)文件
下图节头表又被称为段表
查看ELF文件
例如:readelf -h question_1_x64
分析ELF文件头
Magic
几乎所有的可执行文件格式的最开始的几个字节都是magic
比如a.out格式最开始两个字节为0x01、0x07。PE/COFF文件最开始两个字节为0x4d、0x5a,即ASCII字符的MZ
1 2 3 4 5 Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
类型
类型: DYN (Position-Independent Executable file)
系统架构
e_machine
成员表示该ELF文件的平台属性,比如下图表示该ELF文件只能在x86-64位的机器下使用
ELF文件头结构体
ELF文件在各种平台下都通用,ELF文件有32位版本和64位版本
它的文件头结构也有这两个版本分别叫Elf32_Ehdr
和Elf64_Ehdr
带地址的有差别,其他没啥区别
除了前五个对应了结构体的的一个,后面都与结构体一一对应
基本操作命令
1 2 标准格式:命令名称 [命令参数] [命令对象] 其中命令参数有长和短两种格式,分别用"--"和"-"做前缀。例如:--help和-h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ls [OPtion]... [FILE]... 列出文件信息 cd [-L] [-P [-e]] [-@] [dir] 切换工作目录 pwd [-LP] 显示当前工作目录 uname [OPTION]... 打印系统信息 whoami [OPTION]... 打印用户名 man [OPTION...] [SECTION] PAGE... 查询帮助信息 find [OPTION] [path..] [expression] 查找文件 echo [SHORT-OPTION]... [STRING]... 打印文本,参数“-e”可激活转义字符 cat [OPTION]... [FILE]... 打印到标准输出 less [options] file... 分页打印文本,比more提供更丰富的功能 head/tail [OPTION] [FILE]... 打印文本的前/后N行 grep[OPTION]... PATTERN [FILE]... 匹配文本模式 cut OPTION... [FILE]... 通过列提取文本 diff [OPTION]... [FILE]... 比较文本差异 mv [OPTION]... [-T] SOURCE DEST 移动或重命名文件 cp [OPTION]... [-T] SOURCE DEST 复制文件勾八 rm [OPTION]... [FILE]... 删除文件 ps [options] 查看进程状态 top [options] 实时查看系统运行情况 kill [options] <pid> [...] 杀死进程 ifconfig [-v] [-a] [-s] [interface] 查看或设置网络设备 ping [options] destination 判断网络或设置网络设备 netstat [options] 判断网络主机是否响应 nc [options] 建立TCP/UDP连接并监听 su [options] [username] 切换到超级用户 touch [OPTION]... FILE... 创建文件 mkdir [OPTION]... DIRECTORY... 创建目录 chmod [OPTION]... MODE[,MODE]... FILE... 变更文件或目录权限 chown [OPTION]... [OWNER][:[GROUP]] FILE... 变更文件或目录所属者 nano / vim / emacs 终端文件编辑器 history [-c] [-d offset] [n] 查看".bash_history"中历史命令 exit 退出shell
1 2 3 4 5 var = value 给变量var赋值value $var, ${var} 去变量的值 'cmd', $(cmd) 代换标准输出 'string' 非替换字符串 "string" 可替换字符串
工具操作指令
1 2 3 4 5 6 7 8 9 10 gcc question_1.c -o question_1_X64 gcc -S question_1.c file ldd nm hexdump objdump -d -M intel readelf -a gdb socat tcp-I:8888,fork exec:./a.out,reuseaddr
file指令
file question_1_x64
1 2 question_1_x64: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=93f72a0d1b001212ba5860a6a1da7e57a36e3f47, for GNU/Linux 3.2.0, not stripped
readelf指令
readelf -a question_1_x64 |less
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ELF 头: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64 数据: 2 补码,小端序 (little endian) Version: 1 (current) OS/ABI: UNIX - System V ABI 版本: 0 类型: DYN (Position-Independent Executable file) 系统架构: Advanced Micro Devices X86-64 版本: 0x1 入口点地址: 0x1100 程序头起点: 64 (bytes into file) Start of section headers: 14424 (bytes into file) 标志: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 13 Size of section headers: 64 (bytes) Number of section headers: 31 Section header string table index: 30 节头: [号] 名称 类型 地址 偏移量 大小 全体大小 旗标 链接 信息 对齐 [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000000318 00000318 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.gnu.pr[...] NOTE 0000000000000338 00000338 0000000000000030 0000000000000000 A 0 0 8 [ 3] .note.gnu.bu[...] NOTE 0000000000000368 00000368 0000000000000024 0000000000000000 A 0 0 4 [ 4] .note.ABI-tag NOTE 000000000000038c 0000038c 0000000000000020 0000000000000000 A 0 0 4 [ 5] .gnu.hash GNU_HASH 00000000000003b0 000003b0 0000000000000034 0000000000000000 A 6 0 8 [ 6] .dynsym DYNSYM 00000000000003e8 000003e8 0000000000000168 0000000000000018 A 7 1 8 [ 7] .dynstr STRTAB 0000000000000550 00000550 00000000000000d7 0000000000000000 A 0 0 1 [ 8] .gnu.version VERSYM 0000000000000628 00000628 000000000000001e 0000000000000002 A 6 0 2
nm指令
nm question_1_x64 |less
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 000000000000038c r __abi_tag 0000000000004018 B __bss_start 0000000000004048 b completed.0 w __cxa_finalize@GLIBC_2.2.5 0000000000004000 D __data_start 0000000000004000 W data_start 0000000000001130 t deregister_tm_clones 00000000000011a0 t __do_global_dtors_aux 0000000000003d98 d __do_global_dtors_aux_fini_array_entry 0000000000004008 D __dso_handle 0000000000003da0 d _DYNAMIC 0000000000004018 D _edata 0000000000004050 B _end 0000000000001304 T _fini 00000000000011e0 t frame_dummy 0000000000003d90 d __frame_dummy_init_array_entry 0000000000002138 r __FRAME_END__ 0000000000001252 T func U gets@GLIBC_2.2.5 0000000000003f90 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 000000000000200c r __GNU_EH_FRAME_HDR 0000000000001000 T _init 00000000000011e9 T init_func 0000000000002000 R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable U __libc_start_main@GLIBC_2.34 0000000000001275 T main U printf@GLIBC_2.2.5 U puts@GLIBC_2.2.5 0000000000001160 t register_tm_clones U setvbuf@GLIBC_2.2.5 0000000000004010 D sh U __stack_chk_fail@GLIBC_2.4 0000000000001100 T _start 0000000000004040 B stderr@GLIBC_2.2.5 0000000000004030 B stdin@GLIBC_2.2.5 0000000000004020 B stdout@GLIBC_2.2.5 U system@GLIBC_2.2.5 0000000000004018 D __TMC_END__
hexdump指令
hexdump question_1_x64 | less
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 0003e80 0000 0000 0000 0000 0008 0000 0000 0000 0003e90 0008 0000 0000 0000 0106 0000 0001 0000 0003ea0 0003 0000 0000 0000 4000 0000 0000 0000 0003eb0 3000 0000 0000 0000 0018 0000 0000 0000 0003ec0 0000 0000 0000 0000 0008 0000 0000 0000 0003ed0 0000 0000 0000 0000 010c 0000 0008 0000 0003ee0 0003 0000 0000 0000 4020 0000 0000 0000 0003ef0 3018 0000 0000 0000 0030 0000 0000 0000 0003f00 0000 0000 0000 0000 0020 0000 0000 0000 0003f10 0000 0000 0000 0000 0111 0000 0001 0000 0003f20 0030 0000 0000 0000 0000 0000 0000 0000 0003f30 3018 0000 0000 0000 002b 0000 0000 0000 0003f40 0000 0000 0000 0000 0001 0000 0000 0000 0003f50 0001 0000 0000 0000 0001 0000 0002 0000 0003f60 0000 0000 0000 0000 0000 0000 0000 0000 0003f70 3048 0000 0000 0000 0468 0000 0000 0000 0003f80 001d 0000 0012 0000 0008 0000 0000 0000 0003f90 0018 0000 0000 0000 0009 0000 0003 0000 0003fa0 0000 0000 0000 0000 0000 0000 0000 0000 0003fb0 34b0 0000 0000 0000 028b 0000 0000 0000 0003fc0 0000 0000 0000 0000 0001 0000 0000 0000 0003fd0 0000 0000 0000 0000 0011 0000 0003 0000 0003fe0 0000 0000 0000 0000 0000 0000 0000 0000 0003ff0 373b 0000 0000 0000 011a 0000 0000 0000 0004000 0000 0000 0000 0000 0001 0000 0000 0000 0004010 0000 0000 0000 0000 0004018
strings指令
strings question_1_x64 |less
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /lib64/ld-linux-x86-64.so.2 mfUa __cxa_finalize __libc_start_main gets setvbuf stdout puts system stdin stderr __stack_chk_fail printf libc.so.6 GLIBC_2.4 GLIBC_2.2.5 GLIBC_2.34 _ITM_deregisterTMCloneTable __gmon_start__ _ITM_registerTMCloneTable
ldd指令
ldd question_1_x64
1 2 3 linux-vdso.so.1 (0x00007fffddda6000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000759e6c000000) /lib64/ld-linux-x86-64.so.2 (0x0000759e6c3e0000)
objdump指令
objdump -d question_1_x64 |less
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 question_1_x64: 文件格式 elf64-x86-64 Disassembly of section .init: 0000000000001000 <_init>: 1000: f3 0f 1e fa endbr64 1004: 48 83 ec 08 sub $0x8,%rsp 1008: 48 8b 05 d9 2f 00 00 mov 0x2fd9(%rip),%rax # 3fe8 <__gmon_start__@Base> 100f: 48 85 c0 test %rax,%rax 1012: 74 02 je 1016 <_init+0x16> 1014: ff d0 call *%rax 1016: 48 83 c4 08 add $0x8,%rsp 101a: c3 ret Disassembly of section .plt: 0000000000001020 <.plt>: 1020: ff 35 72 2f 00 00 push 0x2f72(%rip) # 3f98 <_GLOBAL_OFFSET_TABLE_+0x8> 1026: f2 ff 25 73 2f 00 00 bnd jmp *0x2f73(%rip) # 3fa0 <_GLOBAL_OFFSET_TABLE_+0x10> 102d: 0f 1f 00 nopl (%rax) 1030: f3 0f 1e fa endbr64 1034: 68 00 00 00 00 push $0x0 1039: f2 e9 e1 ff ff ff bnd jmp 1020 <_init+0x20> 103f: 90 nop 1040: f3 0f 1e fa endbr64 1044: 68 01 00 00 00 push $0x1 1049: f2 e9 d1 ff ff ff bnd jmp 1020 <_init+0x20> 104f: 90 nop 1050: f3 0f 1e fa endbr64 1054: 68 02 00 00 00 push $0x2 1059: f2 e9 c1 ff ff ff bnd jmp 1020 <_init+0x20> 105f: 90 nop 1060: f3 0f 1e fa endbr64
objdump -d question_1_x64 -M intel|less
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 question_1_x64: 文件格式 elf64-x86-64 Disassembly of section .init: 0000000000001000 <_init>: 1000: f3 0f 1e fa endbr64 1004: 48 83 ec 08 sub rsp,0x8 1008: 48 8b 05 d9 2f 00 00 mov rax,QWORD PTR [rip+0x2fd9] # 3fe8 <__gmon_start__@Base> 100f: 48 85 c0 test rax,rax 1012: 74 02 je 1016 <_init+0x16> 1014: ff d0 call rax 1016: 48 83 c4 08 add rsp,0x8 101a: c3 ret Disassembly of section .plt: 0000000000001020 <.plt>: 1020: ff 35 72 2f 00 00 push QWORD PTR [rip+0x2f72] # 3f98 <_GLOBAL_OFFSET_TABLE_+0x8> 1026: f2 ff 25 73 2f 00 00 bnd jmp QWORD PTR [rip+0x2f73] # 3fa0 <_GLOBAL_OFFSET_TABLE_+0x10> 102d: 0f 1f 00 nop DWORD PTR [rax] 1030: f3 0f 1e fa endbr64 1034: 68 00 00 00 00 push 0x0 1039: f2 e9 e1 ff ff ff bnd jmp 1020 <_init+0x20> 103f: 90 nop 1040: f3 0f 1e fa endbr64 1044: 68 01 00 00 00 push 0x1 1049: f2 e9 d1 ff ff ff bnd jmp 1020 <_init+0x20> 104f: 90 nop 1050: f3 0f 1e fa endbr64 1054: 68 02 00 00 00 push 0x2 1059: f2 e9 c1 ff ff ff bnd jmp 1020 <_init+0x20> 105f: 90 nop 1060: f3 0f 1e fa endbr64
Linux查看文件的指令
cat命令—用于将文件内容输出到终端上,经常使用于查看文本文件的内容。
less命令—用于分页查看文件内容,可以向上翻页、向下翻页、搜索关键字等,合适查看大文件。
more命令—与less类似,也是用于分页查看文件内容,但是功能较少,只能向下翻页。
head命令—用于查看文件的前几行内容,默许情况下显示前10行。
tail命令—用于查看文件的后几行内容,默许情况下显示文件的最后10行。
nl命令—用于在文件中加上行号,便于查看和编辑文件。
vi/vim命令—是一种文本编辑器,可以用于查看和编辑文件内容,适用于高级用户。
cat命令
cat命令—用于将文件内容输出到终端上,经常使用于查看文本文件的内容。
less命令
less命令—用于分页查看文件内容,可以向上翻页、向下翻页、搜索关键字等,合适查看大文件。
more命令
more命令—与less类似,也是用于分页查看文件内容,但是功能较少,只能向下翻页。
head命令
head命令—用于查看文件的前几行内容,默许情况下显示前10行。
tail命令
tail命令—用于查看文件的后几行内容,默许情况下显示文件的最后10行。
nl命令
nl命令—用于在文件中加上行号,便于查看和编辑文件。
vi/vim命令
vi/vim命令—是一种文本编辑器,可以用于查看和编辑文件内容,适用于高级用户。
Linux输入输出
如果题目关闭标准错误输入输出,那么得到shell后就输入指令exec 1>&0
将标准输入输出开启
偏移量
返回地址偏移量:在栈溢出攻击中,攻击者通常会尝试覆盖函数的返回地址,以控制程序的执行流程。攻击者需要计算出返回地址在目标函数栈帧中的偏移量,从而正确地覆盖返回地址。
缓冲区偏移量:攻击者通常会利用缓冲区溢出来实现栈溢出攻击。攻击者需要计算出目标缓冲区在栈帧中的偏移量,以正确地构造恶意输入来溢出缓冲区。
Shellcode 的加载地址:如果攻击者试图在栈溢出攻击中注入恶意代码(如 Shellcode),则需要考虑 Shellcode 在内存中的加载地址。攻击者需要计算出 Shellcode 在栈帧中的偏移量,以正确地设置返回地址指向 Shellcode。
其他关键数据的偏移量:除了返回地址和缓冲区之外,攻击者可能还需要考虑其他关键数据在栈帧中的偏移量,以实现更复杂的攻击目标。
综上所述,在进行栈溢出攻击时,攻击者需要仔细分析目标函数的栈帧结构,计算关键数据的偏移量,并正确地构造恶意输入,以实现对程序的控制或执行恶意代码。通过正确地计算和使用偏移量,攻击者可以更有效地利用栈溢出漏洞进行攻击。
shellcode
shellcode是一段可被CPU直接执行的程序码
使用shellcode进行攻击是一项经典而强大的技术,借助shellcode几乎可以完成任何事情,包括但不限于泄露敏感信息、反弹shell、布置后门等。
编写shellcode的方式有很多,而方式的选择取决于实际场景。如当需要编写复杂的shellcode的时候,需要手搓;当需要注入特定模版的shellcode时,可以采取工具生成;当需要观察shellcode的字符、长度时,可以采用在线网站生成。
shellcode是一段可被CPU直接执行的程序码
使用shellcode进行攻击是一项经典而强大的技术,借助shellcode几乎可以完成任何事情,包括但不限于泄露敏感信息、反弹shell、布置后门等。
编写shellcode的方式有很多,而方式的选择取决于实际场景。如当需要编写复杂的shellcode的时候,需要手搓;当需要注入特定模版的shellcode时,可以采取工具生成;当需要观察shellcode的字符、长度时,可以采用在线网站生成。
纯手搓
学到最后,会回归到最原始的方式:手搓shellcode。
纯汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ;#gcc -c start.s -o start.o ;#ld -e _start -z noexecstack start.o -o start ;//使用intel语法 .intel_syntax noprefix .text .globl _start .type _start, @function _start: ;// SYS_exit mov rdi,0 mov rax,60 syscall
也可以使用nasm,只是编译的命令不一样。
推荐书籍《二进制程序的链接、装载与库》
内联汇编
有时候需要调用一下库函数,可以使用内联汇编 Extended Asm (Using the GNU compiler collection(GCC)
,直接在程序中使用asm(…);编写内联汇编语句。
但是在剥离shellcode的时候,需要将 call xxxxxxxx
的偏移进行修正
使用tiny_libc
为了快速、高效、准确地编写出复杂的shellcode,使用musl库实现简单的libc库,姑且称之为 tiny_libc
,项目地址在
借助工具
pwntools的shellcraft定义了非常多的模版,支持的架构有x86/x64/arm/arm64等等。
alph3
AE64
shellcode encoder
交叉编译
在线网站
其他相关资料
一些内核网站