PWN-题解

jarvisoj_level0

步骤

检查文件,64位,开启NX保护
在这里插入图片描述
拖入IDA打开,查看主函数main
在这里插入图片描述

write:这是一个系统调用,用于将数据写入文件描述符。在这里,write 函数将数据写入文件描述符 1,表示标准输出。

1:这是文件描述符,代表标准输出。标准输出的文件描述符为 1。

"Hello, World\n":这是要写入的数据,即字符串 "Hello, World" 后跟一个换行符 \n。

0xDuLL:这是要写入的数据的大小,使用十六进制表示。0xD 对应十进制的 13,表示字符串的长度为 13 个字节。

双击查看vulenerable_function
在这里插入图片描述

char buf[128];:这行代码定义了一个大小为 128 字节的字符数组 buf,用于存储从标准输入读取的数据。

return read(0, buf, 0x200uLL);:这行代码调用了 read 系统调用,从标准输入(文件描述符为 0)读取数据,将读取的数据存储到 buf 中。0x200uLL 表示读取的最大字节数为 0x200(十六进制)或 512(十进制)。

read:这是一个系统调用,用于从文件描述符中读取数据。
0:表示文件描述符,其中 0 表示标准输入。
buf:表示用于存储读取数据的缓冲区的地址。
0x200uLL:表示要读取的最大字节数。

可以看到buf的长度只有0x80,即可用栈大小只有108字节,但是read()并没有限制输入,显然存在栈溢出漏洞。
在这里插入图片描述
在Functions window可以看到有一个callsystem()函数,按F5反汇编可以看到这是一个系统调用,存在system(“/bin/sh”)
在这里插入图片描述
即使用栈溢出令返回地址指向该函数地址即可

题解

在这里插入图片描述
在这里插入图片描述

jarvisoj_level2_x64

步骤

检查文件,64位,开启NX保护
在这里插入图片描述
拖入64位IDA中打开,shift+F12查看发现存在system与/bin/sh,可用rop传参
在这里插入图片描述
查看主函数,双击vulnerable_function
在这里插入图片描述

vulnerable_function(argc, argv, envp);:这是对函数 vulnerable_function 的调用,其中 argc 是命令行参数的数量,argv 是命令行参数的数组,envp 是环境变量的数组。根据函数名的含义,vulnerable_function 可能是一个存在漏洞或不安全的函数。

return system("echo 'Hello World!'");:这是对 system 函数的调用,执行命令行命令。在这里,system 函数执行的命令是 echo 'Hello World!',即在标准输出打印字符串 "Hello World!"。

发现可栈溢出漏洞点
在这里插入图片描述
这段代码定义了一个名为 vulnerable_function 的函数,该函数存在缓冲区溢出的潜在漏洞。

在函数内部,定义了一个长度为 128 字节的字符数组 buf,并通过 read 函数从标准输入中读取最多 0x200 字节(512 字节)的数据存储到 buf 中。

然而,这段代码没有对输入数据的长度进行有效的检查,而 read 函数会将输入数据直接存储到 buf 中,导致可能发生缓冲区溢出。这意味着如果用户输入的数据超过 128 字节,就会覆盖 buf 数组后面的内存区域,可能导致程序崩溃或被恶意利用。

查看溢出量
在这里插入图片描述
查看system地址
在这里插入图片描述

查看/bin/sh地址
在这里插入图片描述
查看文件中rdi寄存器地址,用来传参
在这里插入图片描述

题解

在这里插入图片描述
在这里插入图片描述

ciscn_2019_en_2

步骤

检查文件,64位,只开启了栈不可执行
在这里插入图片描述
拖入64位IDA中打开,无bin无system
在这里插入图片描述
查看主函数
在这里插入图片描述
尝试运行对照意思
在这里插入图片描述
程序的逻辑大致如下:

打印欢迎信息,并调用函数begin()。

进入一个无限循环,循环内部有一个读取输入的循环,如果读取到的整数为2,重新调用函数begin()。

如果读取到的整数为3,打印"Bye!"并退出程序。

如果读取到的整数不是1或2或3,则打印"Something Wrong!"并退出程序。

如果读取到的整数为1,则调用函数encrypt(),然后再次调用函数begin()。
  • 因此,只有输入1有用,encrypt较为重要

下面看一下encrypt函数
在这里插入图片描述

这段代码定义了一个名为 encrypt 的函数,用于对输入的明文进行加密。

函数内部首先定义了一个长度为 48 字节的字符数组 s,并使用 memset 函数将其初始化为全零。接下来定义了一个名为 v3 的 __int16 变量。

在代码执行过程中,首先通过 puts 函数输出提示信息,要求用户输入明文。然后使用 gets 函数从标准输入读取用户输入的数据,并将其存储到 s 数组中。这里使用了不安全的 gets 函数,它无法限制输入的长度,可能导致缓冲区溢出。

