ciscn_2019_c_1

一.前言

本周学习过程中遇到的一些问题,还有一道 buuctf 上的题。

二.遇到的问题

1.python hex 函数的用途

Hex(number)

将 number 转换为十六进制

2. 为什么要先调用 plt 表再调用 got

可以提高程序的运行效率。问题中的 plt 表 got 表与动态链接的关系是:linux 下的动态链接是通过PLT&GOT 来实现的,got 表是全局偏移量表,储存的是外部函数的内存真实地址。plt 表叫做程序连接表,用来存储外部函数的入口点,plt 表中含有能够解析地址的函数。效率高在 got 表中的地址是可以改写的,plt 表中的改写不了,当调用函数时,先通过 pIt 表中入口地址找到 got 表中相应的函数地址,跳转到 got 表。如果是第一次调用这个函数是会跳转两次的:第一次从 plt 表中找到相应的 got 表中函数的 入口,跳到 got 表,再从 got 表中跳回到 plt 表,目的是已经获得了 got 表中的函数地址,将其带回 plt 表用 plt 表中的解析地址函数进行解析,解析这个函数的地址来获得这个函数的确切地址,获得完后再从 plt 表跳到 got 表,覆盖掉 got表的初始值,再调用函数。如果是第二次执行该函数,则不会再跳转到 plt 表,而是直接跳转执行函数。

3. pwntools 中获取 system 函数地址的方式为什么与获取/bin/sh 的方式不同?

在编写 exp 时,获取 system 函数地址的方式是 elf(定义的).symbols[‘system’],获取/bin/sh 地址的方式是 elf.search(‘/bin/sh’).next()。查找函数用 symbols,查找字符串用 search().next()。

4. 关于 write 函数

write 函数原型是 write(fd, addr, len),fd=0 时是标准输入流 stdin,fd=1 时是标准输出流 stdout,addr 是起始地址,len 是读取字节的长度。

5. 在写 ret2libc 的脚本时要用到 from LibcSearcher import LibcSearcher

但是运行时总是遇到这个问题 No matched libc, please add more libc or try others(已经安LibcSearch 了),然后发现可能是库不全,然后就找到 LibcSearcher 目录下的libc-database 目录,把里面的东西全删了,重装的。

./get 更新一直报错-bash: ./get:

No such file or directoryt,后来找到了解决办法,要先安装 astd 才能运行./get。

1) apt-get update

2)apt-get install -y

3)sudo apt install zstd

安完之后再./get ubuntu 就可以执行了。

6. 真实地址=基地址+偏移地址

三.buuctf 上的一道题

题目:ciscn_2019_c_1

1)checksec ciscn_2019_c_1

是 64 位的,用 64 位的 IDA 打开。开启了 NX 保护,堆栈不可执行,需要构造 ROP链进行绕过。

2)用 IDA 打开

先 shift+f12 查看有没有 system 和 binsh,然后发现啥也没有那可以用 ret2libc。

F5 查看伪代码

前面是一直在用 put 函数输出一些东西,没什么用好像。Puts 函数和 printf 函数都有输出功能,虽然 puts 函数不用输入换行符\n,但是它后面的参数只能是字符指针变量或者字符数组。fflush 函数的作用是刷新缓冲区。begin 函数指向迭代器中的第一个元素,迭代器是 c++里面才有的,用于保存元素的一种数据结构。进入 begin 函数查看,输出了一行等号,三个选项,最后返回到 puts 函数输出了问题。如果输入 1 就会赋值给 v4 进入 while 循环。

给 v4 赋值为 0,进行输入,如果 v4 不等于 2,那么就终止(break)并执行下面的 if 语句,如果等于,那么就 puts(I think you can do it by yourself!),在这里v4=1 并不等于 2,所以执行下一个 if 语句;如果 v4=3 就 Bye 然后返回,如果不是就继续,在这里 v4=1 并不等于 3 所以继续执行下一条 if 语句,如果 v4 不等于1 就跳出循环,输出 something wrong,然后返回到 0,如果 v4=1 就执行下面的encrypt 函数。然后点进去发现 encypt 里面有 gets 函数,它会一直读取字符串直到\n 结束,但是缓冲区只有 48 个字节大小,所以会造成缓冲区溢出.

由于 v4=1 所以就顺理成章地进入 encrypt 函数了。memset 给 s 初始化赋值 0,puts 输出一句话,用 gets 读取我们回复的字符,在这里可以构建 payload。但是下面的加密会破坏 payload。strlen 函数记录我们输入的字符串的长度,如果我们输入的长度小于 v0 就跳出while 循环,不进行下面的加密,直接输出 Ciphertext,并返回执行 puts 函数输出S。在读取时遇到\0 会停止,所以在 payload 前写入\0 就可以绕过加密。

3)编写 exp 脚本

#re2libc##buuctf#
全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务