Pwn 学习

1.了解几个概念

栈   :   地址下高上低

            上esp下ebp

            经常使用add进行舍弃参数与平栈操作

od栈窗口的栈中可以存放数据也可以存放地址,还可以进行跟随

函数局部变量依次压栈,局部函数也是一样,一般会在主函数的上方,也就是低地址的位置

字符串与数组的存储形式

存储的形式就是正常按类型的大小的ascii存储

传参的话传递的是字符串与数组的首地址

函数调用与传参栈的变化

首先明确函数调用需要的两个指令   、

call与ret

执行call时:两步操作,第一步push  eip   也就是把返回值推入栈中

                                    第二步执行jmp   跳转的call之后的地址

执行ret:pop  eip    跳转到call压入的eip之处

--- g:\vc6.0\vcproject\函数栈分析练习.cpp  ----------------------------------------------------------------------------------------------------------------------------------
1:    #include 
2:
3:    int Add(int x, int y) {
00401020 55                   push        ebp
00401021 8B EC                mov         ebp,esp
00401023 83 EC 44             sub         esp,44h
00401026 53                   push        ebx
00401027 56                   push        esi
00401028 57                   push        edi
00401029 8D 7D BC             lea         edi,[ebp-44h]
0040102C B9 11 00 00 00       mov         ecx,11h
00401031 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401036 F3 AB                rep stos    dword ptr [edi]
4:        int z = 0;
00401038 C7 45 FC 00 00 00 00 mov         dword ptr [ebp-4],0
5:        z = x + y;//从主函数的实参栈中取值(用ebp调用),推入到寄存器进行计算,计算结果给寄存器,寄存器再给主函数定义的变量中
0040103F 8B 45 08             mov         eax,dword ptr [ebp+8] 
00401042 03 45 0C             add         eax,dword ptr [ebp+0Ch]
00401045 89 45 FC             mov         dword ptr [ebp-4],eax
6:
7:        return z;
00401048 8B 45 FC             mov         eax,dword ptr [ebp-4]
8:    }
0040104B 5F                   pop         edi
0040104C 5E                   pop         esi
0040104D 5B                   pop         ebx
0040104E 8B E5                mov         esp,ebp
00401050 5D                   pop         ebp
00401051 C3                   ret
--- No source file  ---------------------------------------------------------------------------------------------------------------------------------------------------------
00401052 CC                   int         3
00401053 CC                   int         3
00401054 CC                   int         3
00401055 CC                   int         3
00401056 CC                   int         3
00401057 CC                   int         3
00401058 CC                   int         3
00401059 CC                   int         3
0040105A CC                   int         3
0040105B CC                   int         3
0040105C CC                   int         3
0040105D CC                   int         3
0040105E CC                   int         3
0040105F CC                   int         3
--- g:\vc6.0\vcproject\函数栈分析练习.cpp  ----------------------------------------------------------------------------------------------------------------------------------
9:
10:   int main(void) {
00401060 55                   push        ebp
00401061 8B EC                mov         ebp,esp
00401063 83 EC 4C             sub         esp,4Ch
00401066 53                   push        ebx
00401067 56                   push        esi
00401068 57                   push        edi
00401069 8D 7D B4             lea         edi,[ebp-4Ch]
0040106C B9 13 00 00 00       mov         ecx,13h
00401071 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401076 F3 AB                rep stos    dword ptr [edi]
11:       int a = 3;
00401078 C7 45 FC 03 00 00 00 mov         dword ptr [ebp-4],3
12:       int b = 5;
0040107F C7 45 F8 05 00 00 00 mov         dword ptr [ebp-8],5
13:       int ret = 0;
00401086 C7 45 F4 00 00 00 00 mov         dword ptr [ebp-0Ch],0
14:
15:       ret = Add(a, b);//函数调用需要把每一个传入的实际参数(压数进栈用寄存器)从栈中已经定义的位置取出放入寄存器中,然后把寄存器推入栈中保存,释放函数时释放寄存器,与主函数分开释放
0040108D 8B 45 F8             mov         eax,dword ptr [ebp-8]
00401090 50                   push        eax
00401091 8B 4D FC             mov         ecx,dword ptr [ebp-4]
00401094 51                   push        ecx
00401095 E8 6B FF FF FF       call        @ILT+0(Add) (00401005)
0040109A 83 C4 08             add         esp,8//平衡调用的函数add(a,b)栈,调用两个参数,平两个参数
0040109D 89 45 F4             mov         dword ptr [ebp-0Ch],eax //返回值进行保存,从eax给变量
16:
17:       return 0;
004010A0 33 C0                xor         eax,eax
18:   }
004010A2 5F                   pop         edi
004010A3 5E                   pop         esi
004010A4 5B                   pop         ebx
004010A5 83 C4 4C             add         esp,4Ch//平衡主函数栈,定义了三个变量平三个参数
004010A8 3B EC                cmp         ebp,esp
004010AA E8 21 00 00 00       call        __chkesp (004010d0)
004010AF 8B E5                mov         esp,ebp
004010B1 5D                   pop         ebp
004010B2 C3                   ret
--- No source file  -----------------------------------------------------


