pwn-基础练习
pwn-基础练习
汇编基础
•寄存器简介:
•80x86中,32位寄存器有16个:
•4个数据寄存器、2个变址寄存器、2个指针寄存器、6个段寄存器、1个指令寄存器和1个标志寄存器
•--数据寄存器
•eax,ebx,ecx,edx
•作用:存放运行中间数据,ecx常用作计数器
•特点:可以分割,比如eax可分成ax16寄存器,16位的ax又可以分成al和ah
•--变址寄存器
•esi源地址 edi目的地址
•作用:存放存储单元段内偏移量,用于寻址
•--指针寄存器
•EBP(栈底)/ESP (栈顶)
•作用: EBP是基地址指针寄存器,可以直接访问栈中数据, ESP指向堆栈栈顶。
• •--段寄存器
•CS/DS/ES/SS/FS/GS
•说明:在32位CPU中,段寄存器的作用根据工作方式不用而不同,在保护模式下,
•段寄存器中存放的不在是段值,而是称为"选择子( Selector )的某个值。
• •--指令寄存器和标志寄存器
•指令寄存器: EIP ,存放下一次要执行的指令的地址。
•标志寄存器: PSW ,存放程序运行状态。
汇编指令
enter等价于:
push ebp
mov ebp, esp
在函数的入口时常用。
leave等价于:
mov esp, ebp
pop ebp
在函数的出 口时常用。
GDB调试器
•GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c++程序员,gdb是必不可少的工具
•调试可执行文件
gdb file
注:这里有异常出现但是不影响下面的操作,所以就没改
GDB常用命令
•运行
•run:简记为 r ,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
•continue (简写c ):继续执行,到下一个断点处(或运行结束)
•next:(简写 n),单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。
•step (简写s):单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
disas main 查看地址
GDB常用命令
•断点
•break n (简写b n):在第n行处设置断点 •break func(break缩写为b):在函数func()的入口处设置断点,如:break cb_button
•delete 断点号n:删除第n个断点
•disable 断点号n:暂停第n个断点
•enable 断点号n:开启第n个断点
•clear 行号n:清除第n行的断点
•info b (info breakpoints) :显示当前程序的断点设置情况 •delete breakpoints:清除所有断点:
将断点下在 接收字符串的位置
查看断点信息
•查看
•x /nfu <addr>查看内存
•n表示要显示的内存单元的个数
•f表示显示方式, 可取如下值
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。
•u表示一个地址单元的长度
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节
•Info functions 查看函数
简单的溢出
#include <stdio.h>
int main(int argc, char** argv)
{
int modified;
char buffer[64];
modified = 0;
gets(buffer); // 引发缓冲区溢出
if (modified != 0)
{
printf("Congratulations, you pwned it.\n");
}
else
{
printf("Please try again.\n");
}
return 0;
}
Dump of assembler code for function main:
//压栈
0x0000555555555145 <+0>: push rbp
0x0000555555555146 <+1>: mov rbp,rsp
//rsp=rsp-0x60,即在栈上分配0x60个字节空间
0x0000555555555149 <+4>: sub rsp,0x60
//将edi的值存入[rbp-0x54]
0x000055555555514d <+8>: mov DWORD PTR [rbp-0x54],edi
//将rsi的值存入[rbp-0x60]
0x0000555555555150 <+11>: mov QWORD PTR [rbp-0x60],rsi
//0x0的值存入[rbp-0x4] 这里是modified的值0
0x0000555555555154 <+15>: mov DWORD PTR [rbp-0x4],0x0
//将rbp-0x50的值存入rax
0x000055555555515b <+22>: lea rax,[rbp-0x50]
//将rax的值存入rdi
0x000055555555515f <+26>: mov rdi,rax
//将0x0存入eax
0x0000555555555162 <+29>: mov eax,0x0
/调用gets(buffer)读取输入数据
0x0000555555555167 <+34>: call 0x555555555040 <gets@plt>
//判断modified变量的值是否为0
0x000055555555516c <+39>: cmp DWORD PTR [rbp-0x4],0x0
//如果modified不为0,打印成功提示Congratulations, you pwned it
0x0000555555555170 <+43>: je 0x555555555180 <main+59>
//将rip+0e8b的值存入rdi 成功提示的信息
0x0000555555555172 <+45>: lea rdi,[rip+0xe8b] # 0x555555556004
//调用puts输出数据
0x0000555555555179 <+52>: call 0x555555555030 <puts@plt>
//无条件跳转到0x55555555518c 也就是 0
0x000055555555517e <+57>: jmp 0x55555555518c <main+71>
//将rip+0xe99的值存入rdi 错误的提示信息
0x0000555555555180 <+59>: lea rdi,[rip+0xe99] # 0x555555556020
//调用puts输出数据
0x0000555555555187 <+66>: call 0x555555555030 <puts@plt>
//将0x0的值存入eax
0x000055555555518c <+71>: mov eax,0x0
//弹栈操作,恢复ebp、esp
0x0000555555555191 <+76>: leave
//栈平衡
0x0000555555555192 <+77>: ret
End