注意点:
若代码段开启写权限,可以对进行代码任意修改(通过gdb-vmmap查看)
写入代码段时的注意:
按地址写时,地址一个一的长度是一个字节(即八位二进制 一位十六进制),形式是机器码,所以我们在修改到想要的汇编指令的时候,现将汇编对应的机器码展开,然后按照字节将一个一个字节转成十六进制数ord(),再转成字符串形式输入str()。
p.sendline(str(ord(shellcode[i])))
void *memset(void *s, int ch, size_t n);
函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
alarm():闹钟函数
rand函数,C语言中用来产生一个随机数的函数。
rand函数界限:rand产生一个0-0x7fff的随机数,即最大是32767的一个数
rand函数调用:
rand()函数每次调用前都会查询是否调用过srand(seed),是否给seed设定了一个值,如果有那么它会自动调用srand(seed)一次来初始化它的起始值
若之前没有调用srand(seed),那么系统会自动给seed赋初始值,即srand(1)自动调用它一次
关于_start()
可以看到,程序的08048330的部分是一个叫-start的一个函数,并不是我们想当然的main。为什么?来看看<_start>函数的主要内容,扫一眼,就发现,这个函数的主要内容是在要存相关的寄存器,后面跳转到一个叫_libc_start_main@plt函数下面去了,也就是说,在程序真正的执行main操作之前,还进行了其他的函数操作,也就是main并不是真正的第一个执行的函数。那在main之前,到底那些函数都干了什么呢?
其实很简单。main函数在开始的时候,里面的变量,直接开始的时候就在栈里,然后一开始就可以直接使用malloc和new等来申请堆空间,那栈和堆的刚开始的设置地址是什么?在main里好像没有设置吧?还有比如stdin,stdout等都没有打开,所以,main前面的_start等函数做的就是这种工作,初始化堆栈信息,并且打开标准输入输出等文件。
简单来说,就是一下内容:
__start:
init stack;
init heap;
open stdin;
open stdout;
open stderr;
:
push argv;
push argc;
call _main; (调用 main)
:
destory heap;
close stdin;
close stdout;
close stderr;
:
call __exit;
所以,main只是整个程序的中间函数,并不是程序最开始执行的函数!!!
调试日志
-
在分析栈溢出漏洞的输入变量时,注意是该函数的参数还是局部变量,这关系到是否会影响当前函数的返回地址
-
有时候ida的ebp偏移并不靠谱,需要自己调试出来
-
有时候返回到main函数不可行 需要返回到_start()函数(猜测:rado那一题是需要使用到文件描述符的,0是输入,1是输出,2是错误,3-9是打开的文件,跳转到_start()可能会使3置为flag文件?)
-
gdb-bt可以查看当前运行到了哪里
-
gdb脚本中暂停调试
gdb.attach(p)
pause()
待总结:
32位和64位的字符串参数输入问题