传参栈分析

Pwn 学习_第1张图片

ELF文件格式学习

简单在linux系统下敲脚本

touch wang.c    //新建wang.c
vi wang.c       //填充脚本
gcc wang.c      //编译wang.c
gcc wang.c -o xinyu.out     //编译脚本修改名字输出xinyu.out
./xinyu.out     //执行

Pwn 学习_第2张图片

此时为root用户,不需要赋予权限,如果为普通用户,需要赋予执行编译权限

比如

Pwn 学习_第3张图片

此时需要chmod权限

chmod u+x *.sh
chmod是权限管理命令change the permissions mode of a file的缩写。
u代表所有者。x代表执行权限。’+’ 表示增加权限。
chmod u+x file.sh 就表示对当前目录下的file.sh文件的所有者增加可执行权限。

 Pwn 学习_第4张图片

bingo

ELF文件格式

GCC编译过程

gcc hello.c -o hello -save-temps --verbose    //将.c文件编译成elf文件

在gcc编译的过程主要包括4个阶段

包括: 1.预处理 2.编译 3.汇编 4.链接

预处理和编译

预处理阶段 在这一阶段处理以#开头的预处理指令及删除注释等工作

gcc -E hello.c -o hello.i        //单独进行.c文件到预处理

编译阶段 在这一阶段将已经被预处理的文件进行一系列分析及优化并最终形成汇编代码

gcc -S hello.c -o hello.s        

gcc -S hello.i -o hello.s        //单独进行.c文件到编译阶段

汇编

gcc -c hello.c -o hello.o

gcc -c hello.s -o hello.o            //单独进行.c文件到编译阶段或编译到汇编

as是汇编过程中的汇编器,将文件汇编成一个汇编文件 这时的.o文件已经成为了一个汇编文件,可以objdump查看汇编代码 objdump -sd hello.o -M intel

链接

链接阶段可以划分为静态链接和动态链接,在这一阶段将目标文件与其依赖库进行绑定,包括地址与空间的分配,符号绑定和重定位等。

在gcc中默认使用动态链接,静态链接的使用可以通过添加static关键字来开启

gcc hello.o -o hello -static        //开启静态链接

链接阶段通过由链接器(ld.so,collect2是对ld.so命令的封装)完成,并得到可执行的elf文件,这时的可执行文件已经包括了大量的库文件并完成了对地址与空间的分配。

ELF文件结构

通常目标文件都会包含代码(.text)、数据(.data)和BSS(.bss)三个节。其中代码节用于保存可执行的机器指令,数据节用于保存已初始化的全局变量和局部静态变量,BSS节则用于保存未初始化的全局变量和局部静态变量。 而除了这三个节之外,简化的目标文件还应包含一个文件头(ELF header)

Pwn 学习_第5张图片                 Pwn 学习_第6张图片

 

ELF文件头(ELF header)位于目标文件最开始的位置,包含描述整个文件的一些基本信息,例如ELF文件类型、版本/ABI版本、目标机器、程序入口、段表和节表的位置和长度等

readelf -h hello    //我们可以通过readelf来查看elf头文件的文件信息

Pwn 学习_第7张图片

 节头表

一个目标文件中包含许多节,这些节的信息保存在节头表(Section header table)中,表的每一项都是一个Elf64_Shdr结构体(也称为节描述符),记录了节的名字、长度、偏移、读写权限等信息。节头表的位置记录在文件头的e_shoff域中。节头表对于程序运行并不是必须的,因为它与程序内存布局无关,是程序头表的任务,所以常有程序去除节头表,以增加反编译器的分析难度 readelf -S hello        //同样,我们也可以通过readelf读出elf文件的节头表

Pwn 学习_第8张图片

 Pwn 学习_第9张图片

 

text节 该节区存储了源文件编译生成的机器指令。对开发者来说,这可能是最重要的一个节区,所有的程序逻辑都放在这里。但开发者对该节区能做的控制却很少,能影响它的因素只有开发者写的程序逻辑,以及编译时使用的选项。

.data和.rodata节

.data节中存放所有的已经初始化的全局变量和局部静态变量,这个节区是可读可写的。 .rodata中存在常量数据,从字面上就能看出,ro表示read only,即不可写,因此该节区存储了程序中的常量数据,这个节区是只可读的。

.bss节

该节区存储了所有未初始化或初始化为 0 的全局和静态变量,该节区的设计初衷就是为了节省目标文件的存储空间,该节没有CONTENTS属性,这表示该节在文件中实际上并不存在,只是为变量预留了位置而已,因此该节的sh_offset域也就没有意义了。

内存结构

在内存中,我们的程序通常通过线程来运行,而线程又可以被称为微量级进程,其本质是和进程没有太大区别。 在elf结构中介绍的elf的各个节则存在于各进程空间的各个段中

Pwn 学习_第10张图片

 

 

 

 

你可能感兴趣的:(windows,学习,java)