接下来,通过一个循环遍历数组 s 中的每个字符,对字符进行加密操作。对于字母字符,根据其范围进行不同的异或操作。具体来说:

    如果字符在小写字母范围(97-122),则将其与十六进制值 0xE 进行异或操作。
    如果字符在大写字母范围(65-90),则将其与十六进制值 0xD 进行异或操作。
    如果字符在数字范围(48-57),则将其与十六进制值 0xC 进行异或操作。

最后,通过 puts 函数输出加密后的密文。

程序通过一个变量x来控制当前遍历到字符串s的哪个位置,每次循环先将x强制转换为无符号整型,赋值给变量v0。然后判断v0是否大于或等于s的长度strlen(s)

v0的值(即遍历加密前的明文字符串s的索引)大于等于s字符串(用户输入的0)的长度(即已经遍历完了整个字符串),则退出循环

strlen(s)是一个字符串函数,用于计算一个字符串的长度。如果v0已经等于或大于s字符串的长度,说明已经对整个字符串进行了加密操作,循环可以结束了

解题思路

  • get()存在栈溢出漏洞

  • 用\x00绕过strlen(),形成栈溢出

  • 泄露puts()地址,打常规ret2libc

题解

在这里插入图片描述

第一次使用 p.recvline() 是为了接收服务器端发送的数据,通常是用于确认连接建立成功后的欢迎消息或其他相关信息。

第二次使用 p.recvline() 是为了接收第一次 payload 执行后的输出结果。根据代码中的注释 p.recvline() 的作用是接收输出结果,因此在这里使用它来接收加密后的结果。

puts_plt = elf.sym["puts"]:这行代码获取可执行文件 elf 中 puts 函数的地址。sym 是 ELF 模块的一个属性,用于获取可执行文件中函数符号的地址。

__libc_start_main = elf.got["__libc_start_main"]:这行代码获取可执行文件 elf 中 __libc_start_main 符号在全局偏移表(GOT)中的地址。got 是 ELF 模块的一个属性,用于获取可执行文件中全局变量符号的地址。

main_addr = elf.sym['main']:这行代码获取可执行文件 elf 中 main 函数的地址。

在这里插入图片描述

not_the_same_3dsctf_2016

步骤

检查文件,32位,开启NX保护
在这里插入图片描述
拖入32位IDA中打开
查看主函数发现gets,存在栈溢出漏洞
在这里插入图片描述
shift+F12,发现flag.txt敏感字符串
在这里插入图片描述
找到调用的函数get_secret函数
在这里插入图片描述
代码的执行逻辑如下:

v0 = fopen(“flag.txt”, &unk_80CF91B);:这行代码打开名为 “flag.txt” 的文件,并将文件指针赋值给变量 v0。&unk_80CF91B 是一个未知的地址或变量,可能是用于存储文件句柄的位置。

fgets(&fl4g, 45, v0);:这行代码从打开的文件中读取最多 45 个字符,并将其存储在变量 fl4g 所指向的位置。

函数调用后,flag储存在fl4g里面,我们找到fl4g的位置
在这里插入图片描述
找到可以输出的write函数
在这里插入图片描述

题解

在这里插入图片描述

'a'* 0x2d: 这段代码使用字符 'a' 乘以 0x2d(十进制为45),生成了一个长度为45的字符串。这是为了填充数据,达到满足程序中的缓冲区溢出漏洞的目的。

p32(get_secret): p32() 函数是 pwn 库中的一个函数,它将一个32位整数转换为4字节的字符串。这里将 get_secret 函数的地址转换为4字节的字符串。

p32(write_addr): 同样地,将 write 函数的地址转换为4字节的字符串。

p32(0): 将整数0转换为4字节的字符串。这是用作 get_secret 函数的第一个参数,表示标准输入文件描述符的值。

p32(1): 将整数1转换为4字节的字符串。这是用作 write 函数的第一个参数,表示标准输出文件描述符的值。

p32(flag_addr): 将 flag 的地址转换为4字节的字符串。这是作为 write 函数的第二个参数,表示要写入数据的缓冲区地址。

p32(45): 将整数45转换为4字节的字符串。这是作为 write 函数的第三个参数,表示要写入的字节数。

在这里插入图片描述

others_shellcode

步骤

检查文件,32位开启NX保护地址随机化
在这里插入图片描述
查看主函数
在这里插入图片描述

  • getshell()主函数中直接给了后门函数,跟进查看。

在这里插入图片描述
直接连接即可

题解

在这里插入图片描述

ciscn_2019_n_8

步骤

检查文件,32位,保护全开
在这里插入图片描述
拖入32位IDA中打开,查看分析主函数,存在system(‘/bin/sh’)
在这里插入图片描述
很明显,只要var[13]==17就行,而scanf()又不限制长度,则直接全部输入17就行

题解

在这里插入图片描述

在这里插入图片描述

  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值